[转帖]关于nginx 反向代理upstream中的 keepalive配置

关于,nginx,反向,代理,upstream,keepalive,配置 · 浏览次数 : 0

小编点评

**关于nginx upstream** **3种类型** 1. **handler**:处理请求并将请求转发给后端服务器。 2. **filter**:与 upstream 同理,但处理请求并将其发送给下一个代理服务器。 3. **upstream**:用于实现和后端另外的服务器进行通信,它主要用于以下场景: * 负载均衡 * 轮询 * 缓存 **keepalive参数** keepalive 参数用于设置保留在每个 nginx worker 缓存中“已经与上游服务器建立的空闲连接”的最大连接数。 **示例** ```nginx upstream backend_servers { server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { listen 80; server_name example.com; location / { proxy_pass http://backend_servers; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` **注意** * keepalive 值应该大于等于 upstream 中 server 的数量,建议是 server 数的 2 倍。 * keepalive 用于实现轮询,它会尝试通过不同的服务器来处理请求,以减少负载。 * keepalive 可以用于缓存,但它不能用于缓存请求。

正文

一、关于nginx upstream

在nginx的模块中,分为3种类型,分别是handler,filter和upstream,其中upstream可以看做一种特殊的handler,它主要用来实现和后端另外的服务器进行通信,由于在nginx中全部都是使用非阻塞,并且是一个流式的处理,所以upstream的实现很复杂。

upstream顾名思义,真正产生内容的地方在”上游”而不是nginx,也就是说nginx是位于client和后端的upstream之间的桥梁,在这种情况下,一个upstream需要做的事情主要有2个:

第一个是当client发送http请求过来之后,需要创建一个到后端upstream的请求。

第二个是当后端发送数据过来之后,需要将后端upstream的数据再次发送给client。 

当使用nginx作为反向代理时,为了支持长连接,需要做到两点:

从client到nginx的连接是长连接

从nginx到server的连接是长连接

从HTTP协议的角度看,nginx在这个过程中,对于客户端它扮演着HTTP服务器端的角色。

而对于真正的服务器端(在nginx的术语中称为upstream)nginx又扮演着HTTP客户端的角色。

nginx 通常情况下都是用来当作一个反向代理,通常一个请求都需要经过client -> nginx -> backend_server这么几成关系。

通常情况下client -> nginx使用的 HTTP 1.1 或者 2.0 的协议,keep-alive 复用了 TCP 的连接,减少了 TCP 频发创建和销毁带来的性能损失。

但是默认情况下,nginx -> backend_server是 HTTP 1.0 的协议,并没有复用 TCP 的连接。

二、nginx upstream连接后端的两种方式:短连接和长连接

Keep-Alive即俗称的长连接,使客户端到服务端建立的连接持续有效,当对服务器发起后续请求时,Keep-Alive功能可以复用先前使用过的连接,减少了重新建立连接所需的开销。通常HTTP协议采用的是请求应答模式,客户端到服务端的一次请求完成了,它们之间的连接也随之关闭。在某些应用场景下,比如后端RESTful服务,就需要保持住连接,这时就可以启用HTTP Keep-Alive。

nginx 1.1.14版本以前与后端upstream服务器建立的都是短链接,即通过HTTP/1.0向后端发起连接,并把请求的”Connection” header设为”close”。这样nginx往upstream后端发请求时,也会消耗很多的时间与带宽,如果让nginx与upstream后端建立起长链接,从nginx发起的请求就可以挑选一个合适的长链接发往upstream后端服务器,这样即可以节省带宽,也可以提高响应速度。

其中keepalive指定最大保持的长连接数为1024.,同时要求HTTP协议版本指定为HTTP 1.1,以及清除掉HTTP头部Connection。

nginx upstream keepalive长连接的实现原理  

先每个进程需要一个connection pool,里面都是长连接,多进程之间是不需要共享这个连接池的。 

一旦与后端服务器建立连接,则在当前请求连接结束之后不会立即关闭连接,而是把用完的连接保存在一个keepalive connection pool里面,以后每次需要建立向后连接的时候,只需要从这个连接池里面找,如果找到合适的连接的话,就可以直接来用这个连接,不需要重新创建socket或者发起connect(),这样既省下建立连接时在握手的时间消耗,又可以避免TCP连接的slow start。如果在keepalive连接池找不到合适的连接,那就按照原来的步骤重新建立连接。

如果你的连接池的数控制在128,总共线程池内的线程数是128 * nginx worker ,但因为你要应对更多的并发请求,所以临时又加了很多的连接,但这临时的连接是短连接和长连接要看你的nginx版本。如果是长连接,那它如何被收回,两地保证,一点是它会主动去释放,另一点是keepalive timeout的时间。

说明:

1. 默认情况下 Nginx 访问后端都是用的短连接(HTTP1.0),一个请求来了,nginx 新开一个端口和后端建立连接,请求结束连接回收。如果像上面的配置一样设置了长连接,nginx 会接受客户端的请求,处理完成之后 Nginx 会「继续保持和后端的长连接」,如果并发请求超过了 keepalive 指定的最大连接数,nginx 会启动新的连接 来转发请求,新连接在请求完毕后关闭,而且新建立的连接是长连接,这可能会造成额外的问题,最后再说。

2. keepalive 指定的 数值 是nginx 每个 worker  连接后端的最大长连接数,而不是整个 nginx 的。 而且这里的后端指的是「所有的后端」,而不是每一个后端(已验证)。

3. HttpUpstreamModule 模块里面还有一共指令:least_conn,解释如下:

Specifies that a group should use a load balancing method where a request is passed to the server with the least number of active connections, taking into account weights of servers. If there are several such servers, they are tried in turn using a weighted round-robin balancing method.

翻译:指定服务器组的负载均衡方法,根据其权重值,将请求发送到「活跃连接数最少」的那台服务器。 如果这样的服务器有多台,那就采取有权重的轮转法进行尝试。

4. 一个现象,当 keepalive 设置小的时候,比如1,那么并发请求上去之后 nginx 会出现大量的 TIME_WAIT,而如果把 keepalive 关掉(proxy_http_version 1.1 和 proxy_set_header Connection “” 指令也去掉),那么 TIME_WAIT 就会出现在后端服务器了,后端用的是 tornado,相信 jetty 和 tomcat 也是一样。

nginx 和后端的长连接不够用时 nginx 会新建连接来处理新的请求,而我们的配置已经配置死了 HTTP1.1,建立连接后,后端认为是「长连接」而不会主动关闭连接(一般有个空闲超时),关闭连接由 nginx 来做了,所以 nginx 会出现大量的 TIME_WAIT。

而默认情况下,nginx 用 HTTP1.0 请求后端,后端处理完成后就主动关闭连接,所以 TIME_WAIT 在后端。

那么现在有新的问题:如果开启了长连接,而长连接又大量不够用,此时 Nginx 存在的 TIME_WAIT 可能会大量占用端口,导致端口用尽,如果用尽,后果很严重。

高并发环境下keepalive参数配置不当容易产生大量 TIME_WAIT,导致端口耗尽,服务异常。

keepalive值应该大于等于 upstream 中 server 的数量,建议是 server 数的 2 倍。

keepalive用于设置保留在每个 nginx worker 缓存中『已经与上游服务器建立的空闲连接』的最大连接数,如果超过这个值,最近最少使用的连接将被关闭。

nginx 官方建议这个值应该尽可能小,以便让上游服务器也能处理新进入的连接。但是『尽可能小』有些太模糊,如果配置不当会降低性能以及产生其他问题。

在大量短链接(或者大量分散用户)的请求场景下,同时 upstream 为轮询模式时,因为keepalive值小于 upstream server 数,upstream 新的空闲连接会从缓存中挤出老的空闲链接,导致keepalive在某种意义上失效。

三、参考

关于 client的长连接,server的长连接

https://skyao.gitbooks.io/learning-nginx/content/documentation/keep_alive.html

ngx_http_upstream_module

http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream

https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

http://mdounin.ru/hg/ngx_http_upstream_keepalive/rev/489c5d4318ff

关于nginx upstream长链接的介绍及具体的实现方式

 http://bollaxu.iteye.com/blog/900424

使用nginx keepalive,网站TPS性能提升对比

http://sohulinux.blog.sohu.com/180744817.html

记一次压测引起的nginx负载均衡性能调优

http://xiaorui.cc/archives/3495

Tuning NGINX for Performance

https://www.nginx.com/blog/tuning-nginx

Why does nginx proxy_pass close my connection?

https://stackoverflow.com/questions/46771389/why-does-nginx-proxy-pass-close-my-connection

nginx keepalive connections config example to upstream servers

https://bl.ocks.org/magnetikonline/4a2e68b2ce94bd0c945e

Enable Keepalive connections in Nginx Upstream proxy configurations

https://ma.ttias.be/enable-keepalive-connections-in-nginx-upstream-proxy-configurations

</article>

与[转帖]关于nginx 反向代理upstream中的 keepalive配置相似的内容:

[转帖]关于nginx 反向代理upstream中的 keepalive配置

一、关于nginx upstream 在nginx的模块中,分为3种类型,分别是handler,filter和upstream,其中upstream可以看做一种特殊的handler,它主要用来实现和后端另外的服务器进行通信,由于在nginx中全部都是使用非阻塞,并且是一个流式的处理,所以upstre

[转帖]nginx反向代理时保持长连接

https://www.cnblogs.com/liufarui/p/11075630.html ·【场景描述】 HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。 如果我们使用了nginx去作为反

【转帖】nginx变量使用方法详解-2

https://www.diewufeiyang.com/post/576.html 关于 Nginx 变量的另一个常见误区是认为变量容器的生命期,是与 location 配置块绑定的。其实不然。我们来看一个涉及“内部跳转”的例子: Bash server { listen 8080; locati

[转帖]关于线上环境CLOSE_WAIT和TIME_WAIT过高

https://www.cnblogs.com/Bozh/p/3752476.html 运维的同学和Team里面的一个同学分别遇到过Nginx在线上环境使用中会遇到TIME_WAIT过高或者CLOSE_WAIT过高的状态 先从原因分析一下为什么,问题就迎刃而解了。 首先是TIME_WAIT: 理解一

[转帖]兄弟们,时代变了

https://my.oschina.net/mengshuai/blog/615333 献给默默无闻,奋斗在第一线的苦逼程序员们! 起因 无意间翻看了之前在 Evernote 的关于服务器端记录的开发笔记,感触良多。 2009-2010 的上面记录的大多都是关于 Nginx、Apache、MySQ

[转帖]高性能 -Nginx 多进程高并发、低时延、高可靠机制在百万级缓存 (redis、memcache) 代理中间件中的应用

https://xie.infoq.cn/article/2ee961483c66a146709e7e861 关于作者 前滴滴出行技术专家,现任 OPPO 文档数据库 mongodb 负责人,负责 oppo 千万级峰值 TPS/十万亿级数据量文档数据库 mongodb 内核研发及运维工作,一直专注于

[转帖]Nginx 负载均衡 和 健康检查

https://www.jianshu.com/p/fbb0a81604d9 简介 从 nginx 下载, 到模块安装 关于为什么不使用 ngx_http_upstream_module 测试过 ngx_http_upstream_module 这个模块, 在应用稳定的情况下做做负载均衡还可以. 但

[转帖]nginx 启动、重启、关闭命令详解

https://www.jianshu.com/p/d70006f18a6d 作者:Gakki nginx 命令详解 输入命令:nginx -h nginx -h -?,-h:查看帮助 -v:显示版本信息并退出 -V:显示版本和配置选项信息,然后退出 -t:检测配置文件是否有语法错误,然后退出 -T

[转帖]Nginx超时timeout 设置

Nginx 超时配置,连接时间过长直接关闭连接,显示timeout http { #每个 TCP 连接最多可以保持多长时间 keepalive_timeout 60; #客户端向服务端发送一个完整的 request header client_header_timeout 10; #客户端发送服务端

[转帖]ingress nginx遇到502错误,(113 No route to host) while connecting to upstream

https://www.cnblogs.com/lizexiong/p/15358967.html 1.背景 首先谈一下背景环境,出现文章标题的出错是公司的tke(腾讯云k8s,当然问题和腾讯云k8s集群没有关系),首先分为dev集群环境和生产集群环境,出现问题是在很早期创建的dev环境。 问题报错