nginx反向代理下的长连接

embedded/2024/10/15 17:57:30/

一、nginx使用场景

大型应用架构中,一般会使用nginx反向代理,分为三层:

1.调用层,浏览器或APP;

2.中间层,反向代理nginx

3.服务层,server一般是apche、tomcat

请求调用过程:

1.浏览器/app发起请求

2.DNS解析网址为ip地址

3.通过外网ip访问nginx

4.nginx发送请求给内网ip的server

上面架构,要想支持全链路的长连接,需要做到两点:

1.从client到nginx的连接是长连接;

2.从nginx到server的连接是长连接;

二、长连接设置

1.client到nginx的长连接:

由于目前浏览器默认使用HTTP/1.1,请求header中默认设置Connection:keep-alive,所以只需在nginx配置中做如下配置:

http {keepalive_timeount 120s 120s;keepalive_requests 10000;
}
#语法
keepalive_timeout timeout [header_timeout]
第一个参数(timeout):设置keep_alive客户端(浏览器)连接在服务端(nginx端)保持开启的超时值(默认75s);值为0会禁用keep_alive客户端连接;
第二个参数(header_timeout):可选,在响应的header中设置值“Keep-Alive:timeout=time”;通常可以不用设置;
keepalive_requests这个配置项用于设置一个keep-alive连接上可以服务的请求最大数量,当达到配置的最大请求数时,连接会被关闭,默认值为100.具体过程时指一个keep-alive连接建立之后,nginx会为这个连接设置一个计数器,记录这个长连接上已经接收并处理的客户端请求的数量,一旦达到设置的最大值时,nginx会强行关闭这个长连接,此时如果客户端有新请求,就需要重新建立新的长连接。
注:在QPS较高的场景下,服务端需要将keepalive_requests设置大一些,默认数值就不够了,否则服务端可能会出现大量的TIME_WAIT状态的TCP连接数异常!另外nginx(version 1.15.3)在Upstream内增加了keepalive_requests配置项,默认值也是100,也是需要手动设置,而且这两个数量可以不一致,一般服务端要设置的大些,因为多数情况是一个nginx代理对应多个服务端。

2.nginx和server的长连接

默认情况下,nginx访问后端都是用的短连接(HTTP/1.0)一个请求来了,nginx会新开一个端口和后端建立连接,后端执行完毕后主动关闭该tcp连接。为了让nginx和后端server(nginx称之为upstream)之间保持长连接,典型设置如下:
 

http {upstream http_backend {server 192.168.2.154:8080;server 192.168.2.109:8080;keepalive 32;                  # 长连接缓存池大小为32keepalive_timeout  120s;       # 长连接失效时间keepalive_requests 2000;       # 每条长连接最大复用请求数为2000}server {location /http/ {proxy_pass http://http_backend;proxy_http_version 1.1;        # 启用HTTP/1.1版本与被代理服务器建立连接proxy_set_header Connection "Keep-Alive";  # 设置发送被代理服务器请求头属性字段Connection}}
nginx 与被代理服务器间建立的长连接是通过启用 HTTP/1.1 版本协议实现的。由于 HTTP 代理模块默认会将发往被代理服务器的请求头属性字段 Connection 的值设置为 Close,因此需要通过配置指令设置请求头属性字段 Connection 的内容为“Keep-Alive”或者空值。
另外upstream中的keepalive_timeout和keepalive_requests参数与上面的含义一样,不做过多解析,需要重点关注keepalive参数,他的含义是指设置到upstream服务器的空闲keepalive连接的最大数,当这个数量被突破时,最近最少使用的连接将被关闭,另外这个参数不会限制一个nginx worker进程到upstream服务器连接的总数量,有点像线程池中的核心线程数。
注:keepalive参数设置一定要合理,尤其对于QPS比较高的场景,推荐做一下估算,根据QPS和平均响应时间大概计算出需要长连接的数量,尽量避免系统运行时产生连接数量的反复震荡,比如keepalive设置为10,前一秒系统qps较低,只需50个长连接,用完立马关闭其中50-10=40个连接,而后一秒系统qps突增,需要150个连接,空缺了150-10=140个连接,此时nginx不得不新建140个新连接来满足要求。

三、问题总结

综上所述,nginx反向代理的情况下,tcp长连接设置完成。在实际系统应用长连接的场景中,可能会出现大量TIME_WAIT的情况,这里简单做个总结:

1.导致nginx端出现大量TIME_WAIT的情况有两种:

    a.keepalive_requests设置比较小,高并发下超过此值后nginx会强制关闭和客户端的长连接;(主动关闭连接后导致nginx出现TIME_WAIT)

    b.keepalive设置比较小(空闲数太小),导致高并发下nginx会频繁出现连接数震荡,不停的关闭、开启和后端server的长连接;

2.导致后端server端出现大量TIME_WAIT的情况:

   nginx没有打开和后端的长连接,即:没有设置proxy_http_version 1.1和proxy_set_header Connection "Keep-Alive",从而导致后端server每次请求后就关闭连接,高并发下就会出现server端的大量TIME_WAIT.


http://www.ppmy.cn/embedded/127993.html

相关文章

MySQL 【日期】函数大全(三)

DATEOFYEAREXTRACTFROM_DAYSFROM_UNIXTIMEHOURLAST_DAYLOCALTIMELOCALTIMESTAMP 1、DATEOFYEAR DATEOFYEAR(expr) :返回一个从 1 到 366 代表给定日期是一年中的第几天的数字。 如果指定的表达式不是一个合法的日期或者日期时间,DAYOFYEAR() 函数将返回…

python中的工具

一、Scapy Scapy是python语言编写的工具,也是一个强大的交付式数据包处理程序,能够伪造或者解码大量的网络协议数据包,能够发送、嗅探、剖析和伪造网络数据包,如端口扫描、路由跟踪、探测、攻击或网络发现等。 python3环境下&am…

编码风格之(7)C++语言规范(Google风格)2

编码风格之(6)C命名规范(Google风格) Author: Once Day Date: 2024年10月9日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 本文档翻译自《Google C Style Guide》&#…

10.10 LeetCode 3285 3280 3274

目录 leetcode 3285leetcode 3280leetcode 3274 leetcode 3285 class Solution { public:vector<int> stableMountains(vector<int>& height, int threshold) {vector<int> ans;for(int i1; i<height.size(); i){if(height[i-1] > threshold){ //…

2.1 机器学习--KNN算法(分类)

目录 1.KNN算法 1.1 算法介绍 1.2 算法原理 1.3 API介绍 1.4 代码实例 1.4.1.KNN电影分类 1.4.2.约会数据预测 1.KNN算法 1.1 算法介绍 本章节我们来学习一种分类算法&#xff0c;KNN&#xff08;K- Nearest Neighbor&#xff09;法&#xff0c;即 K 最邻近法&#xf…

【SSM详细教程】-02-Spring容器IOC详解

精品专题&#xff1a; 01.《C语言从不挂科到高绩点》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482 02. 《SpringBoot详细教程》课…

StringEntity 用于将字符串内容作为 HTTP 请求实体(请求体)

StringEntity 类是 Apache HttpClient 库中的一个类&#xff0c;它用于将字符串内容作为 HTTP 请求实体&#xff08;请求体&#xff09;。这个类非常适合用于发送 JSON、XML 或其他需要以字符串形式发送的数据。以下是 StringEntity 类的一些常用方法和代码案例&#xff1a; …

场内期权交易规则及方式详解

场内期权是一种在场内二级市场交易的金融衍生品&#xff0c;场内期权就是赋予持有者在未来某个时间以特定价格买入或卖出某种资产的权利&#xff0c;但不是义务。场内期权在交易所内交易&#xff0c;具有标准化合约、高流动性和透明度。 场内期权的交易规则 1. 合约标准化&am…