nginx对skywalking grpc协议的负载nginx长连接和短连接概念
长连接与短连接的区别,主要在于长连接模式下,不需要频繁的建立起tcp连接,同时也不需要频繁关闭,节省了这部分资源的消耗。这种情况下比较适合频繁请求的场景下。
https://blog.csdn.net/qq_37674086/article/details/109682919
具体可以看今天看上面的这篇博客
一.TCP长连接与短连接
TCP在真正的读写操作之前,server与client之间必须建立一个连接,
当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,
连接的建立通过三次握手,释放则需要四次握手,
所以说每个连接的建立都是需要资源消耗和时间消耗的。
1. TCP短连接
模拟一种TCP短连接的情况:
client 向 server 发起连接请求
server 接到请求,双方建立连接
client 向 server 发送消息
server 回应 client
一次读写完成,此时双方任何一个都可以发起 close 操作
在步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。
从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!
2. TCP长连接
再模拟一种长连接的情况:
client 向 server 发起连接
server 接到请求,双方建立连接
client 向 server 发送消息
server 回应 client
一次读写完成,连接不关闭
后续读写操作...
长时间操作之后client发起关闭请求
3. TCP长/短连接操作过程
3.1 短连接的操作步骤是:
建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
3.2 长连接的操作步骤是:
建立连接——数据传输...(保持连接)...数据传输——关闭连接
4. TCP长/短连接的优点和缺点
长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
对于频繁请求资源的客户来说,较适用长连接。
client与server之间的连接如果一直不关闭的话,会存在一个问题,
随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,
如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;
如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,
这样可以完全避免某个蛋疼的客户端连累后端服务。
短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。
但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。
5. TCP长/短连接的应用场景
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
每个TCP连接都需要三次握手,这需要时间,如果每个操作都是先连接,
再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,
再次处理时直接发送数据包就OK了,不用建立TCP连接。
例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,
而且频繁的socket 创建也是对资源的浪费。
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,
而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,
如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,
那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
二.http长连接与短连接
HTTP的长连接和短连接 - 烛秋 - 博客园
HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。
http长连接标志:
三.tcp的长连接与http的长连接
TCP的keep alive是检查当前TCP连接是否活着;HTTP的Keep-alive是要让一个TCP连接活久点。它们是不同层次的概念。
TCP keep alive的表现:
当一个连接“一段时间”没有数据通讯时,一方会发出一个心跳包(Keep Alive包),如果对方有回包则表明当前连接有效,继续监控。
这个“一段时间”可以设置。
四.Nginx长连接代理
nginx反向代理时保持长连接 - 流年的夏天 - 博客园
HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
如果我们使用了nginx去作为反向代理或者负载均衡,从客户端过来的长连接请求就会被转换成短连接发送给服务器端。
为了支持长连接,我们需要在nginx服务器上做一些配置。
使用nginx时,想要做到长连接,我们必须做到以下两点:
从client到nginx是长连接
从nginx到server是长连接
对于客户端而言,nginx其实扮演着server的角色,反之,之于server,nginx就是一个client。
————————————————
版权声明:本文为CSDN博主「python开发笔记」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37674086/article/details/109682919
https://www.jb51.net/article/198630.htm
【场景描述】
HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
如果我们使用了nginx去作为反向代理或者负载均衡,从客户端过来的长连接请求就会被转换成短连接发送给服务器端。
为了支持长连接,我们需要在nginx服务器上做一些配置。
·【要求】
使用nginx时,想要做到长连接,我们必须做到以下两点:
- 从client到nginx是长连接
- 从nginx到server是长连接
对于客户端而言,nginx其实扮演着server的角色,反之,之于server,nginx就是一个client。
·【保持和 Client 的长连接】
我们要想做到Client与Nginx之间保持长连接,需要:
- Client发送过来的请求携带"keep-alive"header。
- Nginx设置支持keep-alive
【HTTP配置】
默认情况下,nginx已经开启了对client连接的 keepalive 支持。对于特殊场景,可以调整相关参数。
http { keepalive_timeout 120s; #客户端链接超时时间。为0的时候禁用长连接。 keepalive_requests 10000; #在一个长连接上可以服务的最大请求数目。 #当达到最大请求数目且所有已有请求结束后,连接被关闭。 #默认值为100 }
大多数情况下,keepalive_requests = 100也够用,但是对于 QPS 较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT。 QPS=10000 时,客户端每秒发送 10000 个请求 (通常建立有多个长连接),每个连接只能最多跑 100 次请求,意味着平均每秒钟就会有 100 个长连接因此被 nginx 关闭。 同样意味着为了保持 QPS,客户端不得不每秒中重新新建 100 个连接。 因此,如果用netstat命令看客户端机器,就会发现有大量的TIME_WAIT的socket连接 (即使此时keep alive已经在 Client 和 NGINX 之间生效)。 ·【保持和Server的长连接】 想让Nginx和Server之间维持长连接,最朴素的设置如下:
http { upstream backend { server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s; keepalive 300; // 这个很重要! } server { listen 8080 default_server; server_name ""; location / { proxy_pass http://backend; proxy_http_version 1.1; # 设置http版本为1.1 proxy_set_header Connection ""; # 设置Connection为长连接(默认为no)} } } }
【upstream配置】 upstream中,有一个参数特别的重要,就是keepalive。 这个参数和之前http里面的 keepalive_timeout 不一样。 这个参数的含义是,连接池里面最大的空闲连接数量。 不理解?没关系,我们来举个例子: 场景: 有一个HTTP服务,作为upstream服务器接收请求,响应时间为100毫秒。 要求性能达到10000 QPS,我们需要在nginx与upstream服务器之间建立大概1000条HTTP请求。(1000/0.1s=10000) 最优情况: 假设请求非常的均匀平稳,每一个请求都是100ms,请求结束会被马上放入连接池并置为idle(空闲)状态。 我们以0.1s为单位: 1. 我们现在keepalive的值设置为10,每0.1s钟有1000个连接 2. 第0.1s的时候,我们一共有1000个请求收到并释放 3. 第0.2s的时候,我们又来了1000个请求,在0.2s结束的时候释放 请求和应答都比较均匀,0.1s释放的连接正好够用,不需要建立新连接,且连接池中没有idle状态的连接。 第一种情况: 应答非常平稳,但是请求不平稳的时候 4. 第0.3s的时候,我们只有500个请求收到,有500个请求因为网络延迟等原因没有进来 这个时候,Nginx检测到连接池中有500个idle状态的连接,就直接关闭了(500-10)个连接
5. 第0.4s的时候,我们收到了1500个请求,但是现在池里面只有(500+10)个连接,所以Nginx不得不重新建立了(1500-510)个连接。
如果在第4步的时候,没有关闭那490个连接的话,只需要重新建立500个连接。
第二种情况:
请求非常平稳,但是应答不平稳的时候
4. 第0.3s的时候,我们一共有1500个请求收到
但是池里面只有1000个连接,这个时候,Nginx又创建了500个连接,一共1500个连接
5. 第0.3s的时候,第0.3s的连接全部被释放,我们收到了500个请求
Nginx检测到池里面有1000个idle状态的连接,所以不得不释放了(1000-10)个连接
造成连接数量反复震荡的一个推手,就是这个keepalive 这个最大空闲连接数。
上面的两种情况说的都是 keepalive 设置的不合理导致Nginx有多次释放与创建连接的过程,造成资源浪费。
keepalive 这个参数设置一定要小心,尤其是对于 QPS 要求比较高或者网络环境不稳定的场景,一般根据 QPS 值和 平均响应时间能大致推算出需要的长连接数量。
然后将keepalive设置为长连接数量的10%到30%。
【location配置】
http { server { location / { proxy_pass http://backend; proxy_http_version 1.1; # 设置http版本为1.1 proxy_set_header Connection ""; # 设置Connection为长连接(默认为no) } } }
HTTP 协议中对长连接的支持是从 1.1 版本之后才有的,因此最好通过 proxy_http_version 指令设置为 1.1。
HTTP1.0不支持keepalive特性,当没有使用HTTP1.1的时候,后端服务会返回101错误,然后断开连接。
而 "Connection" header 可以选择被清理,这样即便是 Client 和 Nginx 之间是短连接,Nginx 和 upstream 之间也是可以开启长连接的。
【另外一种高级方式】
http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream backend { server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s; keepalive 300; } server { listen 8080 default_server; server_name ""; location / { proxy_pass http://backend; proxy_connect_timeout 15; #与upstream server的连接超时时间(没有单位,最大不可以超过75s) proxy_read_timeout 60s; #nginx会等待多长时间来获得请求的响应 proxy_send_timeout 12s; #发送请求给upstream服务器的超时时间 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } } }
https://segmentfault.com/a/1190000039803158?utm_source=sf-similar-article
nginx与后端服务长短链接配置性能差异比较
有一个服务在qps几万的时候偶尔出现请求timeout情况,因为该机器作为p2p下载的文件源站和服务端,之前流量会被打满时会出现请求timeout的情况。但是经过优化p2p后最近的流量几乎都不会超过1GB/s,查看日志发现qps在2万以上就偶尔出现timeout的情况,很是奇怪。毕竟golang原生的http服务写个hello word放在服务器都可以几十万qps的。
该服务是通过nginx托管文件作为下载源,并转发客户端下载分片请求至后端服务,使用wrk简单压测返回简单信息的接口发现qps只有4w+,且出现部分timeout的错误。使用wrk直接请求服务后端接口,qps却有30w+,wrk直接请求nginx返回简单字符串qps也有30W+,看来问题出在nginx配置上!
查看配置后发现原来nginx是直接转发至后端,未配置长连接,那么一个请求来到后的过程是client->nginx->server要建立两次链接。
于是在本地做了几个实验验证了一下猜想。
使用的是mbp13 2020,4C8T,设定nginx worker数量为1,golang后端也只限制单核,电脑散热不太行 所以qps有所波动,但也能反应问题。
主要配置为下:
1. nginx直接返回字符串 2. golang http server 返回字符串 3. nginx+后端短连接 4. nginx+后端长链接
nginx后端配置如下
我还有这个。1
# 长连接配置 upstream go_http{ server 127.0.0.1:13002; keepalive 300; } # 短连接配置 upstream go_http_short{ server 127.0.0.1:13002; } server { listen 13001; server_name helloWorld; location /nginx { default_type text/html ; return 200 "hello nginx"; } #与后端保持长连接 location /go { proxy_pass http://go_http; proxy_http_version 1.1; proxy_set_header Connection ""; } location /go_short{ proxy_pass http://go_http_short; } }
使用wrk压测
# 1. nginx直接返回字符串
wrk -t 2 -c 100 -d 10s -H "Connection:Close" http://127.0.0.1:13001/nginx
# 2. go http服务直接返回字符串
wrk -t 2 -c 100 -d 10s -H "Connection:Close" http://127.0.0.1:13002/go
# 3. nginx和go http保持长连接
wrk -t 2 -c 100 -d 10s -H "Connection:Close" http://127.0.0.1:13001/go
# 4. nginx和go http采用短连接
wrk -t 2 -c 100 -d 10s -H "Connection:Close" http://127.0.0.1:13001/go_short
最后结果1和2约为5~7万的qps,3为4~5万qps,4仅有3~4千qps
线上服务修改nginx与后端配置后相关测试结果为30~40万qps,而原来的配置只有5万qps左右。
另外nginx其他参数优化等等就不一一赘述。
由此可见,nginx在配置与后端的服务时最好保持为长连接,防止nginx频繁与后端创建关闭造成严重浪
skywalking 使用nginx 做grpc负载
我们知道grpc是基于http2的,http2的设计就是长连接的设计,在连接上可以跑多个stream来规避http 1.1 中的队头阻塞(Head of line blocking),简单说http1协议导致单个连接不能多路复用。
gRPC是一个高性能、通用的开源 RPC 框架,其由 Google 主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。gRPC 提供了一种简单的方法来精确地定义服务和为 iOS、Android 和后台支持服务自动生成可靠性很强的客户端功能库。客户端充分利用高级流和链接功能,从而有助于节省带宽、降低的 TCP 链接次数、节省 CPU 使用、和电池寿命。
从上述描述可以看出grpc基于http2,client到server应该保持长连接
所以使用nginx做grpc协议负载的时候,nginxs必须设置为长连接
https://www.bilibili.com/read/cv15741931/
Nginx 现在已经支持反代 gRPC 服务了,需要 Nginx >= 1.13.10,并且安装 ngx_http_v2_module 模块。
下面宇润分享一下最简单的 Nginx 反代 gRPC 长连接服务的配置: 作者:宇润 https://www.bilibili.com/read/cv15741931/ 出处:bilibili
# 定义我们的 gRPC 业务服务器地址 upstream grpcservers { server 172.17.0.1:13009; # 如果有多个可以定义多次 keepalive 1800; # 保持长连接的秒数。如果不配置这个参数,Nginx 与你的服务之间的连接,大概率会是短连接而不是长连接。 } server { listen 443 ssl http2; # gRPC 基于 Http2 协议,非常推荐启用 SSL # 下面5行根据实际情况进行配置 server_name 你的域名; access_log 你的域名.log main; error_log 你的域名.log error; ssl_certificate 证书.crt; ssl_certificate_key 证书.key; # grpc 代理设置 location ~* ^/(.+)\.(.+)/(.+)$ { grpc_set_header Host $host; grpc_set_header X-Real-IP $remote_addr; grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; grpc_socket_keepalive on; grpc_pass grpc://grpcservers; } # 你的接口或者站点,如果不需要可以去掉 location / { index index.html index.htm; root /var/www/你的域名/html; } } 作者:宇润 https://www.bilibili.com/read/cv15741931/ 出处:bilibili
宇润的生产环境是 Http 接口、gRPC 服务公用一个域名,所以依靠正则去匹配 gRPC 的请求,把他丢给 grpcservers 去处理。其它的请求还是按原来的方式进行处理。
keepalive 那个坑宇润踩了很久,发现不配置的话,Nginx 和服务之间的连接,大概率会是短连接而不是长连接。
Nginx ngx_http_grpc_module 文档:http://nginx.org/en/docs/http/ngx_http_grpc_module.html 作者:宇润 https://www.bilibili.com/read/cv15741931/ 出处:bilibili
posted on 2022-08-26 13:47 luzhouxiaoshuai 阅读(1311) 评论(0) 编辑 收藏 举报