1. 程式人生 > >nginx upstream模組詳解(基礎結構篇)

nginx upstream模組詳解(基礎結構篇)

nginx upstream模組對於nginx 最為代理伺服器提供了基礎功能 結合upstream功能 nginx能對代理進行各種處理

nginx upstream基礎資料結構

typedef struct {

    ngx_uint_t                       status;  //http狀態碼

    ngx_msec_t                     response_time; //上游伺服器響應時間

    ngx_msec_t                     connect_time;  //成功連線上游伺服器時間

    ngx_msec_t                     header_time; //頭部時間耗費 處理完成上游伺服器返回頭部的時間和響應時間差

    off_t                                response_length;   //http包體和頭部總長度

    off_t                                bytes_received; //upstream接收到的位元組數

    ngx_str_t                       *peer; //上游伺服器地址(ip或名稱)

}  ngx_http_upstream_state_t;

state結構體中的成員可以繫結到nginx http變數中 從而可以在nginx access中打印出請求的對應上述變數資訊

upstream main作用域可配置資訊

typedef struct {

    ngx_hash_t                       headers_in_hash;  //其他模組配置的hash頭部資訊
    ngx_array_t                      upstreams; //可配置多個upstream

} ngx_http_upstream_main_conf_t;

upstream server結構

typedef struct {

    ngx_str_t                         name;      //server名稱
    ngx_addr_t                      *addrs;   //server地址
    ngx_uint_t                       naddrs;   //地址數量
    ngx_uint_t                       weight;   //server對應的權重
    ngx_uint_t                       max_conns;  //指定server最大連線數
    ngx_uint_t                       max_fails;   //允許最多連線失敗次數
    time_t                             fail_timeout; //連線超時時間
    ngx_msec_t                     slow_start;  //未使用
    ngx_uint_t                       down; //踢出
    unsigned                         backup:1; //作為備用

    NGX_COMPAT_BEGIN(6)
    NGX_COMPAT_END

} ngx_http_upstream_server_t;

upstream peer結構

typedef struct {
    ngx_http_upstream_init_pt            init_upstream;  //peer配置初始化
    ngx_http_upstream_init_peer_pt   init; //peer初始化
    void                            *data;         //傳入的資料地址

} ngx_http_upstream_peer_t;

nginx server作用域配置結構

struct ngx_http_upstream_srv_conf_s {
    ngx_http_upstream_peer_t         peer;     //upstream peer
    void                                         **srv_conf;

    ngx_array_t                               *servers;  

    ngx_uint_t                       flags;  //可支援的標誌
    ngx_str_t                        host;    //server主機地址
    u_char                          *file_name;  //conf配置檔名
    ngx_uint_t                       line;   //所在配置檔案裡行數
    in_port_t                         port;   //埠號
    ngx_uint_t                        no_port; //沒有埠號
#if (NGX_HTTP_UPSTREAM_ZONE)

    ngx_shm_zone_t                  *shm_zone; // upstream共享記憶體

#endif

};

upstream local  上游伺服器解析繫結到本機地址

typedef struct {
    ngx_addr_t                                 *addr;
    ngx_http_complex_value_t        *value;
#if (NGX_HAVE_TRANSPARENT_PROXY)
    ngx_uint_t                       transparent; /* unsigned  transparent:1; */
#endif

} ngx_http_upstream_local_t

upstream 可配置結構 可以被其它模組進行配置

typedef struct {
    ngx_http_upstream_srv_conf_t        *upstream;    //upstream server域配置指標
    ngx_msec_t                                       connect_timeout; //連線超時時間
    ngx_msec_t                                       send_timeout;  //可寫資料超時時間
    ngx_msec_t                                       read_timeout;  //可讀資料超時時間
    ngx_msec_t                                       next_upstream_timeout;  //滿足next測試請求到另一臺伺服器超時時間


    size_t                           send_lowat;  //upstream傳送低潮度值 
    size_t                           buffer_size; //nginx buffer緩衝區大小 預設ngx_pagesize大小
    size_t                           limit_rate; //讀取upstream速度限制


    size_t                           busy_buffers_size;  // event_pipe "busy" 緩衝區大小  
    size_t                           max_temp_file_size;   //最大臨時檔案大小 預設1GB
    size_t                           temp_file_write_size;  //event_pipe臨時檔案寫入大小 預設2 * buffer_size


    size_t                           busy_buffers_size_conf;    //busy_buffer配置大小
    size_t                           max_temp_file_size_conf; //最大臨時檔案配置大小
    size_t                           temp_file_write_size_conf; //臨時寫入配置大小


    ngx_bufs_t                       bufs; //event_pipe配置的buffer緩衝組

    ngx_uint_t                       ignore_headers;  //upstream配置的可忽略的頭部
    ngx_uint_t                       next_upstream;//upstream配置的next請求位
    ngx_uint_t                       store_access; //store指令儲存檔案的許可權
    ngx_uint_t                       next_upstream_tries;// upstream next嘗試的次數
    ngx_flag_t                       buffering;  //是否進行buffering緩衝
    ngx_flag_t                       request_buffering; //是否快取請求包體
    ngx_flag_t                       pass_request_headers; //請求頭直接通過
    ngx_flag_t                       pass_request_body; //請求體直接通過


    ngx_flag_t                       ignore_client_abort;  //忽略客戶端退出
    ngx_flag_t                       intercept_errors;  //可否被錯誤攔截
    ngx_flag_t                       cyclic_temp_file; //event_pipe臨時檔案能否迴圈使用
    ngx_flag_t                       force_ranges; //是否忽略代理的響應的"Accept-Ranges"


    ngx_path_t                      *temp_path; //臨時檔案路徑


    ngx_hash_t                       hide_headers_hash;  //未使用
    ngx_array_t                     *hide_headers;  //隱藏的頭部
    ngx_array_t                     *pass_headers;//允許通過的頭部


    ngx_http_upstream_local_t       *local; //本地upstream


#if (NGX_HTTP_CACHE)
    ngx_shm_zone_t                  *cache_zone;   //快取zone
    ngx_http_complex_value_t        *cache_value; //快取zone變數


    ngx_uint_t                       cache_min_uses;  //快取最少使用次數 超出便快取
    ngx_uint_t                       cache_use_stale; //快取出錯 直接傳送快取中的舊資料
    ngx_uint_t                       cache_methods; //滿足條件請求method進行快取


    off_t                                 cache_max_range_offset; //最大可快取大小


    ngx_flag_t                         cache_lock;  //是否啟用快取鎖
    ngx_msec_t                       cache_lock_timeout;  //快取鎖超時時間
    ngx_msec_t                       cache_lock_age;  //快取鎖時間

    ngx_flag_t                       cache_revalidate;  //快取資訊更新

    ngx_flag_t                       cache_convert_head;  //HEAD變 GET
    ngx_flag_t                       cache_background_update; //快取後臺更新


    ngx_array_t                     *cache_valid; //快取狀態碼有效期
    ngx_array_t                     *cache_bypass; //可通過測試的快取
    ngx_array_t                     *cache_purge; //快取清理規則
    ngx_array_t                     *no_cache;//不快取的規則
#endif

    ngx_array_t                     *store_lengths; //儲存變數長度陣列
    ngx_array_t                     *store_values; //儲存變數值陣列
#if (NGX_HTTP_CACHE)
    signed                             cache:2; //是否快取
#endif
    signed                             store:2;
    unsigned                         intercept_404:1; //404配置返回
    unsigned                         change_buffering:1; //buffering開關

#if (NGX_HTTP_SSL || NGX_COMPAT)
    ngx_ssl_t                         *ssl;
    ngx_flag_t                       ssl_session_reuse; //ssl session複用

    ngx_http_complex_value_t        *ssl_name; //ssl名
    ngx_flag_t                                   ssl_server_name;  //ssl 伺服器名
    ngx_flag_t                                   ssl_verify;  //ssl校驗
#endif


    ngx_str_t                        module;  //模組名
    NGX_COMPAT_BEGIN(2)
    NGX_COMPAT_END

} ngx_http_upstream_conf_t;

upstream上游伺服器返回頭部處理

typedef struct {

    ngx_str_t                                       name;  //http頭部key值
    ngx_http_header_handler_pt       handler; //返回頭部處理
    ngx_uint_t                                    offset; //上游伺服器返回頭部結構成員偏移量
    ngx_http_header_handler_pt       copy_handler; //頭部資訊拷貝
    ngx_uint_t                                    conf; //http返回頭偏移量
    ngx_uint_t                                    redirect;  //是否隨上游返回頭部x_accel_redirect 跳轉

} ngx_http_upstream_header_t

upstream DNS解析結構

typedef struct {
    ngx_str_t                              host;         //主機 可以為IP或者域名
    in_port_t                              port;         //埠
    ngx_uint_t                           no_port;   //無埠標記


    ngx_uint_t                           naddrs;   //解析出的地址數量
    ngx_resolver_addr_t          *addrs;    //解析出的地址資訊


    struct sockaddr                 *sockaddr;      //socket地址
    socklen_t                            socklen;     //socket地址長度

    ngx_resolver_ctx_t             *ctx;   //域名解析器上下文

} ngx_http_upstream_resolved_t

upstream在http請求結構

struct ngx_http_upstream_s {
    ngx_http_upstream_handler_pt     read_event_handler;         //讀事件處理函式

    ngx_http_upstream_handler_pt     write_event_handler;        //寫事件處理函式

    ngx_peer_connection_t                  peer;           //同上遊伺服器連線描述
    ngx_event_pipe_t                          *pipe;          //event_pipe

    ngx_chain_t                                   *request_bufs;   //請求端產生的bufffer鏈


    ngx_output_chain_ctx_t                 output;    //輸出chain上下文結構
    ngx_chain_writer_ctx_t                   writer;    //upstream寫處理鏈


    ngx_http_upstream_conf_t        *conf;             //upstream配置資訊
#if (NGX_HTTP_CACHE)
    ngx_array_t                                *caches;         //快取陣列  可以配置多個快取目錄
#endif


    ngx_http_upstream_headers_in_t   headers_in;      //上游伺服器返回的頭部資料(已經完成了頭部解析)


    ngx_http_upstream_resolved_t    *resolved;           //upstream域名解析結構


    ngx_buf_t                        from_client;      //對請求端而言的upgrage buffer


    ngx_buf_t                        buffer;              //upstream處理上游資料緩衝
    off_t                                length;             //上游資料包體大小


    ngx_chain_t                     *out_bufs;         //響應到請求端的緩衝chain
    ngx_chain_t                     *busy_bufs;       //upstream 處理資料時用緩衝chain
    ngx_chain_t                     *free_bufs;       //空閒的緩衝chain 


    ngx_int_t                      (*input_filter_init)(void *data);            //上游返回的資料filter初始化 主要設定一些狀態資訊
    ngx_int_t                      (*input_filter)(void *data, ssize_t bytes);   //上游返回的頭部資料filter
    void                            *input_filter_ctx;                             //input_filter上下文地址


#if (NGX_HTTP_CACHE)
    ngx_int_t     (*create_key)(ngx_http_request_t *r);          //用於指定快取key值生成方式
#endif
    ngx_int_t     (*create_request)(ngx_http_request_t *r);         //建立對upstream上游伺服器請求
    ngx_int_t     (*reinit_request)(ngx_http_request_t *r);          //重新初始化upstream   處理配置
    ngx_int_t     (*process_header)(ngx_http_request_t *r);       //指定處理上游伺服器返回的頭部
    void            (*abort_request)(ngx_http_request_t *r);          //指定放棄對上游請求處理
    void            (*finalize_request)(ngx_http_request_t *r,        //指定結束請求處理
                              ngx_int_t rc);
    ngx_int_t     (*rewrite_redirect)(ngx_http_request_t *r,        //upstream返回的refresh跳轉
                                         ngx_table_elt_t *h, size_t prefix);
    ngx_int_t      (*rewrite_cookie)(ngx_http_request_t *r,         //返回請求端的cookie值重寫
                                         ngx_table_elt_t *h);

    ngx_msec_t              timeout;


    ngx_http_upstream_state_t       *state;        //upstream處理過程的狀態資訊(可以通過變數列印到日誌)


    ngx_str_t                        method;         //到上游伺服器的請求方法
    ngx_str_t                        schema;         //協議名
    ngx_str_t                        uri;               
    ngx_str_t                        origin_host;


#if (NGX_HTTP_SSL)
    ngx_str_t                        ssl_name;
#endif

    ngx_http_cleanup_pt             *cleanup;

    unsigned                         store:1;
    unsigned                         cacheable:1;
    unsigned                         accel:1;
    unsigned                         ssl:1;
#if (NGX_HTTP_CACHE)
    unsigned                         cache_status:3;

#endif

    unsigned                         buffering:1;
    unsigned                         keepalive:1;
    unsigned                         upgrade:1;

    unsigned                         request_sent:1;
    unsigned                         request_body_sent:1;
    unsigned                         header_sent:1;
}

//upstream params (由其它模組配置 可以配置多個)

typedef struct {
    ngx_str_t    key;
    ngx_str_t    value;
    ngx_uint_t  skip_empty;  //跳過空格標記

} ngx_http_upstream_param_t

upstream上下游伺服器資料處理關鍵結構 ngx_event_pipe結構詳解

upstream 表示上游伺服器      downstream 表示下游請求端

event_pipe 可以設定input_filter對上游伺服器返回的資料進行處理 同時也能設定output_filter對響應到下游請求端的資料進行處理

struct ngx_event_pipe_s {

    ngx_connection_t  *upstream;            //與上游伺服器的tcp連線
    ngx_connection_t  *downstream;       //與下游請求端的tcp連線

    ngx_chain_t       *free_raw_bufs;    //空閒的用於原始資料緩衝鏈
    ngx_chain_t       *in;                       //輸入到event_pipe中的緩衝鏈
    ngx_chain_t      **last_in;                //緩衝in 最後一個

    ngx_chain_t       *writing;                  //用於將資料寫入臨時檔案的鏈

    ngx_chain_t       *out;            //用於響應請求端緩衝鏈
    ngx_chain_t       *free;           //空閒的緩衝鏈
    ngx_chain_t       *busy;          //正在進行處理的緩衝鏈

    /*
     * the input filter i.e. that moves HTTP/1.1 chunks

     * from the raw bufs to an incoming chain   */

    ngx_event_pipe_input_filter_pt    input_filter;     //上游伺服器返回資料filter
    void                             *input_ctx;  //filter對應的上下文資訊

    ngx_event_pipe_output_filter_pt   output_filter;   //響應到請求端的資料filter
    void                             *output_ctx; 

#if (NGX_THREADS)                                                     //執行緒池相關
    ngx_int_t                       (*thread_handler)(ngx_thread_task_t *task,
                                                      ngx_file_t *file);
    void                              *thread_ctx;
    ngx_thread_task_t        *thread_task;
#endif

    unsigned           read:1;                    //讀取狀態標記
    unsigned           cacheable:1;           //可快取標記
    unsigned           single_buf:1;          //單一buf標記 windows iocp下成立
    unsigned           free_bufs:1;           //釋放緩衝標記
    unsigned           upstream_done:1;  //上游包體資料讀取完畢
    unsigned           upstream_error:1;  //上游資料讀取出錯標記
    unsigned           upstream_eof:1;   //核心網路緩衝區讀取完畢
    unsigned           upstream_blocked:1;  //upstream讀取阻塞
    unsigned           downstream_done:1;   //downstream處理完畢
    unsigned           downstream_error:1;   //downstream處理出錯
    unsigned           cyclic_temp_file:1;  //複用臨時檔案標記
    unsigned           aio:1;  //aio非同步標記

    ngx_int_t            allocated;   //配置的buffer被分配使用的數量
    ngx_bufs_t         bufs; //配置的的buffer組
    ngx_buf_tag_t    tag;  //buffer的tag標記

    ssize_t                busy_size;   //busy buffer的大小

    off_t                   read_length;  //讀取上游資料的長度
    off_t                   length; //動態變化的剩餘上游包體長度

    off_t                   max_temp_file_size;     //最大臨時檔案大小
    ssize_t                temp_file_write_size;     //最大可寫入檔案大小

    ngx_msec_t        read_timeout;      //上游資料讀取超時
    ngx_msec_t        send_timeout;     //下游資料傳送超時
    ssize_t                send_lowat;  //設定的想用下游請求的低潮值

    ngx_pool_t        *pool;  //記憶體池
    ngx_log_t          *log;  

    ngx_chain_t       *preread_bufs;  //預讀取upstream 的緩衝chain
    size_t                  preread_size;  //預讀取的大小
    ngx_buf_t           *buf_to_file; //將資料寫入臨時檔案所用的緩衝

    size_t                  limit_rate;  //upstream讀取限速

    time_t                 start_sec; //event_pipe開始處理的時間

    ngx_temp_file_t  *temp_file;     //臨時檔案地址

    /* STUB */ int      num;   //STUB資訊 buf使用計數
}