ホームページ  >  記事  >  バックエンド開発  >  nginx ソースコード学習メモ (21) - イベント モジュール 2 - イベント駆動型コア ngx_process_events_and_timers

nginx ソースコード学習メモ (21) - イベント モジュール 2 - イベント駆動型コア ngx_process_events_and_timers

WBOY
WBOYオリジナル
2016-07-29 09:11:021730ブラウズ

まず最初に、前のサブスレッド実行操作には関与しないコンテンツ ngx_process_events_and_timers があることを思い出してください。今日はこの関数を学習します。

この記事の引用元: http://blog.csdn.net/lengzijian/article/details/7601730

セクション 19 のスクリーンショットをいくつか見てみましょう:

nginx 源码学习笔记(二十一)—— event 模块二 ——事件驱动核心ngx_process_events_and_timers

今日はイベント駆動関数、図の赤い部分を中心に説明します:

[cpp]ビュー 普通のコピープリント?

  1. src/event/ngx_event.c
  2. void
  3. ngx_process_events_and_timers(ngx _cycle_t *サイクル)
  4. {
  5. ngx_uint_t フラグ
  6. ngx_msec_t タイマー、デルタ;
  7. (ngx_timer_resolution) { 時間 r = NGX_TIMER_INFINITE ;
  8. } 他の
  9. {
  10. タイマー = ngx_event_find_timer();
  11. フラグ = NGX_UPDATE_TIME } /*
  12. ngx_use_accept_mutex 変数は、ミューテックス
  13. を使用するかどうかを表します
  14. はデフォルトで使用され、accept_mutex off コマンドを使用してオフにできます。
  15. ngx_accept_disabled 変数は ng で計算されます。 x_event_accept 関数。
  16. ngx_accept_disabled が 0 より大きい場合、プロセスが受け入れるリンクが多すぎることを意味します。
  17. したがって、受け入れミューテックスを獲得するために競合する機会を放棄し、自分自身を 1 つ減らします。
  18. 次に、既存の接続でイベントの処理を続けます。
  19. nginx はこれを利用して、継承された接続の基本的な負荷分散を実装します。
  20. ngx_accept_disabled-- ;
  21. /* ミューテックスのロックを正常に取得した場合にのみ、Listen は EPOLL にワードを入れることができます。
  22. したがって、これにより、1 つのプロセスだけが listen ソケットを持つことが保証されるため、すべてのプロセスが epoll_wait でブロックされた場合でも、
  23. はグループパニックを引き起こしません。
  24. プロセスがロックを取得すると、NGX_POST_EVENTS フラグが追加されます。
  25. このフラグの機能は、生成されたすべてのイベントを キュー に入れ、イベントが解放された後にゆっくりと処理することです。 - - 処理される、処理されるなど。効率は低い。 ️
  26. } else{
  27. 未取得 結果のプロセスには、当然のことながら、NGX_POST_EVENTS フラグは必要ありません。
  28. ただし、ロックを争う前に遅延時間を設定する必要があります。
  29. */
  30. (タイマー == ngx_timer_infinite
  31. || タイマー & gt; ex_dlay) {
  32. タイマー = ngx_acceth_mutex_lay
  33. delta = ngx_current_msec;
  34. /*次に、epoll は待機イベントを開始します
  35. ngx_process_events の具体的な実装epoll モジュールの ngx_epoll_process_events 関数に対応します
  36. ここで詳しく説明します
  37. */
  38. ( void
  39. ) ngx_process_events(cycle, timer, flags);
  40. / / 統計この待機イベントの消費時間
  41. delta = ngx_current_msec-delta
  42. ngx_log_debug1(NGX_LOG_DEBUG_EVENT,cycle->log, 0,
  43. /*
  44. ngx_posted_accept_events はイベント
  45. queue であり、リッスンソケットからの受け入れイベント epoll 待機を一時的に保存します。
  46. 上記の NGX_POST_EVENTS フラグが使用された後、すべての受け入れイベントはこの
  47. キューに一時的に保存されます
  48. */
  49. if
  50. (ngx_posted_accept_events ) {
  51. ngx_event_process_posted(cycle, &ngx_posted_accept_events);
  52. } //すべての受け入れイベントが処理された後、ロックが保持されている場合は解放します。
  53. if (ngx_accept_mutex_held) {
  54. ngx_shmtx_unlock(&ngx_accept_mutex) }
  55. /*
  56. デルタは前です統計的に時間がかかる場合は、ミリ秒レベルの時間がかかる場合は、すべての時刻のタイマーを確認します。
  57. タイムアウトの場合は、時間切れのタイマーを時間 rbtree から削除し、そのハンドラー関数を呼び出します。処理する対応するイベント
  58. */
  59. if
  60. (delta) {
  61. ngx_event_expire_timers();
  62. }
  63. ngx_log_debug1 (NGX_LOG_DEBUG_EVENT、サイクル>ログ、0、
  64. /*
  65. 通常のイベントの処理 (接続イベントで取得されたデータの読み取りおよび書き込み)、
  66. 各イベントには独自のハンドラー メソッド、
  67. */
  68. if
  69. (ngx_posted_events) {
  70. if (ngx_threaded) {
  71. ngx_wakeup_worker_thread(cycle); :
  72. } }
  73. 受け入れイベントについては以前お話しましたが、実際には、ソケット上に新しいイベントがあるかどうかを監視します。受け入れ時のハンドラーメソッド:
  74. ngx_event_accept:
  75. [cpp] view 普通のコピープリント?
    1. src/event/ngx_event_accept.c
    2. void
    3. ngx_event_accept(ngx_even t_t *ev)
    4. {
    5. socklen_t socklen;  
    6. ngx_err_t エラー;  
    7. ngx_log_t *ログ;  
    8. ngx_socket_t s;  
    9. ngx_event_t *rev、*wev;  
    10. ngx_listening_t *ls;  
    11. ngx_connection_t *c, *lc;  
    12. ngx_event_conf_t *ecf;  
    13. u_char sa[NGX_SOCKADDRLEN];  
    14. //一部省略
    15. lc = ev->data;  
    16. ls = lc->リスニング;  
    17. ev->ready = 0;  
    18. ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
    19. "%V で受け入れます、準備完了: %d", &ls->addr_text, ev->利用可能);  
    20. do {
    21. socklen = NGX_SOCKADDRLEN;  
    22. //新しい接続を受け入れます
    23. s = accept(lc->fd, (struct sockaddr *)さ、&socklen);  
    24. //一部省略
    25. /*
    26. 新しい接続を受け入れた後、新たに計算ngx_accept_disabledの值、
    27. ここでは、私たちは他の内容を閲覧できます。只今
    28. 「总接続数的」 8分の1 - 残りの接続数「
    29. すべての接続は、各プロセスで設定された最大接続数を指し、この数字はファイル内で再構成できます。合計接続数の 7/8 を超えると、NGX_ACCEPT_DISABLED が 0 より大きくなり、接続が過負荷になります
    30. */
    31. ngx_accept_disabled = ngx_cycle->connection_n / 8
    32. - ngx_cycle->free_connection_n
    33. c = ngx_get_connection(s, ev- >ログ);
    34. //接続が閉じられた場合にのみ解放 pool
    35. if (c->pool == NULL ) {
    36. ngx _close_accepted_connection(c);
    37. ); ;
    38. if (log == null) {
    39. ngx_close_accepted_connection (c);  
    40. /* aio にはブロッキング モードを設定し、その他にはノンブロッキング モードを設定します*/
    41. if (ngx_inherited_nonblocking) {
    42. if (ngx_event_flags & NGX_USE_AIO_EVENT) {
    43. if (ngx_blocking(s) == -1) {
    44. ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
    45. ngx_blocking_n " 失敗しました");  
    46. ngx_close_accepted_connection(c);  
    47. 戻る;  
    48. }
    49. }
    50. } else {
    51. //我们epollモデルを使用、这里我们设置连接はノンブロッキングです
    52. if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
    53. if (ngx_nonblocking(s) == -1) {
    54. ngx_log_error(NGX_LOG_ALERT, ev-> ;log、ngx_socket_errno、
    55. ngx_nonblocking_n " 失敗しました");  
    56. ngx_close_accepted_connection(c);  
    57. 戻る;  
    58. }
    59. }
    60. }  
    61. *log = ls->log;  
    62. //初化新的接続
    63. c->recv = ngx_recv;  
    64. c->send = ngx_send;  
    65. c->recv_chain = ngx_recv_chain;  
    66. c->send_chain = ngx_send_chain;  
    67. c->log = log;  
    68. c->pool->log = log;  
    69. c->socklen = socklen;  
    70. c->listening = ls;  
    71. c->local_sockaddr = ls->sockaddr;  
    72. c->unexpected_eof = 1;  
    73. #if (NGX_HAVE_UNIX_DOMAIN)
    74. if (c->sockaddr-&g t;sa_family == AF_UNIX) {
    75. c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;  
    76. c->tcp_nolay = NGX_TCP_NODELAY_DISABLED;  
    77. #if (NGX_SOLARIS)
    78. /* Solaris の sendfilev() は AF_NCA、 AF_INET、および AF_INET6 をサポートしています */
    79. c->sendfile = 0;  
    80. #endif
    81. }
    82. #endif
    83. rev = c->read;  
    84. wev = c->write;  
    85. wev->ready = 1;  
    86. if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
    87. /* rtsig, aio, iocp */
    88. rev->ready = 1;  
    89. }
    90. if (ev->deferred_accept) {
    91. rev->ready = 1;  
    92. #if (NGX_HAVE_KQUEUE)
    93. rev->available = 1;  
    94. #endif
    95. }  
    96. rev->log = log;  
    97. wev->log = log;  
    98. /*
    99. * TODO: MT: - ngx_atomic_fetch_add()
    100. * または クリティカルセクションまたはライトミューテックスによる保護
    101. *
    102. * TODO: MP: - 共有メモリに割り当てられています
    103. * - ngx_atomic_fetch_add()
    104. * またはクリティカルセクションまたはライトミューテックスによる保護
    105. */
    106. c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);  
    107. if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
    108. if (ngx_add_conn(c) == NGX_ERROR) {
    109. ngx_close_accepted_connection (c);  
    110. 戻る;  
    111. }
    112. }
    113. log->data = NULL;  
    114. log->handler = NULL;  
    115. /*
    116. このリスン ハンドラー重要、新しい接続の最後の初期化作業を完了します,
    117. 同時に受け入れられた新しい接続がepollに投入されます中;挂在このハンドラー上の関数,
    118. 就是ngx_http_init_connection 在之后http模块中在详细介绍
    119. */
    120. ls->handler(c);  
    121. if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
    122. ev-> ;利用可能--;  
    123. }
    124. } その間 (EV->利用可能);  
    125. }

    accpt イベントのハンドラー メソッドもこのとおりです。その後は、各接続のコメント イベント ハンドラー メソッドであり、この部分は http モジュールに直接導入されます。更要学习下nginx经典模块epoll。

    上記は、nginx ソース コード学習ノート (21) - イベント モジュール 2 - イベント駆動型コア ngx_process_events_and_timers をキューの内容も含めて紹介しています。PHP チュートリアルに興味のある友人に役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。