Nginnxのclient_header_ブザーsizeとlarge_clientheader_勉強します

7757 ワード

前にある人が書いているのを見ましたが、nginx配置についてのlarge_clientheader_buffersの問題をまとめた文章で、その中で言及しています。
largeclientheader_buffersはserver{}内でも有効ですが、nginxの主な構成における値を下回るだけが意味があります。
この結論に対して、私は疑問を持っています。このデザインはおかしいと思います。自分でテストをしました。もっと深く理解してほしいです。
テスト方法
nginx主構成に構成項目を追加します。(主構成ではheaderサイズを1 kに制御します。)
http {
    include  mime.types;
    default_type  application/octet-stream;
    large_client_header_buffers  4 1k;
    ......
}
すべての干渉vhostを削除し、一つだけを残します。
server {
    listen 80;
    server_name  www.job360.com;
    large_client_header_buffers  4 1m;
    ......
}
構造要求のshell:(構造headerが1 kを超える要求)
#!/bin/bash

url="http://www.job360.com/test.html?debug=1"

for i in {0..1000}
do
    var="v$i"
    url="${url}&$var=$i"
done

curl $url -x 127.0.0.1:80 -v
初めてのテスト結果
テストで得られた結果は前に見た文章とは違って、この長url要求はinxによって処理されました。
どうですか?だから文章の中の環境と違って、重要な点を発見しました。私はこのvhostしか持っていません。
そして、もう一つのvhostを追加して、vhostの構成を追加しました。
server {
    listen 80;
    server_name db.job360.com;
    ......}
第二次試験結果
テストでは、nginxは依然としてこの長url要求を処理することができます。
改めて違った点を考えてみると、これらのvhostは主な構成のincludeによって入力されたもので、読み取り順序と関係があるのではないかと思います。
このように構成を再調整し、2つのvhostを1つのconfファイルに配置すると、以下のように構成される。
server {
    listen 80;
    server_name db.job360.com;
    ......
}

server {
    listen 80;
    server_name  www.job360.com;
    large_client_header_buffers  4 1m;
    ......
}
第三次試験結果
文章と同じ結果が得られ、inxは414 Request-URI Too Largeに戻る。
好奇心を持って、次の2つのvhostの順番を逆にしました。
server {
    listen 80;
    server_name  www.job360.com;
    large_client_header_buffers  4 1m;
    ......
}

server {
    listen 80;
    server_name db.job360.com;
    ......
}
第四回試験結果
この長url要求をうまく処理しました。
初歩的な結論
上記の現象を通して、最初のvhostに配置されたlarge_clientheader_buffersパラメータが働きます。
変な現象ですね。私も自分の結論に疑問を持っています。マニュアルをよく読んで、headerをコントロールすることにしました。ブザー関連のコマンドです。
ハンド・バックの上からinxを理解してheader_に関します。ブザー配置指令
マニュアルから二つのコマンドとheader_があります。ブザー関係:
  • client_header_ブザーsize
  • large_clientheader_バファーズ
  • inxに対してheaderを処理する時の方法は、学習後に次のように理解されます。
  • 要求されたrequest_を先に処理する。LINE、その後はレクリエーションです。header
  • の両者のバffer割り当てポリシーは同じである。
  • とりあえずclientによって。header_ブザーsize配置の値は一つのブザーを割り当てていますが、割り当てられたブザーはrequest_を収容できません。LINE/request_header、それでは再度large_によってできます。clientheader_buffers配置のパラメータ割り当てlarge_ブザー、もしlarge_バfferがまだ収容できないなら、414(request ulineを処理する)/400(request headerを処理する)エラーに戻ります。
  • マニュアルの理解によって、この二つの命令はheader auを配置していることが分かります。ブザー時の使用シーンは違っています。個人的には次のように理解しています。
  • もしあなたの要求の中のheaderが大きいなら、client(u)を使うべきです。header_ブザーこのようにしてメモリの割り当てを一度減らすことができます。
  • もしあなたの要求の中で少量だけheaderが大きいなら、large_を使うべきです。clientheader_バffersは、このように大きなheaderを処理する時だけ、より多くの空間を割り当てるので、無駄なメモリ空間の浪費を減らします。
  • 二つの構成指令に対する自分の理解を実証するために、私はlargeを上げます。clientheader_ブザーをclient_に換えるheader_ブザーsizeは、上の様々なテストを走り直して、前の各シーンと同じ結論を得ました。
    マニュアルでもこの二つのコマンドの使用シーンを説明しただけで、これ以上のものは言われませんでした。前の疑問はまだ答えられませんでした。最後の一手だけです。
    ソース学習
    ここはclientからですheader_ブザーsizeコマンドを入手して、このコマンドの定義部分を確認してください。
    { ngx_string("client_header_buffer_size"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,              //     http{} server{} ,        
      ngx_conf_set_size_slot,                                           //     size,  nginx      size      
      NGX_HTTP_SRV_CONF_OFFSET,                                         //      srv   conf 
      offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),    //     ngx_http_core_srv_conf_t    client_header_buffer_size 
      NULL },
    
    src/http/ngx_http_core_module.c
    
    定義から見て、私達がServer{}で解析した値はhttp{}の中の値と一回mergeして、このserver{}の下の最終値とします。merge関連のロジックを見る:
    ngx_conf_merge_size_value(conf->client_header_buffer_size,        //conf  server{},prev  http{}
                              prev->client_header_buffer_size, 1024); 
    
    src/http/ngx_http_core_module.c
    
    #define ngx_conf_merge_size_value(conf, prev, default)                       \
        if (conf == NGX_CONF_UNSET_SIZE) {                                       \
            conf = (prev == NGX_CONF_UNSET_SIZE) ? default : prev;               \
        }
    
    src/core/ngx_conf_file.h
    
    このロジックから結論を得ました。もし私達がserver{}にclient(u)を配置したらheader_ブザーsizeなら、このserver{}ブロックの最終値は私達が設定した値であるべきです。
    私の結論を確認するために、vhost配置を書き直して、コードにデバッグ情報を入れて、最終結果をプリントアウトしました。
    http {
        include  mime.types;
        default_type  application/octet-stream;
        large_client_header_buffers  4 1k;
        ......
    
        server {
            listen 80;
            server_name db.job360.com;
            ......
        }
    
        server {
            listen 80;
            server_name  www.job360.com;
            large_client_header_buffers  4 1m;
            ......
        }
    }
    
    デバッグコード:
        printf("buffer before merge:
    child: %lu
    parent: %lu

    ", conf->client_header_buffer_size, prev->client_header_buffer_size); ...... ngx_conf_merge_size_value(conf->client_header_buffer_size, prev->client_header_buffer_size, 1024); ...... printf("buffer after merge:
    child: %lu
    parent: %lu

    ", conf->client_header_buffer_size, prev->client_header_buffer_size); src/http/ngx_http_core_module.c
    nginxを再コンパイルして、各server{}の中でclient_をテストします。header_ブザーsizeの最終値は以下の通りです。
    buffer before merge:
    child: 18446744073709551615    //     server{}     ,     -1(NGX_CONF_UNSET_SIZE) unsigned long int  
    parent: 1024    //http{}    1k
    
    buffer after merge:
    child: 1024
    parent: 1024
    
    buffer before merge:
    child: 1048576    //   server{}    1m
    parent: 1024
    
    buffer after merge:
    child: 1048576
    parent: 1024
    
    値の最終結果から見ると、確かに前に設定した1 mですが、要求時には414に戻りました。
    二つのserver{}の位置を逆さまにしてから正常に要求を処理することができますので、逆さまにして最終値をテストしました。出力は以下の通りです。
    buffer before merge:
    child: 1048576
    parent: 1024
    
    buffer after merge:
    child: 1048576
    parent: 1024
    
    buffer before merge:
    child: 18446744073709551615
    parent: 1024
    
    buffer after merge:
    child: 1024
    parent: 1024
    
    最終値の出力はまだ1 mですが、今回は正常処理要求ができます。
    inxは実際に要求を処理する過程で、きっと前に知らなかったロジックがあります。header_ブザーsizeの最終値
    inx処理要求時の関連コードは以下の通りです。
        ngx_http_core_srv_conf_t   *cscf;
    ......
        /* the default server configuration for the address:port */
        cscf = addr_conf->default_server;
    ......
        if (c->buffer == NULL) {
            c->buffer = ngx_create_temp_buf(c->pool,
                                            cscf->client_header_buffer_size);
    
    src/http/ngx_http_request.c
    
    ここは明らかです。
    元々はclientですheader_ブザーsizeの最終値は、nginxが解析conf後、default_server中にmergeを経た最終値。
    default_serverのnginxでの定義は、listen命令で定義されています。
    The default_server parameter,if present,will cause the server to become the default server for the specified address:port pair.If none of the directives have the default_。server parameter the n the first server with the address:port pair will be the default server for this pair.
    この点を検証するために、私はvhost構成を修正しました。
    server {
        listen 80;
        server_name db.job360.com;
        ......
    }
    
    server {
        listen 80 default;
        server_name  www.job360.com;
    
        large_client_header_buffers  1m;
        ......
    }
    
    nginxを再開し、mergeの結果を観察します。
    buffer before merge:
    child: 18446744073709551615
    parent: 1024
    
    buffer after merge:
    child: 1024
    parent: 1024
    
    buffer before merge:
    child: 1048576
    parent: 1024
    
    buffer after merge:
    child: 1048576
    parent: 1024
    
    mergeの結果は違いませんでした。この要求をテストしました。今回のnginxはこの要求をうまく処理しました。予想された効果と一致しました。
    結尾語
    筆者はまたlargeをテストしました。clientheader_buffers、入手とclient_header_ブザーsizeと同じ結果です。結論を出すことができます。inxはheaderを扱う時に実際に割り当てられたbufferサイズです。解析confの後、default_です。serverの最終値。
    個人レベルは限られています。上のテスト方法と理解に問題があれば、ご指摘をお願いします。ありがとうございます。