日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Ningx代碼研究(四)

系統 2182 0

雖然代碼理解起來比較混亂,但是使用還是比較簡單的,常用的有創建 hash 和在 hash 中進行查找兩個操作,對于創建hash的操作,過程一般為:

  1. 構造一個 ngx_hash_key_t 為成員的數組, 包含 key, value 和 使用key計算出的一個hash值
  2. 構建一個 ngx_hash_init_t結構體的變量, 其中包含了ngx_hash_t 的成員, 為hash的結構體, 還包括一些其他初始設置,如bucket的大小,內存池等
  3. 調用 ngx_hash_init 傳入 ngx_hash_init_t 結構, ngx_hash_key_t 的數組,和數組的長度, 進行初始化,這樣 ngx_hash_init_t的hash成員就是我們要的hash結構

查找的過程很簡單

  1. 計算 key 的hash值
  2. 使用 ngx_hash_find 進行查找,需要同時傳入 hash值和key ,返回的就是value的指針

?

需要注意的是,nginx 的 hash 在查找時使用的是分桶后線性查找法,因此當分桶數確定時查找效率同其中的總 key-val 對數量成反比。

下面是一些demo代碼(可以從svn中找到)

    
      #include
    
    
    
    
      <stdio.h>
    
    
    
    
      #include
    
    
    
    
      "ngx_config.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_conf_file.h"
    
    
    
    
      #include
    
    
    
    
      "nginx.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_core.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_string.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_palloc.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_array.h"
    
    
    
    
      #include
    
    
    
    
      "ngx_hash.h"
    
    
    
    
      volatile
    
    
       ngx_cycle_t ?
    
    
      *
    
    
      ngx_cycle
    
    
      ;
    
    
    
    
      void
    
    
       ngx_log_error_core
    
    
      (
    
    
      ngx_uint_t level
    
    
      ,
    
    
       ngx_log_t 
    
    
      *
    
    
      log
    
    
      ,
    
    
       ngx_err_t err
    
    
      ,
    
    
    
    
      const
    
    
    
    
      char
    
    
    
    
      *
    
    
      fmt
    
    
      ,
    
    
    
    
      ...)
    
    
    
    
      {
    
    
    
    
      }
    
    
    
    
      static
    
    
       ngx_str_t names
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      ngx_string
    
    
      (
    
    
      "rainx"
    
    
      ),
    
    
      
? ? ? ? ? ? ? ? ? ? ? ? ? ? ngx_string
    
    
      (
    
    
      "xiaozhe"
    
    
      ),
    
    
      
? ? ? ? ? ? ? ? ? ? ? ? ? ? ngx_string
    
    
      (
    
    
      "zhoujian"
    
    
      )};
    
    
    
    
      static
    
    
    
    
      char
    
    
      *
    
    
       descs
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      "rainx's id is 1"
    
    
      ,
    
    
      "xiaozhe's id is 2"
    
    
      ,
    
    
      "zhoujian's id is 3"
    
    
      };
    
    
    
    
      // hash table的一些基本操作
    
    
    
    
      int
    
    
       main
    
    
      ()
    
    
    
    
      {
    
    
      
? ? ngx_uint_t ? ? ? ? ?k
    
    
      ;
    
    
    
    
      //, p, h;
    
    
      
? ? ngx_pool_t
    
    
      *
    
    
       ? ? ? ? pool
    
    
      ;
    
    
      
? ? ngx_hash_init_t ? ? hash_init
    
    
      ;
    
    
      
? ? ngx_hash_t
    
    
      *
    
    
       ? ? ? ? hash
    
    
      ;
    
    
      
? ? ngx_array_t
    
    
      *
    
    
       ? ? ? ?elements
    
    
      ;
    
    
      
? ? ngx_hash_key_t
    
    
      *
    
    
       ? ? arr_node
    
    
      ;
    
    
      
? ? 
    
    
      char
    
    
      *
    
    
       ? ? ? ? ? ? ? find
    
    
      ;
    
    
      
? ? 
    
    
      int
    
    
       ? ? ? ? ? ? ? ? i
    
    
      ;
    
    
      

? ? ngx_cacheline_size 
    
    
      =
    
    
    
    
      32
    
    
      ;
    
    
      
? ? 
    
    
      // hash key cal start
    
    
      
? ? ngx_str_t str ? ? ? 
    
    
      =
    
    
       ngx_string
    
    
      (
    
    
      "hello, world"
    
    
      );
    
    
      
? ? k ? ? ? ? ? ? ? ? ? 
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
       str
    
    
      .
    
    
      data
    
    
      ,
    
    
       str
    
    
      .
    
    
      len
    
    
      );
    
    
      
? ? pool ? ? ? ? ? ? ? ?
    
    
      =
    
    
       ngx_create_pool
    
    
      (
    
    
      1024
    
    
      *
    
    
      10
    
    
      ,
    
    
       NULL
    
    
      );
    
    
      
? ? printf
    
    
      (
    
    
      "caculated key is %u \n"
    
    
      ,
    
    
       k
    
    
      );
    
    
      
? ? 
    
    
      // hask key cal end
    
    
      
? ? 
    
    
      //
    
    
      
? ? hash 
    
    
      =
    
    
    
    
      (
    
    
      ngx_hash_t
    
    
      *)
    
    
       ngx_pcalloc
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      hash
    
    
      ));
    
    
      
? ? hash_init
    
    
      .
    
    
      hash ? ? ?
    
    
      =
    
    
       hash
    
    
      ;
    
    
       ? ? ? ? ? ? ? ? ? ? ?
    
    
      // hash結構
    
    
      
? ? hash_init
    
    
      .
    
    
      key ? ? ? 
    
    
      =
    
    
    
    
      &
    
    
      ngx_hash_key_lc
    
    
      ;
    
    
       ? ? ? ? ?
    
    
      // hash算法函數
    
    
      
? ? hash_init
    
    
      .
    
    
      max_size ?
    
    
      =
    
    
    
    
      1024
    
    
      *
    
    
      10
    
    
      ;
    
    
       ? ? ? ? ? ? ? ? ? 
    
    
      // max_size
    
    
      
? ? hash_init
    
    
      .
    
    
      bucket_size 
    
    
      =
    
    
    
    
      64
    
    
      ;
    
    
    
    
      // ngx_align(64, ngx_cacheline_size);
    
    
      
? ? hash_init
    
    
      .
    
    
      name ? ? ?
    
    
      =
    
    
    
    
      "yahoo_guy_hash"
    
    
      ;
    
    
       ? ? ? ? ?
    
    
      // 在log里會用到
    
    
      
? ? hash_init
    
    
      .
    
    
      pool ? ? ? ? ? 
    
    
      =
    
    
       pool
    
    
      ;
    
    
       ? ? ? ? ? ? ? ? 
    
    
      // 內存池
    
    
      
? ? hash_init
    
    
      .
    
    
      temp_pool ? ? ?
    
    
      =
    
    
       NULL
    
    
      ;
    
    
      

? ? 
    
    
      // 創建數組
    
    
      

? ? elements 
    
    
      =
    
    
       ngx_array_create
    
    
      (
    
    
      pool
    
    
      ,
    
    
    
    
      32
    
    
      ,
    
    
    
    
      sizeof
    
    
      (
    
    
      ngx_hash_key_t
    
    
      ));
    
    
      
? ? 
    
    
      for
    
    
      (
    
    
      i 
    
    
      =
    
    
    
    
      0
    
    
      ;
    
    
       i 
    
    
      <
    
    
    
    
      3
    
    
      ;
    
    
       i
    
    
      ++)
    
    
    
    
      {
    
    
      
? ? ? ? arr_node ? ? ? ? ? ?
    
    
      =
    
    
    
    
      (
    
    
      ngx_hash_key_t
    
    
      *)
    
    
       ngx_array_push
    
    
      (
    
    
      elements
    
    
      );
    
    
      
? ? ? ? arr_node
    
    
      ->
    
    
      key ? ? ? 
    
    
      =
    
    
    
    
      (
    
    
      names
    
    
      [
    
    
      i
    
    
      ]);
    
    
      
? ? ? ? arr_node
    
    
      ->
    
    
      key_hash ?
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
      arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      data
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      len
    
    
      );
    
    
      
? ? ? ? arr_node
    
    
      ->
    
    
      value ? ? 
    
    
      =
    
    
    
    
      (
    
    
      void
    
    
      *)
    
    
       descs
    
    
      [
    
    
      i
    
    
      ];
    
    
      
? ? ? ? 
    
    
      // 
    
    
      
? ? ? ? printf
    
    
      (
    
    
      "key: %s , key_hash: %u\n"
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key
    
    
      .
    
    
      data
    
    
      ,
    
    
       arr_node
    
    
      ->
    
    
      key_hash
    
    
      );
    
    
      
? ? 
    
    
      }
    
    
      

? ? 
    
    
      if
    
    
    
    
      (
    
    
      ngx_hash_init
    
    
      (&
    
    
      hash_init
    
    
      ,
    
    
    
    
      (
    
    
      ngx_hash_key_t
    
    
      *)
    
    
       elements
    
    
      ->
    
    
      elts
    
    
      ,
    
    
       elements
    
    
      ->
    
    
      nelts
    
    
      )!=
    
    
      NGX_OK
    
    
      ){
    
    
      
? ? ? ? 
    
    
      return
    
    
    
    
      1
    
    
      ;
    
    
      
? ? 
    
    
      }
    
    
      

? ? 
    
    
      // 查找
    
    
      
? ? k ? ?
    
    
      =
    
    
       ngx_hash_key_lc
    
    
      (
    
    
      names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      len
    
    
      );
    
    
      
? ? printf
    
    
      (
    
    
      "%s key is %d\n"
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       k
    
    
      );
    
    
      
? ? find 
    
    
      =
    
    
    
    
      (
    
    
      char
    
    
      *)
    
    
      
? ? ? ? ngx_hash_find
    
    
      (
    
    
      hash
    
    
      ,
    
    
       k
    
    
      ,
    
    
    
    
      (
    
    
      u_char
    
    
      *)
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      data
    
    
      ,
    
    
       names
    
    
      [
    
    
      0
    
    
      ].
    
    
      len
    
    
      );
    
    
      

? ? 
    
    
      if
    
    
    
    
      (
    
    
      find
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? printf
    
    
      (
    
    
      "get desc of rainx: %s\n"
    
    
      ,
    
    
    
    
      (
    
    
      char
    
    
      *)
    
    
       find
    
    
      );
    
    
      
? ? 
    
    
      }
    
    
      

? ? ngx_array_destroy
    
    
      (
    
    
      elements
    
    
      );
    
    
      
? ? ngx_destroy_pool
    
    
      (
    
    
      pool
    
    
      );
    
    
      

? ? 
    
    
      return
    
    
    
    
      0
    
    
      ;
    
    
    
    
      }
    
  

運行結果

    
      rainx@rainx
    
    
      -
    
    
      laptop
    
    
      :~/
    
    
      land
    
    
      /
    
    
      nginxsrp
    
    
      /
    
    
      src
    
    
      /
    
    
      demo
    
    
      /
    
    
      basic_types$ 
    
    
      ./
    
    
      hash_op 
caculated key 
    
    
      is
    
    
    
    
      3654358412
    
    
       
key
    
    
      :
    
    
       rainx 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      108275556
    
    
      
key
    
    
      :
    
    
       xiaozhe 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      2225329080
    
    
      
key
    
    
      :
    
    
       zhoujian 
    
    
      ,
    
    
       key_hash
    
    
      :
    
    
    
    
      3269715264
    
    
      
rainx key 
    
    
      is
    
    
    
    
      108275556
    
    
    
    
      get
    
    
       desc of rainx
    
    
      :
    
    
       rainx
    
    
      's id is 1
    
  

ngx_list

ngx_list 的結構并不復雜,ngx為我們封裝了ngx_list_create, ngx_list_init, 和 ngx_list_push等(建立,初始化,添加)操作, 但是對于我們來說最常用的是遍歷操作, 下面是nginx的注釋里面提到的遍歷的例子

    
      ? ?part 
    
    
      =
    
    
    
    
      &
    
    
      list
    
    
      .
    
    
      part
    
    
      ;
    
    
      
? ?data 
    
    
      =
    
    
       part
    
    
      ->
    
    
      elts
    
    
      ;
    
    
      
?
? ?
    
    
      for
    
    
    
    
      (
    
    
      i 
    
    
      =
    
    
    
    
      0
    
    
    
    
      ;;
    
    
       i
    
    
      ++)
    
    
    
    
      {
    
    
      
?
? ? ? ?
    
    
      if
    
    
    
    
      (
    
    
      i 
    
    
      >=
    
    
       part
    
    
      ->
    
    
      nelts
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? ? ?
    
    
      if
    
    
    
    
      (
    
    
      part
    
    
      ->
    
    
      next
    
    
    
    
      ==
    
    
       NULL
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? ? ? ? ?
    
    
      break
    
    
      ;
    
    
      
? ? ? ? ? ?
    
    
      }
    
    
      
?
? ? ? ? ? ?part 
    
    
      =
    
    
       part
    
    
      ->
    
    
      next
    
    
      ;
    
    
      
? ? ? ? ? ?data 
    
    
      =
    
    
       part
    
    
      ->
    
    
      elts
    
    
      ;
    
    
      
? ? ? ? ? ?i 
    
    
      =
    
    
    
    
      0
    
    
      ;
    
    
      
? ? ? ?
    
    
      }
    
    
      
?
? ? ? ?
    
    
      ...
    
    
       ?data
    
    
      [
    
    
      i
    
    
      ]
    
    
    
    
      ...
    
    
      
?
? ?
    
    
      }
    
  

了解nginx的core module 的結構和運行機制

參考資料

在開始這個task的學習的時候,經過搜索發現了langwan同學之前對nginx的源代碼研究資料,很有參考意義,所以大量節省了我們的工作,我覺得對于本章的進行比較有用的是,下面這幾個文章

  1. nginx源代碼分析? http://hi.baidu.com/langwan/blog/item/6b18ef24cd859e064c088d28.html
  2. nginx 緩沖區構造? http://hi.baidu.com/langwan/blog/item/822b758d5d1d9a1ab31bbaf8.html
  3. Nginx源代碼分析 - 日志處理? http://hi.baidu.com/langwan/blog/item/7e7db51978e04e4d43a9ad32.html

Debug信息的輸出

為了方便研究,將nginx的debug 信息打開,重新編譯

    
      rainx@rainx
    
    
      -
    
    
      laptop
    
    
      :~/
    
    
      land
    
    
      /
    
    
      nginx
    
    
      -
    
    
      0.7
    
    
      .
    
    
      61
    
    
      $ 
    
    
      ./
    
    
      configure 
    
    
      --
    
    
      prefix
    
    
      =
    
    
      /home/
    
    
      rainx
    
    
      /
    
    
      land
    
    
      /
    
    
      test 
    
    
      --
    
    
      with
    
    
      -
    
    
      debug
    
  

然后修改nginx.conf

    
      worker_processes ?
    
    
      2
    
    
      ;
    
    
       
error_log ?logs
    
    
      /
    
    
      error
    
    
      .
    
    
      log ?debug
    
    
      ;
    
  

打開debug信息的支持,并使用2個worker進程,通過查看 log 信息來了解 nginx 運行的情況

基于上面的配置信息,結合一個簡單的http訪問操作,我這里記錄了一個? log日志的例子

ngx_init_cycle

其中一個比較重要的函數調用是, ngx_init_cycle, 這個是使用kscope輸出的他的調用關系,他被main, ngx_master_process_cycle,ngx_single_process_cycle 調用, 其中后兩者是在reconfigure的時候被調用的

他主要做了如下幾件事情:

    
      初始化
    
    
      cycle
    
    
      是基于舊有的
    
    
      cycle
    
    
      進行的,比如這里的
    
    
       init_cycle
    
    
      ,會繼承
    
    
      old cycle
    
    
      的很多屬性,
    
    
    
    
      比如
    
    
      log
    
    
      等,
    
    
    
    
      但是同時會對很多資源重新分配,比如
    
    
      pool
    
    
      ,
    
    
       shared mem
    
    
      ,
    
    
       file handler
    
    
      ,
    
    
       listening socket 
    
    
      等,同時清除舊有的
    
    
      cycle
    
    
      的資源
    
    
    
  

另外,ngx_master/single_process_cycle 里面會對init_process進行調用, 并且循環調用 ngx_process_events_and_timers , 其中里面會調用ngx_process_events(cycle, timer, flags); 對事件循環進行polliing 時間一般默認為 500 ms

了解nginx的http core module 的結構和運行機制

HTTP相關的Module都在 src/http 目錄和其子目錄下, 其中 src/http 下的文件為http模塊的核心文件, src/http/modules 下的文件為http模塊的擴展模塊。

其中:

ngx_http.[c|h]

ngx_http.c 中,注冊了 http 這個指令的處理模塊,對應ngx_http_block函數

    
      static
    
    
       ngx_command_t ?ngx_http_commands
    
    
      []
    
    
    
    
      =
    
    
    
    
      {
    
    
      

? ? 
    
    
      {
    
    
       ngx_string
    
    
      (
    
    
      "http"
    
    
      ),
    
    
      
? ? ? NGX_MAIN_CONF
    
    
      |
    
    
      NGX_CONF_BLOCK
    
    
      |
    
    
      NGX_CONF_NOARGS
    
    
      ,
    
    
      
? ? ? ngx_http_block
    
    
      ,
    
    
      
? ? ? 
    
    
      0
    
    
      ,
    
    
      
? ? ? 
    
    
      0
    
    
      ,
    
    
      
? ? ? NULL 
    
    
      },
    
    
      

? ? ? ngx_null_command

    
    
      };
    
  

這個函數里面會進行一些conf資源分配/Merge,配置文件解析等工作。 這里面有個一比較重要的工作是注冊了nginx http 的 phase handler

    
      ? ? 
    
    
      if
    
    
    
    
      (
    
    
      ngx_http_init_phase_handlers
    
    
      (
    
    
      cf
    
    
      ,
    
    
       cmcf
    
    
      )
    
    
    
    
      !=
    
    
       NGX_OK
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? 
    
    
      return
    
    
       NGX_CONF_ERROR
    
    
      ;
    
    
      
? ? 
    
    
      }
    
  

phase handler的類型在 ngx_http_core_module 這里定義:

    
      typedef
    
    
    
    
      enum
    
    
    
    
      {
    
    
      
? ? NGX_HTTP_POST_READ_PHASE 
    
    
      =
    
    
    
    
      0
    
    
      ,
    
    
      

? ? NGX_HTTP_SERVER_REWRITE_PHASE
    
    
      ,
    
    
      

? ? NGX_HTTP_FIND_CONFIG_PHASE
    
    
      ,
    
    
      
? ? NGX_HTTP_REWRITE_PHASE
    
    
      ,
    
    
      
? ? NGX_HTTP_POST_REWRITE_PHASE
    
    
      ,
    
    
      

? ? NGX_HTTP_PREACCESS_PHASE
    
    
      ,
    
    
      

? ? NGX_HTTP_ACCESS_PHASE
    
    
      ,
    
    
      
? ? NGX_HTTP_POST_ACCESS_PHASE
    
    
      ,
    
    
      

? ? NGX_HTTP_TRY_FILES_PHASE
    
    
      ,
    
    
      
? ? NGX_HTTP_CONTENT_PHASE
    
    
      ,
    
    
      

? ? NGX_HTTP_LOG_PHASE

    
    
      }
    
    
       ngx_http_phases
    
    
      ;
    
  

每一個phase的handlers 都是一個數組,里面可以包含多個元素,通過 ngx_array_push 添加新的handler

其中每個phase的處理大都包含了對ngx_request_t 的 write 或者 read event的改寫,其中

在 ngx_http_core_content_phase 里面, 有對location handler的調用, 其中的 r->content_handler 就是運行時刻從location handler中注冊的,

    
      ? ? 
    
    
      if
    
    
    
    
      (
    
    
      r
    
    
      ->
    
    
      content_handler
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? r
    
    
      ->
    
    
      write_event_handler 
    
    
      =
    
    
       ngx_http_request_empty_handler
    
    
      ;
    
    
      
? ? ? ? ngx_http_finalize_request
    
    
      (
    
    
      r
    
    
      ,
    
    
       r
    
    
      ->
    
    
      content_handler
    
    
      (
    
    
      r
    
    
      ));
    
    
    
    
      /*實際的請求發送處理*/
    
    
      
? ? ? ? 
    
    
      return
    
    
       NGX_OK
    
    
      ;
    
    
      
? ? 
    
    
      }
    
  

其中, 在各個phase的結束階段,一般都是調用

    
      ? ? r
    
    
      ->
    
    
      phase_handler
    
    
      ++;
    
    
      
? ? 
    
    
      return
    
    
       NGX_AGAIN
    
    
      ;
    
  

移動request 中 phase_handler的指針,并且示意主程序繼續進行。

這里,無論是phase handler,還是 location handler,我們都是可以在程序里進行注冊的。

另外, ngx_http_block 里面調用了 ngx_http_optimize_servers ,這個函數對listening和connection相關的變量進行了初始化和調優,并最終在 ngx_http_add_listening (被ngx_http_add_listening調用) 中注冊了listening 的 handler 為 ngx_http_init_connection

    
      ? ? ls
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_init_connection
    
    
      ;
    
  

ngx_http_init_connection 在 ngx_http_request.c中定義,后續會進行詳細的介紹

ngx_http_request.[c|h]

這里面,ngx_http_init_connection 注冊了connection事件的讀操作的回叫函數, 并將寫操作設置為空函數

    
      ? ? rev 
    
    
      =
    
    
       c
    
    
      ->
    
    
      read
    
    
      ;
    
    
      
? ? rev
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_init_request
    
    
      ;
    
    
      
? ? c
    
    
      ->
    
    
      write
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_empty_handler
    
    
      ;
    
  

當新的連接進入的時候,就執行到 ngx_http_init_request, 開始對后面的流程進行處理,主要是將rev的handler 設置為ngx_http_process_request_line , 然后ngx_http_process_request_line 會先后有調度到 ngx_http_process_request_headers 和 ngx_http_process_request 函數對讀取過來的event進行處理,其中, ngx_http_process_request_headers 里面會對http的請求頭進行解析,ngx_http_process_request 設置event handler 到ngx_http_request_handler ,ngx_http_request_handler 中會根據事件可能是讀取還是寫入的操作分別調用 request 的 read_event_handler 和 write_event_handler ,所以后續程序對 request 的 read/write event_handler 調整 本質上類似對 rev 和 wev的handler的調整,只是回叫函數的參數變更為了 ngx_request_t 而不是之前的ngx_event_t

    
      ? ? c
    
    
      ->
    
    
      read
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_request_handler
    
    
      ;
    
    
      
? ? c
    
    
      ->
    
    
      write
    
    
      ->
    
    
      handler 
    
    
      =
    
    
       ngx_http_request_handler
    
    
      ;
    
    
      
? ? r
    
    
      ->
    
    
      read_event_handler 
    
    
      =
    
    
       ngx_http_block_reading
    
    
      ;
    
  

根據上面代碼可以看出, 模塊開始使用 ngx_http_block_reading 這個handler對后續的讀請求進行處理

在注冊完事件后, ngx_http_process_request 會分別調用下面的兩個函數

    
      ? ? ngx_http_handler
    
    
      (
    
    
      r
    
    
      );
    
    
      
? ? ngx_http_run_posted_requests
    
    
      (
    
    
      c
    
    
      );
    
  

其中, ngx_http_handler 在ngx_http_core_module中定義,處理程序的主請求, ngx_http_run_posted_requests 在ngx_http_request.c 里定義,處理所有提交的子請求數據的輸出。

ngx_http_core_module.[c|h]

對于 ngx_http_core_module 是http 模塊中比較重要的模塊, 他本身是一個 NGX_HTTP_MODULE (不同于ngx_http_module, ngx_http_module本質上是一個 NGX_CORE_MODULE

這里面對http block下面的一些指令進行了處理, 比如 server, location 等, 同時, 上面提到的 ngx_http_handler 也在這里面

ngx_http_handler 所作的最核心的工作就是在最后調用 并將 write event 設置為 ngx_http_core_run_phases, 開始依次處理各個階段的 handler

當handler處理完成后,http的處理流程也就基本上完成了..

    
      ? ? 
    
    
      while
    
    
    
    
      (
    
    
      ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ].
    
    
      checker
    
    
      )
    
    
    
    
      {
    
    
      

? ? ? ? rc 
    
    
      =
    
    
       ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ].
    
    
      checker
    
    
      (
    
    
      r
    
    
      ,
    
    
    
    
      &
    
    
      ph
    
    
      [
    
    
      r
    
    
      ->
    
    
      phase_handler
    
    
      ]);
    
    
      

? ? ? ? 
    
    
      if
    
    
    
    
      (
    
    
      rc 
    
    
      ==
    
    
       NGX_OK
    
    
      )
    
    
    
    
      {
    
    
      
? ? ? ? ? ? 
    
    
      return
    
    
      ;
    
    
      
? ? ? ? 
    
    
      }
    
    
      
? ? 
    
    
      }
    
  

run_phases 的過程實際上非常簡單, 一次的運行每一個handler, 當任意一個handler返回ok或者所有handler執行完成后,整個流程結束。

這里需要注意的是, ph的下標變化是根據 r->phase_handler 變量決定的, 所以在每個handler內部,如果想要讓主程序繼續處理下一個 handler,需要手動的 r->phase_handler++ ,將phase handler數組的下標轉移到下一個成員。


Ningx代碼研究(四)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 武穴市| 义马市| 西安市| 昌都县| 山阳县| 东至县| 张家界市| 淮阳县| 垫江县| 彭州市| 永清县| 乌兰县| 济南市| 滦南县| 青州市| 永胜县| 肥乡县| 夹江县| 永登县| 黄梅县| 六枝特区| 固原市| 丰台区| 石狮市| 平和县| 泰顺县| 连江县| 郯城县| 桑植县| 嘉禾县| 江陵县| 巴中市| 营山县| 大理市| 班戈县| 珲春市| 佳木斯市| 洛浦县| 东兴市| 中阳县| 古浪县|