首页 > 编程知识 正文

关于 HTTP 长连接

时间:2023-05-03 05:09:25 阅读:273099 作者:4396

使用长连接能够减少建立销毁连接的消耗,三次握手、四次挥手对性能影响是很大的。一般 RPC 如 Dubbo 默认都是长连接的,HTTP 1.1 之上也可以支持长连接了,HTTP 2.0 也支持了单一长连接的多路复用。

一般 HTTP 服务前面都会挂 nginx 做负载均衡,那么长连接的设置也分为从客户端到 nginx、从 nginx 到服务端两部分。

如果使用 Java 的 apache HTTPClient 可以通过设置 ConnectionKeepAliveStrategy 和协议为 HTTP1.1 来使用长连接,对于 4.2.x 版本设置方法如下所示:

private static final ConnectionKeepAliveStrategy KEEP_ALIVE_STRATEGY = new ConnectionKeepAliveStrategy() { public long getKeepAliveDuration(HttpResponse response, HttpContext context) { HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { // 如果 response header 里有 Keep-Alive:timeout 参数,则使用其值作为长连接超时时间 return Long.parseLong(value) * 1000; } catch (NumberFormatException ignore) { } } } return 30 * 1000; // 30s } }; HttpParams params = new BasicHttpParams(); // 指定使用 http1.1,1.1里默认使用长连接 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); //创建连接池 PoolingClientConnectionManager cm = new PoolingClientConnectionManager(registry, 1, TimeUnit.MINUTES); cm.setDefaultMaxPerRoute(10); cm.setMaxTotal(200); httpClient = new DefaultHttpClient(cm, params); // 设置超时时间 httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 100); httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 100); httpClient.getParams().setParameter(ClientPNames.CONN_MANAGER_TIMEOUT, 100); httpClient.setKeepAliveStrategy(KEEP_ALIVE_STRATEGY);

在 NGINX 请求后端服务时启用长连接需要配置:

proxy_http_version 1.1; proxy_set_header Connection "";keepalive_timeout 120s 120s;keepalive_requests 10000;

关于长连接,有两个参数需要注意:

keepalive_timeout:连接不活跃多长时间后断开,如果服务端(nginx)设置的时间比客户端短的话,可能会导致客户端请求异常。前提是 HTTPClient 都 http.connection.stalecheck 参数置为 false,也就是不在请求前检查连接的有效性。keepalive_requests:用于设置一个keep-alive连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭。nginx 和 Tomcat 上默认都是100,对于 QPS 较高的应用来说 100 有些太小了。

以上两个参数在 nginx、服务端都有,当 QPS 比较高时就需要做适当调整以减少或避免连接都频繁断开、建立。如果服务端使用的 Tomcat 容器,可以在 server.xml 文件里修改配置。

在 Spring Boot 2.x 里修改长连接的配置方法如下所示:

@Configurationpublic class TomcatCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { factory.addConnectorCustomizers(connector -> { AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) connector.getProtocolHandler(); protocol.setMaxKeepAliveRequests(10000); protocol.setKeepAliveTimeout(60000);// 长连接超时时间,单位 ms }); }}

上面提到 HTTPClient 的 http.connection.stalecheck 参数用于设置是否在发送请求之前检查连接有效性,如果每次发请求都检查对性能影响也会较大,可以去掉该参数。但是去掉之后,在连接被 NGINX 关闭后依然发请求则会导致 NoHttpResponseException 异常,需要对其进行特殊处理,进行适当的重试。

资料

nginx 优化

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。

  •  标签:  
  • HTTP