WebサーバとしてのNginxの調査結果を記録する。


はじめに

Nginxの動きを把握するため、ソースを読み進めたTipsとして解析内容を残していく。
主にどうやってアクセスを処理しているかに注目するため
main()からではなく、ブラウザからアクセスを受け付けるところからのソースを追う。

前提

環境
OS:CentOS5.3
解析していくバージョン:0.7.65(深い意味なし。手元の環境で以前インストールしてたもの)
アクセス受付
ワーカプロセスは、「ngx_epoll_module.c」のngx_epoll_process_events()関数にて
システムコールepoll_waitで待ち状態となっている。


   386  ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
   387  {
   388      int                events;
   389      uint32_t           revents;
   390      ngx_int_t          instance, i;
   391      ngx_uint_t         level;
   392      ngx_err_t          err;
   393      ngx_log_t         *log;
   394      ngx_event_t       *rev, *wev, **queue;
   395      ngx_connection_t  *c;
   396
   397      /* NGX_TIMER_INFINITE == INFTIM */
   398
   399      ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
   400                     "epoll timer: %M", timer);
   401
   402      events = epoll_wait(ep, event_list, (int) nevents, timer);
   403

ここでセットしているepoll_waitのタイマー値は、ngx_process_events_and_timers()関数にて定義されている。
ややこしいけど、confファイルのtimer_resolution定義をしているか、accept()を使うかで変わってくるみたい。
epoll_wait()の戻り値チェックとタイムアウト時の動作が下記です。
   404      if (events == -1) {
   405          err = ngx_errno;
   406      } else {
   407          err = 0;
   408      }
   409
   410      if (flags & NGX_UPDATE_TIME) {
   411          ngx_time_update(0, 0);
   412      }
   413
   414      if (err) {
   415          if (err == NGX_EINTR) {
   416
   417              if (ngx_event_timer_alarm) {
   418                  ngx_event_timer_alarm = 0;
   419                  return NGX_OK;
   420              }
   421
   422              level = NGX_LOG_INFO;
   423
   424          } else {
   425              level = NGX_LOG_ALERT;
   426          }
   427
   428          ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
   429          return NGX_ERROR;
   430      }
   431
   432      if (events == 0) {
   433          if (timer != NGX_TIMER_INFINITE) {
   434              return NGX_OK;
   435          }
   436
   437          ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
   438                        "epoll_wait() returned no events without timeout");
   439          return NGX_ERROR;
   440      }
events=-1がエラー処理、events == 0がタイムアウトの処理ですね。
とすると、以降がエラーが発生していないときに動作するコード


   441
   442      ngx_mutex_lock(ngx_posted_events_mutex);
   443
   444      log = cycle->log;
   445
   446      for (i = 0; i < events; i++) {
   447          c = event_list[i].data.ptr;
   448
   449          instance = (uintptr_t) c & 1;
   450          c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
   451
   452          rev = c->read;
   453
   454          if (c->fd == -1 || rev->instance != instance) {
   455
   456              /*
   457               * the stale event from a file descriptor
   458               * that was just closed in this iteration
   459               */
   460
   461              ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
   462                             "epoll: stale event %p", c);
   463              continue;
   464          }
   465
   466  #if (NGX_DEBUG0)
   467          log = c->log ? c->log : cycle->log;
   468  #endif
   469
   470          revents = event_list[i].events;
   471
   472          ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
   473                         "epoll: fd:%d ev:%04XD d:%p",
   474                         c->fd, revents, event_list[i].data.ptr);
   475
   476          if (revents & (EPOLLERR|EPOLLHUP)) {
   477              ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
   478                             "epoll_wait() error on fd:%d ev:%04XD",
   479                             c->fd, revents);
   480          }
   481
   482  #if 0
   483          if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
   484              ngx_log_error(NGX_LOG_ALERT, log, 0,
   485                            "strange epoll_wait() events fd:%d ev:%04XD",
   486                            c->fd, revents);
   487          }
   488  #endif
   489
   490          if ((revents & (EPOLLERR|EPOLLHUP))
   491               && (revents & (EPOLLIN|EPOLLOUT)) == 0)
   492          {
   493              /*
   494               * if the error events were returned without EPOLLIN or EPOLLOUT,
   495               * then add these flags to handle the events at least in one
   496               * active handler
   497               */
   498
   499              revents |= EPOLLIN|EPOLLOUT;
   500          }
   501
   502          if ((revents & EPOLLIN) && rev->active) {
   503
   504              if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
   505                  rev->posted_ready = 1;
   506
   507              } else {
   508                  rev->ready = 1;
   509              }
   510
   511              if (flags & NGX_POST_EVENTS) {
   512                  queue = (ngx_event_t **) (rev->accept ?
   513                                 &ngx_posted_accept_events : &ngx_posted_events);
   514
   515                  ngx_locked_post_event(rev, queue);
   516
   517              } else {
   518                  rev->handler(rev);
   519              }
   520          }
   521
   522          wev = c->write;
   523
   524          if ((revents & EPOLLOUT) && wev->active) {
   525
   526              if (flags & NGX_POST_THREAD_EVENTS) {
   527                  wev->posted_ready = 1;
   528
   529              } else {
   530                  wev->ready = 1;
   531              }
   532
   533              if (flags & NGX_POST_EVENTS) {
   534                  ngx_locked_post_event(wev, &ngx_posted_events);
   535
   536              } else {
   537                  wev->handler(wev);
   538              }
   539          }
   540      }
   541
   542      ngx_mutex_unlock(ngx_posted_events_mutex);
   543
   544      return NGX_OK;
   545  }

長い引用ですが、for文でeventsの数だけ繰り返し==有効なファイルディスクリプタの数だけ繰り返しです。
epoll_waitシステムコールを知っていないとわけわからんので、知らない人はepoll,epoll_waitあたりを把握しましょう。
正常処理を追うと、eventsが502行目からの処理がデータ受信準備完了。
先のコードを読まないと断定はできないですが、変数名称からしておそらくリクエストデータ受信待ちかPOSTデータ受信待ちかで
処理が分岐しています。
   502          if ((revents & EPOLLIN) && rev->active) {
   503
   504              if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
   505                  rev->posted_ready = 1;
   506
   507              } else {
   508                  rev->ready = 1;
   509              }
   510
   511              if (flags & NGX_POST_EVENTS) {
   512                  queue = (ngx_event_t **) (rev->accept ?
   513                                 &ngx_posted_accept_events : &ngx_posted_events);
   514
   515                  ngx_locked_post_event(rev, queue);
   516
   517              } else {
   518                  rev->handler(rev);
   519              }
   520          }

新規のリクエストの場合、accept()するためにrev->handler(rev);でngx_event_accept()関数になります。
すでに接続済みでリクエストデータ受信の場合はrev->handler(rev);でngx_http_init_request関数・・・HTTP処理のコードとなっていきます。
epoll_waitで監視していたファイルディスクリプタがwriteできるようになった場合が
524以降のコードでしょう。

最初は新規接続が来たことを想定して、ngx_event_accept()を見てみます。

このページへのコメント

IBkDCs <a href="http://cjxifohwuwvz.com/">cjxifohwuwvz</a>, [url=http://wdsiibgrpruu.com/]wdsiibgrpruu[/url], [link=http://ffeiigumizll.com/]ffeiigumizll[/link], http://gydjxpibigia.com/

0
Posted by qhpniqgg 2013年11月14日(木) 14:01:04 返信

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

メニューサンプル1

メニューサンプル2

開くメニュー

閉じるメニュー

  • アイテム
  • アイテム
  • アイテム
【メニュー編集】

管理人/副管理人のみ編集できます