理解Keepalive(1)

大家都听过keepalive,但是其实对于keepalive这个词还是很晦涩的,至少我一直都只知道一个大概,直到之前排查线上一些问题,发现keepalive还是有很多玄机的。其实keepalive有两种,一种是TCP层的keepalive,另一种是HTTP层的Keep-Alive。这篇文章先说说tcp层的keepalive

tcp keepalive

设想有一种场景:A和B两边通过三次握手建立好TCP连接,然后突然间B就宕机了,之后时间内B再也没有起来。如果B宕机后A和B一直没有数据通信的需求,A就永远都发现不了B已经挂了,那么A的内核里还维护着一份关于A&B之间TCP连接的信息,浪费系统资源。于是在TCP层面引入了keepalive的机制,A会定期给B发空的数据包,通俗讲就是心跳包,一旦发现到B的网络不通就关闭连接。这一点在LVS内尤为明显,因为LVS维护着两边大量的连接状态信息,一旦超时就需要释放连接。

Linux内核对于tcp keepalive的调整主要有以下三个参数

1. tcp_keepalive_time

 the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further

2. tcp_keepalive_intvl

 the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime

3. tcp_keepalive_probes

 the number of unacknowledged probes to send before considering the connection dead and notifying the application layer

Example

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
$ cat /proc/sys/net/ipv4/tcp_keepalive_probes
9 当tcp发现有tcp_keepalive_time(7200)秒未收到对端数据后,开始以间隔tcp_keepalive_intvl(75)秒的频率发送的空心跳包,如果连续tcp_keepalive_probes(9)次以上未响应代码对端已经down了,close连接

在socket编程时候,可以调用setsockopt指定不同的宏来更改上面几个参数

TCP_KEEPCNT: tcp_keepalive_probes

TCP_KEEPIDLE: tcp_keepalive_time

TCP_KEEPINTVL: tcp_keepalive_intvl

Nginx配置tcp keepalive

Nginx对于keepalive的配置有一大堆,大伙每次看都迷茫了,其实Nginx涉及到tcp层面的keepalive只有一个:so_keepalive。它属于listen指令的配置参数,具体配置

so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]

this parameter (1.1.11) configures the “TCP keepalive” behavior for the listening socket. If this parameter is omitted then the operating system’s settings will be in effect for the socket. If it is set to the value “on”, the SO_KEEPALIVE option is turned on for the socket. If it is set to the value “off”, the SO_KEEPALIVE option is turned off for the socket. Some operating systems support setting of TCP keepalive parameters on a per-socket basis using the TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT socket options. On such systems (currently, Linux 2.4+, NetBSD 5+, and FreeBSD 9.0-STABLE), they can be configured using the keepidle, keepintvl, and keepcnt parameters. One or two parameters may be omitted, in which case the system default setting for the corresponding socket option will be in effect.

  • Example
so_keepalive=30m::10
will set the idle timeout (TCP_KEEPIDLE) to 30 minutes, leave the probe interval (TCP_KEEPINTVL) at its system default, and set the probes count (TCP_KEEPCNT) to 10 probes.

在Nginx的代码里可以看到

./src/http/ngx_http_core_module.c

static ngx_command_t  ngx_http_core_commands[] = {
...
// listen 指令解析 -->> call ngx_http_core_listen()
{ ngx_string("listen"),
NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
ngx_http_core_listen,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },
...
} static char *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ ...
// 下面就是 so_keepalive 后面的参数解析
if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[n].data[13], "on") == 0) {
lsopt.so_keepalive = 1; } else if (ngx_strcmp(&value[n].data[13], "off") == 0) {
lsopt.so_keepalive = 2; } else {
// 自定义系统keepalive的相关设置
... } if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) {
return NGX_CONF_OK;
} } ./src/core/ngx_connection.c if (ls[i].keepidle) {
value = ls[i].keepidle;
// 设置 tcp_keepalive_time
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
value, &ls[i].addr_text);
}
} if (ls[i].keepintvl) {
value = ls[i].keepintvl;
// 设置 tcp_keepalive_intvl
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
value, &ls[i].addr_text);
}
} if (ls[i].keepcnt) {
// 设置 tcp_keepalive_intvl
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
(const void *) &ls[i].keepcnt, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
ls[i].keepcnt, &ls[i].addr_text);
}
}

总结

这篇文章说了TCP层面的keepalive相关知识以及Nginx的支持tcp keepalive的配置。tcp层面的keepalive存在更多意义上是为了检测两端连接是否正常,注重点是在于连接的本身!要和HTTP层面的keepaplive区分开来,明白这点很重要。

tcp中的keepalive(转)的更多相关文章

  1. TCP中的KeepAlive与HTTP中的Keep-Alive

    KeepAlive 与 Keep-Alive 前言 昨天被问到了HTTP中Keep-Alive的概念,看名字我只知道是保持连接用的,但是对于他怎么结束连接,为什么要用他这些就不是很清楚了,今天查了一下 ...

  2. 聊聊 TCP 中的 KeepAlive 机制

    KeepAlive并不是TCP协议规范的一部分,但在几乎所有的TCP/IP协议栈(不管是Linux还是Windows)中,都实现了KeepAlive功能 RFC1122#TCP Keep-Alives ...

  3. TCP连接探测中的Keepalive和心跳包

    TCP连接探测中的Keepalive和心跳包 tcp keepalive 心跳 保活 Linuxtcp心跳keepalive保活1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 ...

  4. TCP连接探测中的Keepalive 和心跳包

    采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...

  5. TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活

    1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...

  6. SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成,浏览器中的Keep-Alive

    http://www.cnblogs.com/OpenCoder/p/5089258.html     IE中Keep-Alive机制引起的错误 我们知道Http协议是基于TCP/IP连接的,也就是说 ...

  7. http中的KeepAlive

    为什么要使用KeepAlive? 终极的原因就是需要加快客户端和服务端的访问请求速度.KeepAlive就是浏览器和服务端之间保持长连接,这个连接是可以复用的.当客户端发送一次请求,收到相应以后,第二 ...

  8. 通过wireshark抓包来讲解HTTP中Connection: keep-alive头部的作用

    今天周末时间,有空给大家讲解一个小知识点,即HTTP的keep-alive头部.我使用wireshark来抓取网络包来在实战中讲解.希望能让大家更容易.更直观的理解! HTTP中keep-alive头 ...

  9. TCP漫谈之keepalive和time_wait

    TCP是一个有状态通讯协议,所谓的有状态是指通信过程中通信的双方各自维护连接的状态. 一.TCP keepalive 先简单回顾一下TCP连接建立和断开的整个过程.(这里主要考虑主流程,关于丢包.拥塞 ...

随机推荐

  1. 获取数据库表中自增长最新的id

    mybatis <insert id="InsertCourse"> insert into training_course(type_id,course_title, ...

  2. 25_ajax请求_使用fetch

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. PRC远程过程调用

    RPC(Remote Promote Call) 一种进程间通信方式.允许像调用本地服务一样调用远程服务. RPC框架的主要目标就是让远程服务调用更简单.透明.RPC框架负责屏蔽底层的传输方式(TCP ...

  4. linux suse 3.0.101的一次中断暴增的排查

    本文相关背景知识可以在:http://man7.org/linux/man-pages/man5/proc.5.html?spm=5176.100239.blogcont6047.8.ImCGpr 看 ...

  5. 手工获取AWR报告

    AWR(Automatic Workload Repository)报告常用于Oracle数据库性能分析.熟练解读AWR报告有助于快速分析Oracle性能问题.下面主要描述如何手工获取AWR报告. 操 ...

  6. 【转】Classful IPv4 addressing definition

    Classful addressing definition Class Leadingbits Size of networknumber bit field Size of restbit fie ...

  7. effective C++学习三(仅供个人学习记录,本文摘录effective C++)

    条款 3:尽量用 new 和 delete 而不用 malloc 和 free  把 new和 delete 与malloc 和 free 混在一起用也是个坏想法.对一个用 new 获取来的指针调用 ...

  8. unity3d assetbundle打包策略

    由于assetbundle打包存在依赖的问题,所有资源要进行合理的分包 零.代码 代码都放在本地,包括NGUI等插件的代码.shader代码(内置的shader无需打包,而自定义的shader还是需要 ...

  9. windows下一分钟配置ngnix实现HLS m3u8点播

    1. 下载 nginx-1.5.10 for windows 2. 修改配置文件nginx-1.5.10\conf\nginx.conf,增加以下行到最后一个"}"的前一行: lo ...

  10. Redis入门及主从配置

    1.Redis入门简介 Redis是一个开源的使用ANSI C语音编写.支持网络.可基于内存亦可持久化的日志型,Key-Value数据库.支持存储的value类型包括 string(字符串).list ...