建设部科技中心网站,有趣的网页设计,网易企业邮箱 登录,建设一个网站需要什么技术人员文章目录 一. http的长连接历史1. HTTP短连接模型2. HTTP长连接模型 二. nginx作为代理时实现HTTP长连接1. nginx与client的长连接1.1. keepalive_timeout指令1.2. keepalive_requests指令* 场景分析 2. 保持和server的长连接2.1. location设置* 场景分析 2.2. upstream设置* 场… 文章目录 一. http的长连接历史1. HTTP短连接模型2. HTTP长连接模型 二. nginx作为代理时实现HTTP长连接1. nginx与client的长连接1.1. keepalive_timeout指令1.2. keepalive_requests指令* 场景分析 2. 保持和server的长连接2.1. location设置* 场景分析 2.2. upstream设置* 场景分析场景1场景2场景3 长连接基础先了解为什么要保持长连接http的长连接历史。 长连接实战接着如何分析如何通过nginx设置长连接。如果不恰当的设置长连接会出现什么问题。
一. http的长连接历史
HTTP是属于应用层七层的协议传输层四层使用的是TCP协议所以HTTP的长连接和短连接其本质就是TCP的长连接和短连接 HTTP是一个无状态的面向连接的协议指的是协议对于事务处理没有记忆能力服务器不知道客户端是什么状态但无状态不代表HTTP不能保持TCP连接 TCP建立连接和断开连接是需要三握四挥的也就说HTTP连接的建立与断开是消耗资源的。
接下来正式了解下http长短连接模型
1. HTTP短连接模型
短连接的基本逻辑与特点 HTTP 短连接模型是最早期的模型也是 HTTP/1.0 的默认模型。在早期HTTP 使用一个简单的模型来处理这样的连接。这些连接的生命周期是短暂的每发起一个请求时都先有一次TCP握手然后创建一个新连接并在收到应答时立即关闭。
持续的短连接是耗时、耗费资源的 实际上TCP 协议握手本身就是耗费时间的所以 TCP 可以保持更多的热连接来适应负载。短连接破坏了 TCP 具备的能力新的冷连接降低了其性能。
长短连接的设置 在 HTTP/1.0 中如果没有指定 Connection协议头或者是值被设置为 close就会启用短连接模型要在 HTTP/1.0 中启用长连接模型需要在协议头中指定Connection: Keep-Alive 不过并不建议这样操作。 而在 HTTP/1.1 中默认使用长连接模型只有当 Connection被设置为 close 时才会用到这个短连接模型协议头都不用再去声明它(但是一般还是会把它加上以防万一因为某种原因要退回到 HTTP/1.0 )。 2. HTTP长连接模型
长连接的趋势 后来网页需要请求的资源越来越多短连接模型显然已经十分吃力了。因为短连接有两个比较大的问题创建新连接耗费的时间尤为明显三次握手很耗费时间另外 TCP 连接的性能只有在该连接被使用一段时间后(热连接)才能得到改善。因此在HTTP/1.1中引入了长连接模型。
在 HTTP/1.1 之前长连接也被称为keep-alive 连接。 一个长连接会保持一段时间重复用于发送一系列请求节省了新建 TCP 连接握手的时间还可以利用 TCP 的性能增强能力ing。当然这个连接也不会一直保留着连接在空闲一段时间后会被关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。
长连接的缺点资源占用问题 使用长连接本质上是因为当不断地三次握手建立连接所消耗的资源大于维持连接所需要的资源。
当处于空闲状态时它还是会消耗服务器资源。如果空闲较长可以使用非长连接即尽快关闭那些空闲的连接也能对性能有所提升。
二. nginx作为代理时实现HTTP长连接
当我们配置Nginx作为代理服务器的时候想要支持HTTP长连接需要client到Nginx和Nginx到servernginx中upstream配置的server都是长连接因为此时Nginx既是client的server也是server的client。
多个HTTP请求通过复用TCP连接会达到以下效果 减少握手次数通过减少并发连接数减少了服务器资源的消耗降低TCP拥塞控制的影响 1. nginx与client的长连接
为了在client和nginx之间保持长连接有两个要求 client发送的HTTP请求要求keep alive 2.nginx设置上支持keep alive默认情况下nginx已经自动开启了对client连接的keep alive支持。 1.1. keepalive_timeout指令
语法用户一个HTTP请求连接完成以后最多经过timeout时间如果还是没有新的请求就会关闭连接
Syntax: keepalive_timeout timeout [header_timeout];
Default: keepalive_timeout 75s;
Context: http, server, location1. 第一个参数设置keep-alive客户端连接在服务器端保持开启的超时值。值为0会禁用keep-alive客户端连接。默认75s一般情况下也够用对于一些请求比较大的内部服务器通讯的场景适当加大为120s或者300s。2. 可选的第二个参数在响应的header域中设置一个值“Keep-Alive: timeouttime”。第二个参数通常可以不用设置。1.2. keepalive_requests指令
使用语法
Syntax: keepalive_requests number;
Default: keepalive_requests 1000;
Context: http, server, location;该指令首次出现在版本0.8.0中。在版本1.19.10之前默认值为100。1.参数的作用
一个TCPkeep-alive连接上最多执行多少个HTTP请求。
当达到这个参数设置的最大值默认是1000时则nginx会强行关闭这个长连接
逼迫客户端不得不重新建立新的长连接。注意
定期关闭连接是为了释放每个连接的内存分配。
因此设置过高的最大请求数可能导致过多的内存使用这是不推荐的。* 场景分析 这个参数往往被大多数人忽略因为大多数情况下当QPS(每秒请求数)不是很高时默认值100凑合够用。但是对于一些QPS比较高比如超过10万QPS甚至达到30万,50万甚至更高) 的场景默认的1000就不适用了。因为此时会频繁创建长连接。 出现频繁的关闭、创建连接 当QPS10万/s时客户端每秒发送10万个请求(通常建立有多个长连接)每个连接只能最多跑1000次请求意味着平均每秒钟就会有100个长连接因此被nginx关闭。同样意味着为了保持QPS客户端不得不每秒中重新新建100个连接。 大量的TIME_WAIT 如果用netstat命令看客户端机器就会发现有大量的TIME_WAIT的socket连接(即使此时keep alive已经在client和nginx之间生效)。因此对于QPS较高的场景非常有必要加大这个参数以避免出现大量连接被生成再抛弃的情况减少TIME_WAIT。 2. 保持和server的长连接
2.1. location设置
为了让nginx和serverupstream块中的servers之间保持长连接典型设置如下
http {upstream BACKEND {server 192.168.0.18080 weight1 max_fails2 fail_timeout30s;server 192.168.0.28080 weight1 max_fails2 fail_timeout30s;keepalive 300; // 这个很重要}server {listen 8080 default_server;server_name ;location / {proxy_pass http://BACKEND;proxy_set_header Host $Host;proxy_set_header x-forwarded-for $remote_addr;proxy_set_header X-Real-IP $remote_addr;add_header Cache-Control no-store;add_header Pragma no-cache;proxy_http_version 1.1; // 这两个最好也设置proxy_set_header Connection ;client_max_body_size 3072k;client_body_buffer_size 128k;}}
}location中的两个参数 proxy_http_version 1.1; proxy_set_header Connection ;HTTP协议中对长连接的支持是从1.1版本之后才有的因此最好通proxy_http_version指令设置为1.1代表来自client的请求Connection header会被清理。清理 Connection 头可以确保代理层完全控制连接的生命周期。 * 场景分析
假设client和nginx之间是短连接nginx和upstream之间可以开启长连接。这种情况下必须清理来自client请求中的Connection header如果不清理则会将client的header传递过来导致不能开启长连接。 2.2. upstream设置
upstream设置中有个参数要特别的小心就是这个keepalive。
nginx keepalive语法:
Syntax: keepalive connections;
Default: —
Context: upstreamkeepalive参数作用 connections参数设置每个worker进程与upstream server建立的最多空闲 的keepalive连接数量。当这个数量被突破时最近使用最少的连接将被关闭。 特别提醒keepalive指令不会限制一个nginx worker进程到upstream服务器连接的总数量。connections参数应该设置为一个足够小的数字来让upstream服务器来处理新进来的连接。 * 场景分析
场景描述 有一个HTTP服务作为upstream server接收请求响应时间为100毫秒一秒能处理10个请求。如果要达到10000 QPS的性能就需要在nginx和upstream服务器之间建立大约1000条HTTP连接。 nginx为此建立连接池然后请求过来时为每个请求分配一个连接请求结束时回收连接放入连接池中连接的状态也就更改为idle。 我们再假设这个upstream服务器的keepalive参数设置比较小比如常见的10.
场景1
假设请求和响应是均匀而平稳的那么这1000条连接应该都是一放回连接池就立即被后续请求申请使用线程池中的idle线程会非常的少趋进于零。 我们以100毫秒为一个单位来看连接的情况
每100毫秒有100个新请求需要100个连接根据前面假设可以知道每100毫秒有100个请求结束可以释放100个连接如果请求和应答都均匀则100毫秒内释放的连接刚好够用不需要新建连接连接池也不空闲。
场景2
回到现实世界请求通常不是足够的均匀和平稳为了简化问题我们假设应答始终都是平稳的只是请求不平稳
假设此时100毫秒内只有50个请求。此时连接池内有50个空闲连接。注意看keepalive10的设置这意味着连接池中最多容许保留有10个空闲连接。因此nginx不得不将这50个空闲连接中的40个关闭只留下10个。再下一个100个毫秒有150个请求进来有100个请求结束任务释放连接。150 - 100 50,空缺了50个连接减掉前面连接池保留的10个空闲连接nginx不得不新建40个新连接来满足要求。 我们可以看到在短短的200毫秒内仅仅因为请求不够均匀就导致nginx在前100毫秒判断空闲连接过多关闭了40个连接而后10毫秒又不得不新建40个连接来弥补连接的不足。
场景3
假设请求是均匀的而应答不再均匀前100毫秒只有50个请求结束后100毫秒有150个
前100毫秒进来100个请求只结束了50个请求导致此时连接不够下次请求用nginx为此新建50个连接此时有150个连接后100毫秒进来100个请求结束150个请求导致空闲连接过多ngixn为此关闭了150-10140个空闲连接。 小结
现实世界中请求往往不均匀服务器处理请求的时间也不平稳当qps很高时就会在短时间内导致两种非常矛盾现象 1. 连接不够用造成新建连接2. 连接空闲造成关闭连接。从而使得总连接数出现反复震荡不断的创建新连接和关闭连接使得长连接的效果被大大削弱。
keepalive参数设置方法比如前面10000 QPS和100毫秒响应时间就可以推算出需要的长连接数量大概是1000. 然后将keepalive设置为这个长连接数量的10%到30%。 参考 https://www.jianshu.com/p/142b35998947