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连接建立和断开的整个过程.(这里主要考虑主流程,关于丢包.拥塞 ...
随机推荐
- ABAP-定时-异步
*&---------------------------------------------------------------------* *& Report ZRICO_TES ...
- Firebird日期时间操作
最近在使用Firebird数据做 一项目,使用FireBird边用边学.(以下转贴) 查询2007年度以后的,12月份以上的数据记录,datetime为timestamp字段 select * fro ...
- linux 自定义模块来缓存skb的意义
linux中,管理网卡收发报文的结构是sk_buff,这个结构比freebsd中的m_buf复杂的多,这个也是为什么现在用户态协议栈大多采用bsd为基础来实现的一个原因. struct sk_buff ...
- 【358】GitHub 上面文件夹下载方法
参考:https://www.bilibili.com/read/cv210500/ 参考:https://www.jianshu.com/p/743ecc20ffb2 软件下载:Downloads ...
- Python开发环境搭建指导
本文主要介绍Python开发环境的搭建.主要包括如下几部分内容: (1)Python软件的安装.注意版本的选择和安装过程中选项的勾选. (2)pip工具环境变量.镜像源的配置使用和常用镜像源介绍.pi ...
- Matlab实现BP网络识别字母
训练样本空间 每个样本使用5×5的二值矩阵表征一个字母.一共10个字母类型,分别是N,I,L,H,T,C,E,F,Z,V.每个字母9个样本.共90个. N1=[1,0,0,0,1; 1,0,0,0 ...
- 【原创】锐捷实现OSPF路由协议和NAT地址转换协议
路由网络设计与实施 [锐捷设备实现OSPF路由协议与NAT地址转换] 说明: 本文是在多VLAN双星型交换网络的基础之上发展的.关于组建多VLAN双星型交换网络,请参阅: <思科和锐捷组建多 ...
- 求1到n,n个整数的全排列
package com.dong.harder; public class AllArrays { public static void main(String[] args) { // TODO A ...
- 关于scp在zsh报错:zsh:no matches found :
我要将某一目录下面所有文件拷贝的时候,scp *.jpg 的时候,报错 zsh: no matchs found:path 其实是zsh自己解析了*号,所以,只要给*加上就可以了\ scp \*.jp ...
- MySQL可以通过phpmyadmin连接,但是无法通过SqlYog(Windows)或Sequel Pro(Mac)下进行远程连接
更改数据库密码: update user set password=passworD("sunjingyu0509!") where user='root'; flush priv ...