高負荷ネットワーク向けに Nginx と Node.js を最適化する方法

PHPz
リリース: 2023-05-13 13:31:06
転載
720 人が閲覧しました

ネットワークチューニング
まずnginxとnode.jsの基礎となる送信メカニズムを理解し、ターゲットを絞った最適化を実行しないと、2つのチューニングをどれほど詳細に行ったとしても、無駄です。通常、nginx は tcp ソケットを介してクライアントと上流アプリケーションを接続します。
私たちのシステムには、カーネル パラメータを通じて設定される tcp のしきい値と制限が多数あります。これらのパラメータのデフォルト値は一般的な目的のために設定されていることが多く、Web サーバーの高トラフィックと短い寿命の要件を満たすことができません。
TCP を調整するためのパラメーターをいくつか示します。これらを有効にするには、それらを /etc/sysctl.conf ファイルに入れるか、/etc/sysctl.d/99-tuning.conf などの新しい構成ファイルに入れてから sysctl -p を実行します。カーネルにそれらをロードさせます。この物理的な作業には sysctl-cookbook を使用します。
ここにリストされている値は安全に使用できますが、負荷、ハードウェア、および使用状況に基づいてより適切な値を選択するために、各パラメーターの意味を検討することをお勧めします。

コードをコピーしますコードは次のとおりです:

net .ipv4.ip_local_port_range='1024 65000'
net.ipv4.tcp_tw_reuse='1'
net.ipv4.tcp_fin_timeout='15'
net.core.netdev_max_backlog='4096'
net. core.rmem_max ='16777216'
net.core.somaxconn='4096'
net.core.wmem_max='16777216'
net.ipv4.tcp_max_syn_backlog='20480'
net.ipv4。 tcp_max_tw_buckets=' 400000'
net.ipv4.tcp_no_metrics_save='1'
net.ipv4.tcp_rmem='4096 87380 16777216'
net.ipv4.tcp_syn_retries='2'
net.ipv4。 tcp_synack_retries=' 2'
net.ipv4.tcp_wmem='4096 65536 16777216'
vm.min_free_kbytes='65536'

重要なもののいくつかを強調表示します。
net.ipv4.ip_local_port_range
上流アプリケーションのために下流クライアントにサービスを提供するには、nginx は 2 つの TCP 接続を開く必要があります。1 つはクライアントに接続し、もう 1 つはアプリケーションに接続します。サーバーが多数の接続を受信すると、システムの使用可能なポートがすぐに枯渇してしまいます。 net.ipv4.ip_local_port_range パラメータを変更すると、使用可能なポートの範囲を増やすことができます。 /var/log/syslog で「ポート 80 で syn フラッディングが発生している可能性があります。Cookie を送信しています」というエラーが見つかった場合は、システムが使用可能なポートを見つけられないことを意味します。 net.ipv4.ip_local_port_range パラメータを増やすと、このエラーを減らすことができます。
net.ipv4.tcp_tw_reuse
サーバーが多数の TCP 接続を切り替える必要がある場合、time_wait 状態の接続が多数生成されます。 time_wait は、接続自体は閉じられていますが、リソースは解放されていないことを意味します。 net_ipv4_tcp_tw_reuse を 1 に設定すると、カーネルは安全なときに接続をリサイクルしようとします。これは、新しい接続を再確立するよりもはるかに安価です。
net.ipv4.tcp_fin_timeout
これは、time_wait 状態の接続がリサイクルするまで待機する必要がある最小時間です。小さくすることでリサイクルを早めることができます。
接続ステータスを確認する方法
netstat:
netstat -tan | awk '{print $6}' | sort | uniq -c
または ss:
を使用します。 ss - s
nginx
ss -s
total: 388 (カーネル 541)
tcp: 47461 (estab 311、クローズド 47135、孤立 4、synrecv 0、timewait 47135/0)、ポート 33938
トランスポート合計 ip ipv6
* 541 - -
raw 0 0 0
udp 13 10 3
tcp 326 325 1
inet 339 335 4
frag 0 0 0
Web サーバーの負荷が徐々に増加すると、nginx の奇妙な制限に遭遇し始めます。接続が切断され、カーネルは syn フラッドを報告し続けます。現時点では、負荷平均と CPU 使用率は非常に小さく、サーバーは明らかにより多くの接続を処理できるため、非常にイライラします。
調査の結果、time_wait 状態の接続が多数あることが判明しました。これはサーバーの 1 つからの出力です:
time_wait 接続が 47,135 個あります!また、ss を見ると、それらはすべて閉じた接続であることがわかります。これは、サーバーが使用可能なポートのほとんどを消費したことを示し、サーバーが接続ごとに新しいポートを割り当てていることも意味します。ネットワークを調整することで問題は少し解決しましたが、それでも十分なポートがありませんでした。
さらに調査した結果、アップストリーム接続キープアライブ ディレクティブに関するドキュメントを見つけました:
アップストリーム サーバーへのアイドル キープアライブ接続の最大数を設定します。これらの接続はワーカー プロセスのキャッシュに保持されます。 。 ###面白い。理論的には、この設定では、キャッシュされた接続を介してリクエストを渡すことにより、無駄な接続が最小限に抑えられます。ドキュメントには、proxy_http_version を「1.1」に設定し、「connection」ヘッダーをクリアする必要があるとも記載されています。さらに調査した結果、http/1.1 は http1.0 に比べて tcp 接続の使用を大幅に最適化し、nginx はデフォルトで http/1.0 を使用するため、これは良いアイデアであることがわかりました。
ドキュメントの推奨事項に従って変更すると、アップリンク構成ファイルは次のようになります:

コードをコピーします。コードは次のとおりです:

アップストリーム backend_nodejs {
サーバー nodejs-3:5016 max_fails=0 フェイル_タイムアウト=10s;
サーバー ノードjs-4:5016 max_fails=0 フェイルタイムアウト=10秒;
サーバー ノードjs-5:5016 max_fails=0また、提案に従ってサーバー セクションのプロキシ設定も変更しました。 。同時に、失敗したサーバーをスキップするために proxy_next_upstream が追加され、クライアントの keepalive_timeout が調整され、アクセス ログがオフになりました。構成は次のようになります。


コードをコピーします。コードは次のとおりです。

server {
listen 80;

server_name fast.gosquared.com;

client_max_body_size 16m;

keepalive_timeout 10;

location / {
proxy_next_upstream エラー タイムアウト http_500 http_502 http_503 http_504;
proxy_set_header 接続 "";
proxy_http_version 1.1;
proxy_pass http://backend_nodejs;
}
access_log off;
error_log /dev/null crit;
}

新しい構成を採用した後、サーバーが占有するソケットが 90% 削減されたことがわかりました。 。はるかに少ない接続を使用してリクエストを送信できるようになりました。新しい出力は次のとおりです。
ss -s
total: 558 (kernel 604)
tcp: 4675 (estab 485、closed 4183、orphaned 0、synrecv 0、timewait 4183/0)、ports 2768

transport total ip ipv6

* 604 - -
raw 0 0 0
udp 13 10 3
tcp 492 491 1
inet 505 501 4
node.js
got I/O を非同期に処理するイベント駆動型の設計のおかげで、Node.js はすぐに大量の接続とリクエストを処理できます。他にもチューニング方法はありますが、この記事では主にnode.jsのプロセス面に焦点を当てます。
ノードはシングルスレッドであり、複数のコアを自動的に使用しません。つまり、アプリケーションはサーバーのすべての機能を自動的に取得できません。

ノード プロセスのクラスタリングの実現

複数のスレッドをフォークし、同じポートでデータを受信するようにアプリケーションを変更することで、負荷が複数のコアにまたがることが可能になります。 Node には、この目標を達成するために必要なすべてのツールを提供するクラスター モジュールがありますが、それらをアプリケーションに追加するには多くの手作業が必要です。 Expressを使用している場合、eBayにはcluster2というモジュールがあり、それを使用できます。

コンテキスト切り替えの防止複数のプロセスを実行する場合、各 CPU コアが同時に 1 つのプロセスのみでビジーになるようにする必要があります。一般に、CPU に n 個のコアがある場合、n-1 個のアプリケーション プロセスを生成する必要があります。これにより、各プロセスが適切なタイム スライスを取得し、カーネル スケジューラが他のタスクを実行できるように 1 つのコアが空きます。また、CPU 競合を防ぐために、基本的に、node.js 以外の他のタスクがサーバー上で実行されないようにする必要もあります。
私たちはかつて間違いを犯し、サーバー上に 2 つの Node.js アプリケーションをデプロイしてしまい、各アプリケーションが n-1 個のプロセスを開きました。その結果、CPU を奪い合うことになり、システム負荷が急激に上昇します。当社のサーバーはすべて 8 コア マシンですが、コンテキストの切り替えによって生じるパフォーマンスのオーバーヘッドは依然としてはっきりと感じられます。コンテキストスイッチングとは、CPU が他のタスクを実行するために現在のタスクを一時停止する現象を指します。切り替えるとき、カーネルは現在のプロセスのすべての状態を一時停止してから、別のプロセスをロードして実行する必要があります。この問題を解決するために、各アプリケーションが起動するプロセスの数を減らし、CPU を公平に共有できるようにし、その結果、システムの負荷が軽減されました。上の図に注目してシステムを見てください。負荷 (青線) が CPU コア数 (赤線) を下回っている様子を確認してください。他のサーバーでも同じことが確認されました。合計のワークロードは同じままであるため、上のグラフのパフォーマンスの向上はコンテキスト スイッチの減少によるものとしか考えられません。
順不同:


1. パフォーマンスの問題が発生した場合、アプリケーション層で計算と処理が実行できる場合は、データベース層から計算と処理を実行します。出てくる。並べ替えとグループ化は典型的な例です。データベース層よりもアプリケーション層のパフォーマンスを向上させる方が常に簡単です。 MySQL と同様に、sqlite は制御が簡単です。
高負荷ネットワーク向けに Nginx と Node.js を最適化する方法2. 並列コンピューティングに関しては、できる限り避けるようにしてください。それが避けられない場合は、大きな力には大きな責任が伴うことを思い出してください。可能であれば、スレッド上で直接操作することは避けてください。可能な限り、より高い抽象レベルで動作します。たとえば、iOS では、GCD、ディストリビューション、キュー操作が友達になります。人間の脳は無限の一時的な状態を分析するようには設計されていません - 私はこれを苦労して学びました。

3. 状態を可能な限り単純化し、可能な限りローカライズします。適用性が第一です。

4. 短くて組み合わせ可能なメソッドが味方です。

5. コードのコメントは、古くなったり誤解を招きやすいため危険ですが、だからといってコメントを書かない理由にはなりません。些細なことについてはコメントしないでください。ただし、必要に応じて、特別な場所では長い戦略的なコメントが必要です。おそらく明日の朝、コーヒーを一杯飲んだ後、あなたの記憶はあなたを裏切るでしょう。

6. ユースケース シナリオが「大丈夫」かもしれないと思った場合、1 か月後にリリースされた製品で大失敗する可能性があります。懐疑的になり、テストし、検証してください。

7. 疑問がある場合は、チームの全員に相談してください。

8. 正しいことをしましょう—通常、それが何を意味するかあなたは知っています。

9. ユーザーは愚かではなく、ショートカットを理解する忍耐力がないだけです。

10. 開発者があなたが開発したシステムを長期間保守する予定がない場合は、その開発者に注意してください。ソフトウェアのリリース後、血、汗、涙の 80% が流されます。そうすれば、あなたは人間嫌いになりますが、より賢い「鑑定家」にもなります。

11. ToDo リストはあなたの親友です。

12. 仕事をもっと楽しくするために率先して行動しましょう。これには時にはあなたの努力が必要です。

13. 静かなメルトダウン、今でも悪夢で目が覚めます。モニタリング、ロギング、アラート。さまざまな誤報や避けられない感覚の鈍化に注意してください。システムの障害に対する警戒をタイムリーに保ちます。

以上が高負荷ネットワーク向けに Nginx と Node.js を最適化する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!