TCP的keepalive
前端
keepalive是设置在操做系统级别,做用于到本机的链接。在必定时间内对远程主机发送TCP探测报文用于探测对方是否存活。
后端
上图2个场景是最多见的,可是针对于keepalive的问题是同样的。无非就是客户端和最终的WEB服务器直接多了中间设备。这会怎么样呢?正常状况下不会有问题,可是客户端把请求发送给Nginx,Nginx的后端Tomcat须要必定时间才能返回结果,超过90秒就会有问题,若是使用LVS作负载均衡看到的现象就是90秒内没有返回则LVS会把客户端到Nginx的链接断开。由于LVS默认保持的TCP会话为90秒。超过90秒没有TCP传输,LVS就会给客户端和Nginx发送RESET报文断开链接。这样作的缘由其实就是节省资源关闭空闲链接和保护后端。遇到这种请求你只须要在LVS上开启keepalive就好,固然你的Nginx上也要设置,由于真正的后端服务器是Tomcat等应用程序。浏览器
keepalive是什么:bash
链接创建之后,若是应用程序或上层协议一直不发数据或者间隔好久才发一次,那么如何肯定创建链接的双方还存在呢?在TCP协议的设计中,在一段时间以后,TCP自动发送一个空数据报文给对方,若是对方回应了这个报文说明还在线,那么继续保持链接,若是对方没有回应而且通过屡次重试发送以后依然没有回应,则认为对方不在线能够关闭链接。服务器
如何开启keepalive:网络
keepalive在Linux系统上没有一个全局开关来开启或关闭这个功能觉得它是TCP的一个特性,因此不能简单的说默认是否是开启。由于开启这个功能是须要应用程序在注册使用socket时单独设置的,Linux上关于TCP的内核参数只是会影响keepalive的行为。注意:启动Nginx或者LVS等任何网络服务都会使用socket。并发
sysctl -a | grep net.ipv4.tcp_keepalive
参数 |
含义 |
net.ipv4.tcp_keepalive_intvl |
表示发送前一个探测报文和后一个探测报文的间隔时间 |
net.ipv4.tcp_keepalive_probes | 表示探测次数,超过这个次数仍是探测失败则关闭链接 |
net.ipv4.tcp_keepalive_time | 表示TCP链接多少秒以后没有数据报文传输就启动探测报文 |
代码体现负载均衡
setsockopt函数是设置与套接字有关的选项,它里面的选项有不少,下面的SO_KEEPALIVE表示长链接。
socket
//使用长链接 if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1) { //if error } //设置选项 if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1) { //if error } if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1) { //if error } if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1) { //if error }
socket选项 |
对应的内核参数 |
TCP_KEEPCNT |
net.ipv4.tcp_keepalive_probes |
TCP_KEEPIDLE |
net.ipv4.tcp_keepalive_time |
TCP_KEEPINTVL |
net.ipv4.tcp_keepalive_intvl |
Linux系统对这三个参数有默认设置,你的应用程序能够覆盖自行设置须要的值。tcp
HTTP的keep-alive
HTTP的keep-alive和TCP的不是一个概念,一个页面上有几百个元素一个元素其实就是一个HTTP请求,若是每一个请求都打开和关闭一次TCP链接那至关消耗资源,对于HTTP的Keep-Alive来讲就是TCP链接的复用,一个请求完毕后服务器不关闭链接而是等待一段时间接收浏览器可能发来的以后的请求。一般浏览器在完成第一个请求以后会立刻发送第二个请求,因此这样会节省不少资源消耗。
Nginx如何开启TCP层的KeepAlive呢?
从TCP层面上Nginx要关系和client和后端upstream的KeepAlive,同时从HTTP层面Nginx还须要关系client和upstream的keep-alive。
参数 |
说明 |
so_keepalive |
用于设置监听套接字的TCP KeepAlive行为,若是只是设置on而不设置具体参数则使用操做系统默认设置 on|off|[keepidle]:[keepintvl]:[keepcnt] on表示开启 off表示关闭 keepidle表示等待时间 keepintvl表示探测报文发送间隔时间 keepcnt表示探测报文发送次数 以上参数只能用一个。该参数属于listen的辅助参数,在server端中,配置完监听端口可使用这个参数。 listen 80 so_keepalive=on,若是要设置时间能够这样设置 listen 80 so_keepalive=30::10 在Nginx中针对TCP层的keepalive只有这一个。 |
Nginx如何开启针对前端客户端的HTTP层的keep-alive?
参数 |
说明 |
keepalive_timeout |
0表示关闭keepalive,设置大于0的值表示保持连接多少秒,这个值不能解决TCP层面的KeepAlive问题 |
keepalive_requests |
一个长链接创建以后,Nginx会给客户端计数,达到数值时则强制关闭链接,致使Nginx服务器出现TIME_WAIT。默认100,对于QPS比较高的场景这个值能够设置大一点。 |
Nginx如何开启针对后端服务器的HTTP层的keep-alive?
参数 |
说明 |
keepalive |
这个是在upstream中设置的。设置upstream到后端服务器的最大空闲长链接数量,当达到数量时则收回,它并不影响到后端的并发数量。若是设置的值比较小对于不一样时段的请求和响应数量均衡的场景没有影响,可是对于不一样时段请求数量不一样就有影响。因此建议设置大一点。这个的计算要和QPS和RT来计算出须要多少长链接数量,好比10000QPS,每一个请求0.1秒。1/0.1=10, 10000/10=1000,也就是须要1000个长链接,不过一般能够设置到10%-30%。 |
总结
HTTP的keep-alive是为了让TCP链接存活久一点以便复用链接完成更多HTTP请求,提升链接利用率。
TCP的Keepalive是一种TCP链接的探测机制,使其一直保持可用。