기본적으로 http1.1 프로토콜의 요청 헤더는 그림과 같이 기본적으로 Keepalive를 활성화하는 것입니다.
그럼 Keepalive란 무엇인가요? 기능은 무엇입니까?
keepalive는 끊어진 연결을 감지할 수 있는 TCP의 메커니즘입니다. 해당 기능은 긴 소켓 연결이 끊어지지 않도록 하는 것입니다. 이는 TCP 계층의 기능이며 애플리케이션 계층에 속하지 않습니다.
tcp 계층은 어떻게 긴 연결을 유지하나요?
먼저 Keepalive의 사용법을 살펴보겠습니다. 세 가지 매개변수가 있으며 애플리케이션 계층에 열려 있습니다.
sk->keepalive_probes:探测次数,重试次数 sk->keepalive_time 探测的心跳间隔,tcp链接在多少秒之后没有数据报文传输启动探测报文 sk->keepalive_intvl 探测间隔,未收到回复时,重试的时间间隔
기본 구성 보기:
[***@*** ~]$ 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
사용 방법:
int keepalive = 1; // 开启keepalive属性 int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测 int keepinterval = 5; // 探测时发包的时间间隔为5 秒 int keepcount = 3; // 探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发。并且清零该计数 setsockopt(rs, sol_socket, so_keepalive, (void *)&keepalive , sizeof(keepalive )); setsockopt(rs, sol_tcp, tcp_keepidle, (void*)&keepidle , sizeof(keepidle )); setsockopt(rs, sol_tcp, tcp_keepintvl, (void *)&keepinterval , sizeof(keepinterval )); setsockopt(rs, sol_tcp, tcp_keepcnt, (void *)&keepcount , sizeof(keepcount ));
애플리케이션 계층을 이렇게 설정한 후 기본 구성을 덮어쓰고 수동으로 설정합니다.
TCP 연결이 설정된 경우. keepalive_time 내에 두 당사자 간에 데이터 패킷 전송이 없으면 keepalive 기능을 켜는 쪽에서는 keepalive 데이터 하트비트 패킷을 전송합니다. 응답이 없으면 keepalive_intvl 시간 및 keepalive_probes 횟수마다 데이터 패킷을 다시 보냅니다. . 응답이 수신되지 않으면 연결을 종료하기 위해 첫 번째 패킷이 전송됩니다. 응답을 받으면 타이머가 지워집니다.
패킷을 캡처하여 tcp 하트비트 패킷의 내용을 확인하세요
패킷 캡처를 기반으로 keepalive에서 보내고 응답한 하트비트 패킷의 내용을 계속 분석합니다.
TCP 헤더의 소스 코드 구조는 다음과 같습니다.
typedef struct _tcp_header { short m_ssourport; // 源端口号16bit short m_sdestport; // 目的端口号16bit unsigned int m_uisequnum; // req字段 序列号32bit unsigned int m_uiacknowledgenum; //ack字段 确认号32bit short m_sheaderlenandflag; // 前4位:tcp头长度;中6位:保留;后6位:标志位 short m_swindowsize; //win字段 窗口大小16bit short m_schecksum; // 检验和16bit short m_surgentpointer; // 紧急数据偏移量16bit }__attribute__((packed))tcp_header, *ptcp_header;
보내진 하트비트 패킷의 내용을 살펴보세요:
0000 d4 6d 50 f5 02 7f f4 5c 89 cb 35 29 08 00 //mac头 14字节: 45 00 // ip头 20字节 : 0010 00 28 10 f4 00 00 40 06 5b dd ac 19 42 76 0a b3 0020 14 bd e4 4a 1f 7c 32 7e 7a cb 4c bc 55 08 50 10 // tcp头 20字节 0030 10 00 3f 00 00 00 //分析tcp头部内容 e4 4a //源端口号16bit 10进制为:58442 1f 7c //目的端口号16bit 10进制为 : 8060 32 7e 7a cb // req字段 序列号32bit 10进制为 : 4c bc 55 08 // ack字段 确认号32bit 5 // 前4位:tcp头长度 5*4 =20 字节 没问题 0 10 /// 中6位:保留;后6位:标志位 10 代表倒数第5位为1, 标识改tcp包为 ack 确认包 0030 10 00 3f 00 00 00
계속해서 응답 하트비트 패킷의 내용을 살펴보세요.
0000 f4 5c 89 cb 35 29 d4 6d 50 f5 02 7f 08 00 45 00 0010 00 34 47 28 40 00 36 06 ef 9c 0a b3 14 bd ac 19 0020 42 76 // 前面数据不解读 1f 7c e4 4a 4c bc 55 08 32 7e 7a cc 8// tcp头长度为8 * 4 = 32 除了头部 还有 选项数据 12字节 0 10 // 中6位:保留;后6位:标志位 10 代表倒数第5位为1, 标识该tcp包为 ack 确认包 0030 01 3f //win字段 窗口大小16bit 4e 0d // 检验和16bit 00 00 // 紧急数据偏移量16bit 01 01 08 0a 00 59 be 1c 39 13 0040 cf 12 // 选项数据 12字节
위에서 볼 수 있듯이 TCP의 하트비트 패킷은 긴 연결은 브라우저가 먼저 서버에 ack 패킷을 보낸 다음 서버가 ack 패킷으로 응답한다는 것입니다. 그리고
옵션 데이터가 사용 가능한 경우 nginx는 어떻게 keepalive 요청을 처리합니까?
首先做的是版本判断 :http协议版本低于1.1时,该链接的keepalive置为0 if (r->http_version < ngx_http_version_11) { r->keepalive = 0; } ngx_http_process_connection 函数中 ngx_http_request_t 中带有keep-alive则把改链接标识起来 if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) { r->headers_in.connection_type = ngx_http_connection_keep_alive; } ngx_http_handler函数中对r->headers_in.connection_type 判断,给r->keepalive赋值为1 switch (r->headers_in.connection_type) { case ngx_http_connection_keep_alive: r->keepalive = 1; break; } ngx_configure_listening_sockets函数中,当keepalive为1时,对该连接开启keepalive,之后tcp底层就会对该连接fd做检测死连接的机制,保持长连接,不断开。 if (ls[i].keepalive) { value = (ls[i].keepalive == 1) ? 1 : 0; if (setsockopt(ls[i].fd, sol_socket, so_keepalive,//开启keepalive功能 (const void *) &value, sizeof(int)) == -1) }
nginx의 오랜 연결은 언제 끊어지나요?
nginx가 setockopt(ls[i].fd, sol_socket, so_keepalive,(const void *) &value, sizeof(int))를 통해 keepalive를 켠 후에는 항상 클라이언트와의 긴 연결을 유지하므로 매우 심각한 문제 문제는 각 작업자가 유지할 수 있는 연결 수가 제한되어 있다는 것입니다(ep = epoll_create(cycle->connection_n/2); Cycle->connection_n/2는 epoll이 관리할 수 있는 fd의 상한입니다) 이런 식으로 연결 데이터가 빨리 소모됩니다. nginx는 이를 어떻게 처리해야 할까요?
이 답을 찾기 위해 keeoalive
keepalive_timeout
keepalive_timeout timeout [header_timeout];
에 대한 nginx의 두 가지 구성 매개변수를 살펴보겠습니다. 첫 번째 매개변수: 연결 유지 클라이언트 연결에 대한 시간 제한 값을 서버 측에서 열려 있도록 설정합니다(기본값) 75s); 값 0으로 설정하면 연결 유지 클라이언트 연결이 비활성화됩니다.
두 번째 매개변수: 선택 사항, 응답의 헤더 필드에 "keep-alive: timeout=time" 값을 설정합니다.
참고: keepalive_timeout 기본 75초
keepalive_requests
keepalive_requests 지시어는 연결 유지 연결에서 처리할 수 있는 최대 요청 수를 설정하는 데 사용됩니다. 최대 요청 수에 도달하면 연결이 닫힙니다. 0 값은 연결 유지 클라이언트 연결도 비활성화합니다. 기본값은 100입니다.
대답은 명확합니다. 긴 연결을 관리하려면 keepalive_timeout keepalive_requests를 사용하세요.
tcp 연결이 keepalive_timeout을 초과하면 nginx의 특정 구현이 타이머를 통해 완료됩니다. 연결 수가 keepalive_requests를 초과하면 이 두 가지 메커니즘은 각 작업자의 연결 수가 epoll이 관리할 수 있는 수를 초과하지 않도록 하는 데 사용됩니다.
위 내용은 nginx 킵얼라이브를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!