我有一个REST终结点,该终结点基本上只从发出呼叫的计算机上上传文件到我们的一个云VM。

当我从客户端VM用cURL拨打电话时,大约需要10秒钟才能上传100兆字节的文件。

当我从客户端VM用jaxrs client进行呼叫时,大约需要2m50s来上传100兆字节的文件。

客户代码。我玩过创建自定义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);


我的问题是:什么可能导致网络吞吐量如此巨大的差异?我是否可以在Java端打开SocketOptions的任何拨号盘,这可能有助于解决此问题?

任何和所有上下文/帮助将不胜感激!

相关详细信息:


jre11.0.6
TLSv1.2(已与CBC和GCM密码套件一起试用,两者均未更改)
我已经修改了TCP_NODELAY,SO_SNDBUF和SO_RCVBUF(通过SSLSocketFactory)。 TCP_NODELAY的性能提高了约10%,而更改SO_SNDBUF和SO_RCVBUF则没有任何影响。


更新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,它仍然很慢。而且没有Conscrypt提供程序的普通Feign客户端仍然很慢。

可能还值得注意的是,我已经尝试了GCM和CBC密码套件,它们根本不影响性能(无论设置了哪个客户端或Conscrypt提供程序)。

更新2

因此,我已经将JRE更新为11.0.6,并且通过该更改,我不再需要启用Conscrypt才能使Feign请求更快。我已经捕获了假请求的JFR(快速)和JaxRsClient请求(慢)。

这是Feign上的Socket I / O(高级HttpURLConnection)请求
java - JaxRsClient(OkHttpClient)比Feign(HttpURLConnection)或cURL慢得多-LMLPHP

这是JaxRsClient(位于引擎盖下的OkHttpClient)请求上的Socket I / O
java - JaxRsClient(OkHttpClient)比Feign(HttpURLConnection)或cURL慢得多-LMLPHP

这些是使用Java Mission Control查看的。有趣的是,慢速请求只是套接字上的大量读取(〜200),而快速请求是3次读取和15次写入。就像进行完整性检查一样,我还针对这两个请求在CBC和GCM密码套件之间进行了切换,两者之间没有真正的区别。

最佳答案

因此,对于这个答案我没有更深入的了解,我有点不满意,但是确实如此。

JaxRsClient正在协商HTTP / 2。我不确定到底发生了什么,但是如果未启用GCM密码,则唯一允许的协议应该是HTTP1.1。这是纠正此问题的PR:

https://github.com/palantir/conjure-java-runtime/commit/e52efdc1f66a52c3ee9112ecaae7bb40ac799224

如果未启用GCM密码,则该更改之后,JaxRsClient将不会协商HTTP / 2。在HTTP / 1.1上,它与cURLFeign匹配以提高速度。

09-27 21:39
查看更多