Apache Camel https4 客户端对 keepAlive=true 的多个请求不使用相同的 tcp 端口
Apache Camel https4 client not using the same tcp port for multiple requests with keepAlive=true
您好,我正在使用 Apache camel http4 组件 发送带有 keepAlive=true
的 https 请求,但是当我看到 netstat
发送多个请求后,我看到每个请求都会打开一个新的 TCP 端口 到对等方。
我觉得这不应该是 keepAlive transactions 的通常行为,为什么同一个 TCP 端口没有被 reused 用于与服务器通信以及如何才能如果可以的话,那就实现了。
您是否已经分析了 HTTP 响应 headers 以检查是否考虑了 KeepAlive 以及超时值。
预期响应示例:
HTTP/1.1 200 OK
Connection: Keep-Alive
Keep-Alive: timeout=10, max=20
Content-Type: text/html; charset=UTF-8
Date: ...
Content-Length: ...
事实证明这不是保活问题;连接实际上保持正常。问题在于,作为默认 PoolingHttpClientConnectionManager 管理的池的一部分的连接没有被重用。通过为 Apache 的 HttpClient(在后台使用)启用日志记录,可以很容易地看到这两件事:
正在使用 Keep-Alive:
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "HTTP/1.1 200 OK[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Keep-Alive: timeout=5, max=300[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Server: Apache-Coyote/1.1[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Encoding: gzip[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Vary: Accept-Encoding[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Cluster-Id: A[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Date: Wed, 19 Dec 2018 06:59:17 GMT[\r][\n]"
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Type: text/xml[\r][\n]"
2018/12/19 07:59:17:471 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Length: 239[\r][\n]"
2018/12/19 07:59:17:471 CET [DEBUG] 电线 - http-outgoing-7 << “[\r][\n]”
连接未被重用:
2018/12/19 08:00:08:240 CET [DEBUG] PoolingHttpClientConnectionManager - 连接请求:[route: {s}->https://someurl.com:443][total keep alive: 1;分配的路线:1 of 1;总分配:1 of 1]
2018/12/19 08:00:08:240 CET [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-7:关闭连接
2018/12/19 08:00:08:242 CET [DEBUG] PoolingHttpClientConnectionManager - 连接租用:[id: 8][route: {s}->https://someurl.com:443][total keep alive: 0;分配的路线:1 of 1;总分配:1 of 1]
请注意,通过在启动时将一些参数传递给 JVM,可以轻松地为 HttpClient 启用日志记录。
那么,为什么连接没有被重用呢?这是因为正在使用 SSL 并且 Apache 的 HttpClient 使用的 PoolingHttpClientConnectionManager 不允许重用连接,以防现有连接的用户主体与请求的连接不同(由 DefaultUserTokenHandler 提供便利)。另见例如这个 Whosebug post。解决方案是实现自定义 UserTokenHandler(如果足够,则使用 NullTokenHandler)并相应地配置 HttpClientBuilder。
您好,我正在使用 Apache camel http4 组件 发送带有 keepAlive=true
的 https 请求,但是当我看到 netstat
发送多个请求后,我看到每个请求都会打开一个新的 TCP 端口 到对等方。
我觉得这不应该是 keepAlive transactions 的通常行为,为什么同一个 TCP 端口没有被 reused 用于与服务器通信以及如何才能如果可以的话,那就实现了。
您是否已经分析了 HTTP 响应 headers 以检查是否考虑了 KeepAlive 以及超时值。
预期响应示例:
HTTP/1.1 200 OK
Connection: Keep-Alive
Keep-Alive: timeout=10, max=20
Content-Type: text/html; charset=UTF-8
Date: ...
Content-Length: ...
事实证明这不是保活问题;连接实际上保持正常。问题在于,作为默认 PoolingHttpClientConnectionManager 管理的池的一部分的连接没有被重用。通过为 Apache 的 HttpClient(在后台使用)启用日志记录,可以很容易地看到这两件事:
正在使用 Keep-Alive:
2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "HTTP/1.1 200 OK[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Keep-Alive: timeout=5, max=300[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Server: Apache-Coyote/1.1[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Encoding: gzip[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Vary: Accept-Encoding[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Cluster-Id: A[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Date: Wed, 19 Dec 2018 06:59:17 GMT[\r][\n]" 2018/12/19 07:59:17:470 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Type: text/xml[\r][\n]" 2018/12/19 07:59:17:471 CET [DEBUG] 电线 - http-outgoing-7 << "Content-Length: 239[\r][\n]" 2018/12/19 07:59:17:471 CET [DEBUG] 电线 - http-outgoing-7 << “[\r][\n]” 连接未被重用:
2018/12/19 08:00:08:240 CET [DEBUG] PoolingHttpClientConnectionManager - 连接请求:[route: {s}->https://someurl.com:443][total keep alive: 1;分配的路线:1 of 1;总分配:1 of 1] 2018/12/19 08:00:08:240 CET [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-7:关闭连接 2018/12/19 08:00:08:242 CET [DEBUG] PoolingHttpClientConnectionManager - 连接租用:[id: 8][route: {s}->https://someurl.com:443][total keep alive: 0;分配的路线:1 of 1;总分配:1 of 1] 请注意,通过在启动时将一些参数传递给 JVM,可以轻松地为 HttpClient 启用日志记录。
那么,为什么连接没有被重用呢?这是因为正在使用 SSL 并且 Apache 的 HttpClient 使用的 PoolingHttpClientConnectionManager 不允许重用连接,以防现有连接的用户主体与请求的连接不同(由 DefaultUserTokenHandler 提供便利)。另见例如这个 Whosebug post。解决方案是实现自定义 UserTokenHandler(如果足够,则使用 NullTokenHandler)并相应地配置 HttpClientBuilder。