client,server,nginx 在使用keepAlive里要保持一致,否则起不到效果

为什么要有KeepAlive?

在谈KeepAlive之前,我们先来了解下简单TCP知识(知识很简单,高手直接忽略)。首先要明确的是在TCP层是没有“请求”一说的,经常听到在TCP层发送一个请求,这种说法是错误的。

TCP是一种通信的方式,“请求”一词是事务上的概念,HTTP协议是一种事务协议,如果说发送一个HTTP请求,这种说法就没有问题。也经常听到面试官反馈有些面试运维的同学,基本的TCP三次握手的概念不清楚,面试官问TCP是如何建立链接,面试者上来就说,假如我是客户端我发送一个请求给服务端,服务端发送一个请求给我。。。

TCP层是没有请求的概念,HTTP协议是事务性协议才有请求的概念,TCP报文承载HTTP协议的请求(Request)和响应(Response)。

现在才是开始说明为什么要有KeepAlive。链接建立之后,如果应用程序或者上层协议一直不发送数据,或者隔很长时间才发送一次数据,当链接很久没有数据报文传输时如何去确定对方还在线,到底是掉线了还是确实没有数据传输,链接还需不需要保持,这种情况在TCP协议设计中是需要考虑到的。

TCP协议通过一种巧妙的方式去解决这个问题,当超过一段时间之后,TCP自动发送一个数据为空的报文给对方,如果对方回应了这个报文,说明对方还在线,链接可以继续保持,如果对方没有报文返回,并且重试了多次之后则认为链接丢失,没有必要保持链接。

如何开启KeepAlive?

KeepAlive并不是默认开启的,在Linux系统上没有一个全局的选项去开启TCP的KeepAlive。需要开启KeepAlive的应用必须在TCP的socket中单独开启。Linux Kernel有三个选项影响到KeepAlive的行为:

1.net.ipv4.tcpkeepaliveintvl = 75
2.net.ipv4.tcpkeepaliveprobes = 9
3.net.ipv4.tcpkeepalivetime = 7200

tcpkeepalivetime的单位是秒,表示TCP链接在多少秒之后没有数据报文传输启动探测报文; tcpkeepaliveintvl单位是也秒,表示前一个探测报文和后一个探测报文之间的时间间隔,tcpkeepaliveprobes表示探测的次数。

TCP socket也有三个选项和内核对应,通过setsockopt系统调用针对单独的socket进行设置:

TCPKEEPCNT: 覆盖 tcpkeepaliveprobes
TCPKEEPIDLE: 覆盖 tcpkeepalivetime
TCPKEEPINTVL: 覆盖 tcpkeepalive_intvl

举个例子,以我的系统默认设置为例,kernel默认设置的tcpkeepalivetime是7200s, 如果我在应用程序中针对socket开启了KeepAlive,然后设置的TCP_KEEPIDLE为60,那么TCP协议栈在发现TCP链接空闲了60s没有数据传输的时候就会发送第一个探测报文。

TCP KeepAlive和HTTP的Keep-Alive是一样的吗?

估计很多人乍看下这个问题才发现其实经常说的KeepAlive不是这么回事,实际上在没有特指是TCP还是HTTP层的KeepAlive,不能混为一谈。TCP的KeepAlive和HTTP的Keep-Alive是完全不同的概念。

TCP层的KeepAlive上面已经解释过了。 HTTP层的Keep-Alive是什么概念呢? 在讲述TCP链接建立的时候,我画了一张三次握手的示意图,TCP在建立链接之后, HTTP协议使用TCP传输HTTP协议的请求(Request)和响应(Response)数据,一次完整的HTTP事务如下图:

这张图我简化了HTTP(Req)和HTTP(Resp),实际上的请求和响应需要多个TCP报文。

从图中可以发现一个完整的HTTP事务,有链接的建立,请求的发送,响应接收,断开链接这四个过程,早期通过HTTP协议传输的数据以文本为主,一个请求可能就把所有要返回的数据取到,但是,现在要展现一张完整的页面需要很多个请求才能完成,如图片,JS,CSS等,如果每一个HTTP请求都需要新建并断开一个TCP,这个开销是完全没有必要的。

开启HTTP Keep-Alive之后,能复用已有的TCP链接,当前一个请求已经响应完毕,服务器端没有立即关闭TCP链接,而是等待一段时间接收浏览器端可能发送过来的第二个请求,通常浏览器在第一个请求返回之后会立即发送第二个请求,如果某一时刻只能有一个链接,同一个TCP链接处理的请求越多,开启KeepAlive能节省的TCP建立和关闭的消耗就越多。

当然通常会启用多个链接去从服务器器上请求资源,但是开启了Keep-Alive之后,仍然能加快资源的加载速度。HTTP/1.1之后默认开启Keep-Alive, 在HTTP的头域中增加Connection选项。当设置为Connection:keep-alive表示开启,设置为Connection:close表示关闭。实际上HTTP的KeepAlive写法是Keep-Alive,跟TCP的KeepAlive写法上也有不同。所以TCP KeepAlive和HTTP的Keep-Alive不是同一回事情。

Nginx的TCP KeepAlive如何设置?

开篇提到我最近遇到的问题,Client发送一个请求到Nginx服务端,服务端需要经过一段时间的计算才会返回, 时间超过了LVS Session保持的90s,在服务端使用Tcpdump抓包,本地通过wireshark分析显示的结果如第二副图所示,第5条报文和最后一条报文之间的时间戳大概差了90s。

在确定是LVS的Session保持时间到期的问题之后,我开始在寻找Nginx的TCP KeepAlive如何设置,最先找到的选项是keepalivetimeout,从同事那里得知keepalivetimeout的用法是当keepalivetimeout的值为0时表示关闭keepalive,当keepalivetimeout的值为一个正整数值时表示链接保持多少秒,于是把keepalivetimeout设置成75s,但是实际的测试结果表明并不生效。

显然keepalivetimeout不能解决TCP层面的KeepAlive问题,实际上Nginx涉及到keepalive的选项还不少,Nginx通常的使用方式如下:

从TCP层面Nginx不仅要和Client关心KeepAlive,而且还要和Upstream关心KeepAlive, 同时从HTTP协议层面,Nginx需要和Client关心Keep-Alive,如果Upstream使用的HTTP协议,还要关心和Upstream的Keep-Alive,总而言之,还比较复杂。

所以搞清楚TCP层的KeepAlive和HTTP的Keep-Alive之后,就不会对于Nginx的KeepAlive设置错。我当时解决这个问题时候不确定Nginx有配置TCP keepAlive的选项,于是我打开Ngnix的源代码,
在源代码里面搜索TCP_KEEPIDLE,相关的代码如下:

从代码的上下文我发现TCP KeepAlive可以配置,所以我接着查找通过哪个选项配置,最后发现listen指令的so_keepalive选项能对TCP socket进行KeepAlive的配置。

http://www.bubuko.com/infodetail-260176.html

KeepAlive,这次看下Nginx加Tomcat做反向代理这种典型场景下的KeepAlive配置与否的影响。以下图中的数据只能做个定性的参考,具体要根据实际业务测试。

  • 显然keepalive需要client和sever同时支持才生效;
  • 未使用keepalive(无论是客户端还是服务端不支持),服务端会主动关闭TCP连接,存在大量的TIME_WAI;
  • 是否使用keepalive比较复杂,并不是单纯的一个http头决定的;
  • Nginx似乎跟upstream之间维持着一个长连接池,所以很少会看到TIME_WAIT,都处于ESTABLISHED状态。

Nginx有关KeepAlive的配置有两处:

一处是http节点下的keepalive_timeout,这个设置的是跟client(图中downstream)的连接超时时间;还有一处是upstream中配置的keepalive,注意这个单位是数量不是时间。

时间: 2024-10-10 21:30:41

client,server,nginx 在使用keepAlive里要保持一致,否则起不到效果的相关文章

Nginx学习之keepalive

当然,在nginx中,对于http1.0与http1.1也是支持长连接的.什么是长连接呢?我们知道,http请求是基于TCP协议之上的,那么,当客户端在发起请求前,需要先与服务端建立TCP连接,而每一次的TCP连接是需要三次握手来确定的,如果客户端与服务端之间网络差一点,这三次交互消费的时间会比较多,而且三次交互也会带来网络流量.当然,当连接断开后,也会有四次的交互,当然对用户体验来说就不重要了.而http请求是请求应答式的,如果我们能知道每个请求头与响应体的长度,那么我们是可以在一个连接上面执

NGINX Web Server Nginx web 服务器

原文地址:http://nginx.com/resources/admin-guide/web-server/ NGINX Web Server Nginx web 服务器 This section describes: the most common configuration of a web server how to set up virtual servers and define locations for request processing how to use variable

NGINX Web Server Nginx web server

原文地址:http://nginx.com/resources/admin-guide/web-server/ NGINX Web Server Nginx web server This section describes: the most common configuration of a web server how to set up virtual servers and define locations for request processing how to use varia

NetMQ(ZeroMQ)Client => Server => Client 模式的实现

ØMQ (也拼写作ZeroMQ,0MQ或ZMQ)是一个为可伸缩的分布式或并发应用程序设计的高性能异步消息库.它提供一个消息队列, 但是与面向消息的中间件不同,ZeroMQ的运行不需要专门的消息代理(message broker).该库设计成常见的套接字风格的API. ZeroMQ是由iMatix公司和大量贡献者组成的社群共同开发的.ZeroQ通过许多第三方软件支持大部分流行的编程语言 .类库提供一些套接字(对传统Berkeley套接字和Unix domain socket的泛化),每一个套接字可

QDjango,tufao,C++ websocket client/server

QDjango, a Qt-based C++ web frameworkhttps://github.com/jlaine/qdjango/ An asynchronous web framework for C++ built on top of Qt http://vinipsmaker.github.io/tufao/https://github.com/vinipsmaker/tufao C++ websocket client/server library http://www.za

《Python Network Programming Cookbook》读书笔记1---套接字, IPv4, 简单的Client/Server程序

这一部分主要介绍python中socket模块的相关内容,socket即套接字. socket是使用TCP/IP协议的应用程序通常采用的应用编程接口,它位于运输层和应用层之间,起源于UNIX,由于遵从UNIX“一切皆文件的”思想故socket可看作一种特殊的文件,对其的操作基本可以视为读写I/O.打开.关闭.关于套接字的基本概念@吴秦的Linux Socket编程(不限Linux)写的很详细,大家可以参考. 在下面列出的各个部分中我将先贴出代码,然后对其进行解释. 通过python3获得本机名和

Network client/server (二)

接上篇 Network client/server (一) server.c 1  header files #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> heade

Client–server model

Client–server model From Wikipedia, the free encyclopedia The client–server model of computing is a distributed application structure that partitions tasks or workloads between the providers of a resource or service, called servers, and service reque

Linux SocketCan client server demo hacking

/*********************************************************************** * Linux SocketCan client server demo hacking * 说明: * 本文主要是解读Linux上的SocketCan的基本使用方法,内容和Linux上的 * 网络编程差不多. * * 2016-3-28 深圳 南山平山村 曾剑锋 ********************************************