tcp中的keepalive(转)
理解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(转)的更多相关文章
- TCP中的KeepAlive与HTTP中的Keep-Alive
KeepAlive 与 Keep-Alive 前言 昨天被问到了HTTP中Keep-Alive的概念,看名字我只知道是保持连接用的,但是对于他怎么结束连接,为什么要用他这些就不是很清楚了,今天查了一下 ...
- 聊聊 TCP 中的 KeepAlive 机制
KeepAlive并不是TCP协议规范的一部分,但在几乎所有的TCP/IP协议栈(不管是Linux还是Windows)中,都实现了KeepAlive功能 RFC1122#TCP Keep-Alives ...
- TCP连接探测中的Keepalive和心跳包
TCP连接探测中的Keepalive和心跳包 tcp keepalive 心跳 保活 Linuxtcp心跳keepalive保活1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 ...
- TCP连接探测中的Keepalive 和心跳包
采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...
- TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...
- SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成,浏览器中的Keep-Alive
http://www.cnblogs.com/OpenCoder/p/5089258.html IE中Keep-Alive机制引起的错误 我们知道Http协议是基于TCP/IP连接的,也就是说 ...
- http中的KeepAlive
为什么要使用KeepAlive? 终极的原因就是需要加快客户端和服务端的访问请求速度.KeepAlive就是浏览器和服务端之间保持长连接,这个连接是可以复用的.当客户端发送一次请求,收到相应以后,第二 ...
- 通过wireshark抓包来讲解HTTP中Connection: keep-alive头部的作用
今天周末时间,有空给大家讲解一个小知识点,即HTTP的keep-alive头部.我使用wireshark来抓取网络包来在实战中讲解.希望能让大家更容易.更直观的理解! HTTP中keep-alive头 ...
- TCP漫谈之keepalive和time_wait
TCP是一个有状态通讯协议,所谓的有状态是指通信过程中通信的双方各自维护连接的状态. 一.TCP keepalive 先简单回顾一下TCP连接建立和断开的整个过程.(这里主要考虑主流程,关于丢包.拥塞 ...
随机推荐
- git 配置提交过滤文件
1)在Git项目中定义.gitignore文件 2)在Git项目的设置中指定排除文件 3)定义Git全局的 .gitignore 文件
- Angular2学习笔记
Angular2 这里 Angular2 是指采用 TypeScript 语言的 Angular 2.0及以上版本.与采用 JavaScript 语言的 AngularJS 相比,Angular2 不 ...
- 漫谈C指针:参数传递的三道题目
漫谈C指针:参数传递的三道题目 2009-07-02 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?) 考题一,程序代码如下: [c] view plaincopy ...
- C++ 动态创建按钮及 按钮的消息响应
动态创建的按钮 都会在消息 OnCommand 中得到处理,无论是什么消息,都会处理的 1\创建按钮 CButton* btn = new CButton(); btn->Create(_T(, ...
- C# windows服务:C#windows服务中的Timer控件的使用
C# windows服务程序中的Timer控件的使用问题是如何解决的呢? 今天和同事一起研究了下C# windows服务程序中的Timer控件的使用的写法. 我们在建立一个C# windows服务程序 ...
- jquery iframe父子框架中的元素访问方法
在web开发中,经常会用到iframe,难免会碰到需要在父窗口中使用iframe中的元素.或者在iframe框架中使用父窗口的元素 js 在父窗口中获取iframe中的元素 1. 格式:window. ...
- 寒假生活第一天——Github初体验
快开学了,今天体验了一下github这个对我来说很是神秘的东西 它的定义来源于百度百科,如有异议,那就有吧.//gitHub是一个面向开源及私有软件项目的托管平台,因为只支持git 作为唯一的版本库格 ...
- Java Runtime
Runtime 类代表着Java程序的运行时环境,构造方法 private Runtime(){},采用单例模式,一个jvm只有一个Runtime实例对象,该类会被自动创建,我们可以通过Runtime ...
- Ubuntu 16.04 LTS network DIASBLED解决办法
问题 昨天正浏览着网页,突然无法连接.但右上角的wifi信号显示仍然是连接状态.于是我尝试断开再重新连接一次,没想到刚断开就报了个内部错误,然后wifi图标直接消失了.重启后虽然有wifi图标,但无法 ...
- 【C++】构造函数语意
构造函数的构造操作 编译器何时会为一个类合成默认构造函数? 答:当编译器需要的时候. 有以下四种情况: 带有默认构造函数的类对象 以下代码为例: class Foo {public: Foo();} ...