У меня есть конечная точка REST, которая в основном просто загружает файл с компьютера, выполняющего вызов, на одну из наших облачных виртуальных машин.
Когда с клиентской виртуальной машины я выполняю вызов с cURL
, она Загрузка файла размером 100 мегабайт занимает ~ 10 с.
Когда с клиентской виртуальной машины я выполняю вызов с клиентом jaxrs , загрузка файла размером 100 мегабайт занимает ~ 2 мкс.
Код клиента. Я играл с созданием собственной SSLSocketFactory, которая позволяет мне поворачивать ручки на SocketOptions, но этого нет в приведенном ниже фрагменте.
SslConfiguration sslConfig = SslConfiguration.of(Paths.get(trustStorePath));
ClientConfiguration config = ClientConfigurations.of(
ImmutableList.of(<uri>),
SslSocketFactories.createSslSocketFactory(sslConfig),
SslSocketFactories.createTrustManagers(sslConfig));
MyService service = JaxRsClient.create(
MyService.class,
UserAgent.of(UserAgent.Agent.of("my-user-agent", "1.0.0")),
new HostMetricsRegistry(),
config);
service.fooBar(...);
Конечная точка хоста (абстрактное определение)
@POST
@Path("path/foo")
@Consumes(MediaType.WILDCARD)
void fooBar(
@HeaderParam(HttpHeaders.AUTHORIZATION) AuthHeader authHeader,
InputStream fileData);
Мой (ые) вопрос (ы) заключается в следующем: что может вызвать такое огромное несоответствие пропускной способности сети? Есть ли какие-либо наборы, которые я могу включить для SocketOptions на стороне Java, которые могут помочь решить эту проблему?
Любой контекст и помощь будут приветствоваться!
Соответствующие сведения:
- jre11.0.6
- TLSv1.2 (пробовал с обоими наборами шифров CB C и GCM, без изменений ни для одного из них)
- Я возился с TCP_NODELAY, SO_SNDBUF и SO_RCVBUF (через SSLSocketFactory). TCP_NODELAY дал ~ 10% улучшения производительности, в то время как изменение SO_SNDBUF и SO_RCVBUF ни на что не повлияло.
UPDATE 1
Я переключился на использование ванильного клиента Feign (HttpsURLConnection, под капот):
MyService service = Feign.builder()
.client(new Client.Default(new KeepAliveSslSocketFactory(sslContext.getSocketFactory()), null))
.contract(new JAXRSContract())
.encoder(
new InputStreamDelegateEncoder(
new TextDelegateEncoder(
new CborDelegateEncoder(
new ObjectMapper(),
new ConjureFeignJacksonEncoder(objectMapper)))))
.target(MyService.class, <url>);
и установите следующий блок в начале класса:
static {
Security.insertProviderAt(Conscrypt.newProvider(), 1);
}
Эти два изменения вместе (и клиент Feign, и поставщик Conscrypt) сделали java вызов выполняется аналогично cURL
. Однако, если я добавлю провайдер Conscrypt в исходный JaxRsClient, он все равно будет медленным. И ванильный клиент Feign без провайдера Conscrypt также все еще работает медленно.
Стоит также отметить, что я пробовал комплекты шифров GCM и CB C, и они не влияют на производительность все (независимо от того, какой клиент или поставщик Conscrypt установлены).
ОБНОВЛЕНИЕ 2
Итак, я обновил JRE до 11.0.6, и с этим изменением мне больше не нужно включать Conscrypt для быстрого выполнения запроса Feign. Я захватил JFR симметричного запроса (быстрый) и запроса JaxRsClient (медленный).
Это сокет ввода-вывода для запроса Feign (HttpURLConnection под капотом) ![This is the socket I/O on the Feign (HttpURLConnection) request](https://i.stack.imgur.com/wCNPc.png)
Это сокет ввода-вывода на запросе JaxRsClient (OkHttpClient под капотом) ![This is the socket I/O on the JaxRsClient (OkHttpClient) request](https://i.stack.imgur.com/Fylkt.png)
Они были просмотрены с помощью Java Миссия Контроль. Интересно то, что медленный запрос - это всего лишь тонна операций чтения в сокете (~ 200), а быстрый запрос - 3 операции чтения и 15 операций записи. В качестве проверки работоспособности я также переключился между наборами шифров CB C и GCM в обоих этих запросах, без реальной разницы между ними.