ホームページ  >  記事  >  運用・保守  >  nginxキープアライブの使い方

nginxキープアライブの使い方

PHPz
PHPz転載
2023-05-19 14:13:131682ブラウズ

図に示すように、デフォルトの http1.1 プロトコル リクエスト ヘッダーでは、デフォルトでキープアライブが有効になります。

nginx keepalive如何使用

それでは、キープアライブとは何でしょうか。機能は何ですか?

keepalive は、切断された接続を検出できる TCP のメカニズムです。その機能は、長いソケット接続が切断されないようにすることです。これは TCP 層の機能であり、アプリケーション層には属しません。

TCP 層はどのようにして長い接続を維持するのでしょうか?

まずキープアライブの使用法を見てみましょう: アプリケーション層に公開されている 3 つのパラメーターがあります。

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 ハートビート パケットの内容を確認します

nginx 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 はそれをどのように処理しますか?キープアライブ リクエストはどうなりますか?

首先做的是版本判断 :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 は、setsockopt(ls[i].fd, sol_socket, so_keepalive, (const void *) &value, sizeof(int)) を通じてキープアライブを開いた後、常にクライアントとの長い接続を維持します。これは非常に深刻な問題を引き起こします。各ワーカーが維持できる接続の数は制限されています (ep = epoll_create(cycle->connection_n / 2);cycle->connection_n / 2 は epoll が実行できる fd の上限です) manage) を実行すると、接続数がすぐに枯渇してしまいます。nginx はこれをどのように処理すればよいでしょうか?

この答えを見つけるために、keeoalive に関する nginx の 2 つの構成パラメータを見てみましょう

keepalive_timeout

keepalive_timeout timeout [header_timeout];

最初のパラメータ: 接続するキープアライブ クライアントを設定しますサーバーへのクライアントを開いたままにするためのタイムアウト値 (デフォルトは 75 秒)。値 0 はキープアライブ クライアント接続を無効にします。

2 番目のパラメーター: オプションで、値「キープアライブ」を設定します。応答のヘッダー フィールド : timeout=time”; 通常は設定する必要はありません。

注: keepalive_timeout のデフォルトは 75 秒です。

keepalive_requests

keepalive_requests コマンドは、キープアライブ接続で処理できるリクエスト リクエストの最大数に達したときに閉じる接続の最大数。値を 0 にすると、キープアライブ クライアント接続も無効になります。デフォルトは 100 です。
答えは明白です。長い接続を管理するには、keepalive_timeout keepalive_requests を使用してください。

  • TCP 接続が keepalive_timeout よりも長く存続すると、閉じられます。nginx の具体的な実装は、

  • #TCP 接続のラブレターの最大数が keepalive_requests を超えると、接続も閉じられます

を通じて保証されますこれら 2 つのメカニズム ワーカーあたりの接続数は、epoll が管理できる数を超えることはありません。

以上がnginxキープアライブの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。