nginxでの共有メモリの使用に関する詳細な説明

nginxでの共有メモリの使用に関する詳細な説明

nginx プロセス モデルでは、トラフィック統計、トラフィック制御、データ共有などのタスクを完了するには、複数の作業プロセスが連携して動作する必要があります。共有メモリは、重要なプロセス通信ソリューションです。この記事では、ngx_shmem と ngx_slab の使い方や注意点など、nginx コード内の共有メモリに関連する機能を紹介しますが、ngx_slab に実装されているメモリ管理アルゴリズムについては取り上げません。

ngx_shmemの使用

ngx_shmem.c/h ファイルは、mmap()/munmap() システム コールまたは shmget()/shmdt() の非常に単純なラッパーです。連続した共有メモリ空間の申請と解放が可能な ngx スタイルの基本ライブラリを実装しました。一般的には固定長の共有データに使用されます。使用中はデータ長が固定され、拡張または縮小されません。

typedef構造体{
  u_char *アドレス;
  size_t サイズ;
  ...
} ngx_shm_t;
shm は、 ngx_int_t 型の配列です。
ngx_shm_free() を呼び出します。

ngxin における共有メモリの使用プロセスは、通常、マスタープロセスによって作成され、ワー​​カープロセスは継承によってメモリポインタを取得します。

ngx_shmem の使用については、ngx_event_module_init() のいくつかのスニペットを参照できます。コードのこの部分では、共有メモリにいくつかの変数を作成し、各状態 (承認済み/読み取り/書き込み中など) のリクエスト数を記録し、ngx_event_module のいくつかの主要なイベント エントリでこれらの変数の統計の加算と減算を実行します。すべてのワーカー プロセスの現在の要求ステータスに関する統計を実装します。

shm.size = サイズ;
ngx_str_set(&shm.name, "nginx_shared_zone");
shm.log = サイクル->ログ;

ngx_shm_alloc(&shm) が NGX_OK の場合 {
  NGX_ERROR を返します。
}

共有 = shm.addr;
...
ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
ngx_stat_handled = (ngx_atomic_t *) (共有 + 4 * cl);
ngx_stat_requests = (ngx_atomic_t *) (共有 + 5 * cl);
ngx_stat_active = (ngx_atomic_t *) (共有 + 6 * cl);
ngx_stat_reading = (ngx_atomic_t *) (共有 + 7 * cl);
ngx_stat_writing = (ngx_atomic_t *) (共有 + 8 * cl);
ngx_stat_waiting = (ngx_atomic_t *) (共有 + 9 * cl);

この機能の詳細については、NGX_STAT_STUB マクロ定義とコード内の ngx_http_stub_status_module を参照してください。

ngx_slabの使用

ngx_shmem は、共有メモリの基本機能を実装する最小限のカプセル化です。ただし、プログラム内の共有データのほとんどは固定サイズの構造ではなく、ngx_array、ngx_list、ngx_queue、ngx_rbtree などのデータ構造のサイズは変更できます。

動的にスペースを要求および解放できる ngx_pool_t のようなメモリ プールが必要になると予想されます。 ngx_slab はそのような構造です。原理的には、一連のアルゴリズムを使用してメモリ セグメントを適用および解放するという点で、システムの malloc() に似ています。ただ、ngx_slab が操作するオブジェクトは ngx_shmem に基づく共有メモリです。

まずはngx_slabのインターフェースを見てみましょう

typedef構造体{
  ngx_shmtx_t ミューテックス;
  ...
  void *data; /* 通常はプールから取得したルートデータアドレス(プールで要求された最初のデータインターフェイス)を格納します */
  void *addr; /* ngx_shmem を使用して共有メモリのベースアドレスを取得します*/
} ngx_slab_pool_t;

ngx_slab_init() を呼び出します。
void *ngx_slab_alloc(ngx_slab_pool_t *プール、size_t サイズ);
void *ngx_slab_alloc_locked(ngx_slab_pool_t *プール、size_t サイズ);
void *ngx_slab_calloc(ngx_slab_pool_t *プール、size_t サイズ);
void *ngx_slab_calloc_locked(ngx_slab_pool_t *プール、size_t サイズ);
ngx_slab_free は、プールからデータを解放します。
ngx_slab_free_locked を void に設定します。

インターフェースは複雑ではないことがわかります。alloc と calloc の違いは、アプリケーションが取得したメモリ セグメントがクリアされるかどうかにあります。_locked で終わるインターフェースは、操作対象のプールがすでにロックを取得していることを示します。 ngx_slab_pool_t 構造には、複数のプロセスが同時にプールにアクセスする同時シナリオを同期するために使用される ngx_shmtx_t ミューテックス ロックがあります。 ngx_slab_alloc() は最初にロックを取得し、次にスペースを適用し、最後にロックを解放することに注意してください。ただし、ngx_slab_alloc_locked() は、プログラムがすでに他のロジックでロックを取得していると想定して、スペースに直接適用されます。

nginx 開発で ngx_shmem を使用するには、通常、次の初期化プロセスが必要です。

  • モジュールは、構成解析プロセス中に ngx_shared_memory_add() インターフェースを呼び出して、共有メモリ セグメントを登録します。共有メモリのサイズとメモリの初期化のためのコールバック関数を提供します。
  • フレームワークは、ngx_shmem を使用して ngx_init_cycle() でメモリを適用し、ngx_slab を初期化してから、モジュールによって登録された初期化関数をコールバックします。
  • ngx_slab を使用したモジュールのアプリケーション/インターフェース

このプロセスには、ngx_shared_memory_add() インターフェースと対応する ngx_shm_zone_t 構造が関与します。

構造体 ngx_shm_zone_s {
  void *データ;
  ngx_shm_t shm;
  ngx_shm_zone_init_pt を初期化します。
  void *タグ;
  void *同期;
  ngx_uint_t noreuse; /* 符号なし noreuse:1; */
};
ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
  size_t サイズ、void *タグ);

その中でも、nginx のリロード プロセス中に共有メモリが再適用されるかどうかを制御する noreuse 属性について言及する価値があります。

ngx_init_cycle() 関数は長いため、コメント /* create shared memory */ または cycle->shared_memory オブジェクトを探すことで、関連するコードを表示できます。

ngx_slab の使用に関する詳細については、共有メモリを介して接続制限を実装するモジュールである ngx_http_limit_conn_module を参照することをお勧めします。このモジュールは複雑さが低く、優れた参考例です。

参考文献

Nginx 徹底理解(第 2 版) https://book.douban.com/subject/26745255/

ngx_http_limit_conn_module http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • nginx共有メモリの仕組みの詳細な説明

<<:  MySQL パフォーマンスの包括的な最適化方法リファレンス、CPU、ファイルシステムの選択から mysql.cnf パラメータの最適化まで

>>:  JS for ループで setTimeout を使用する 4 つのソリューション

推薦する

Reactは感情を使ってCSSコードを書く

目次導入:感情のインストール:一般的な CSS コンポーネントを追加します。既存のコンポーネントにス...

MySQLエラー10061を解決する方法

この記事では、「'localhost' (10061) の MySQL サーバーに接...

Maxwell を使用して MySQL データをリアルタイムで同期する方法

目次マクスウェルについてMaxwellの設定と使用1. Maxwellインストールパッケージをダウン...

Vueは小さなメモ帳機能を実装しました

この記事の例では、メモ帳の小さな機能を実現するためのvueの具体的なコードを参考までに共有しています...

win10環境でDockerをインストールする実装

1. Docker公式サイトにアクセスするまず、Dockerの公式ウェブサイトにアクセスして、最新の...

シェルでパスワードなしでMySQLデータベースに素早くログインする方法

背景Shell の mysql-client を介して MySQL データベースにログインする場合、...

Docker Compose ワンクリック ELK デプロイ方式の実装

インストールFilebeat は、より軽量でより安全なため、Logstash-Forwarder に...

Vue.js で AntV X6 を使用する手順の例

目次0x0 はじめに0x1 インストール0x2 ノードサイドバー0x3 統合例0x0 はじめにプロジ...

バージョン管理ツール Rational ClearCase の紹介

Rational ClearCase は、コードやその他のソフトウェア開発資産のバージョン管理を実...

jQueryは居住地を選択するためのドロップダウンボックスを実装します

居住地を選択するためのドロップダウンボックスをjQueryで実装するための具体的なコードは参考までに...

Linux での GDB 入門チュートリアル

序文gdb は Linux で非常に便利なデバッグ ツールです。コマンドライン モードのデバッグ ツ...

JavaScriptタイマーとボタン効果設定の詳細な説明

タイマー効果: <div> <font id='timeCount'...

Vue3の組み込みコンポーネントであるTeleportの使い方を詳しく説明します

目次1. テレポートの使用2. モーダルダイアログコンポーネントを完成させる3. コンポーネントのレ...

uni-appがNFC読み取り機能を実装

この記事では、参考までに、NFC読み取り機能を実装するためのuni-appの具体的なコードを紹介しま...

Mysql テーブル、列、データベースの追加、削除、変更、クエリの問題の概要

以下は私がまとめた基本的なSQL知識です。主に参考資料として、また将来の他の初心者の助けとして、私自...