nginx round_robin模組剖析

來源:互聯網
上載者:User
基本資料模組名:round_robin檔案位置:src/http/ngx_http_upstream_round_robin.c,src/http/ngx_http_upstream_round_robin.h程式碼:844運行階段:content_phase上遊調用:Ngx_http_upstream.c Ngx_http_upstream_ip_hash_module.c功能:nginx在用作反向 Proxy伺服器時,對於後端的伺服器可以採用兩種分流策略:加權分流和ip hash。本模組主要完成加權分流功能。對於權重較高的機器,被選中的機率大,對於權重相同的機器,則採用輪詢方式。亮點:1、在資料結構中設定了single欄位,判斷是否是只有一台後端伺服器。如果是,則無需走分流原則模組,直接返回即可;2、同時設定了失敗次數和失敗時間的上限。如果達到了失敗次數上限,在一段時間內該server不參與分流。3、backup伺服器的使用。只有在現有server都無效時,才會請求backup伺服器。資料結構
typedef struct {//基本socket資訊    struct sockaddr                *sockaddr;    socklen_t                       socklen;    ngx_str_t                       name;//當前權重值和設定權重值    ngx_int_t                       current_weight;    ngx_int_t                       weight;//失敗次數和訪問時間    ngx_uint_t                      fails;    time_t                          accessed;//失敗次數上限值和失敗時間閾值    ngx_uint_t                      max_fails;    time_t                          fail_timeout;//伺服器是否參與策略    ngx_uint_t                      down;          /* unsigned  down:1; *///ssl相關#if (NGX_HTTP_SSL)    ngx_ssl_session_t              *ssl_session;   /* local to a process */#endif} ngx_http_upstream_rr_peer_t;//round robin後端伺服器資訊typedef struct ngx_http_upstream_rr_peers_s  ngx_http_upstream_rr_peers_t;struct ngx_http_upstream_rr_peers_s {    ngx_uint_t                      single;             //是否只有一台伺服器    ngx_uint_t                      number;             //後端伺服器數量    ngx_uint_t                      last_cached; /* ngx_mutex_t                    *mutex; */    ngx_connection_t              **cached;    ngx_str_t                      *name;    ngx_http_upstream_rr_peers_t   *next;               //下個upstream節點    ngx_http_upstream_rr_peer_t     peer[1];            //伺服器資訊};typedef struct {    ngx_http_upstream_rr_peers_t   *peers;              //所有伺服器資訊    ngx_uint_t                      current;            //當前伺服器    uintptr_t                      *tried;              //伺服器位元影像指標,用於記錄伺服器當前的狀態    uintptr_t                       data;               //tried位元影像實際儲存位置} ngx_http_upstream_rr_peer_data_t;

以上為資料結構設計。其中有兩個地方值得關註:

1、作者對單台伺服器的情況做了單獨的考慮。對於後端只有一台伺服器情況,無需考慮策略問題,直接使用即可。設定此標誌位有助於提高效能。2、tried欄位實現了一個位元影像。對於後端伺服器小於32台時,使用一個32位int來標識各個伺服器是否嘗試串連過。當後端伺服器大於32台時,會在記憶體池中新申請記憶體來儲存該位元影像。data是該欄位實際儲存的位置。current是當前嘗試到哪台伺服器。函數設計
ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf,    ngx_http_upstream_srv_conf_t *us);ngx_int_t ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,    ngx_http_upstream_srv_conf_t *us);ngx_int_t ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,    ngx_http_upstream_resolved_t *ur);ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc,    void *data);void ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc,    void *data, ngx_uint_t state);#if (NGX_HTTP_SSL)ngx_int_t    ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,    void *data);void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,    void *data);#endif
函數設計的思路非常清晰,從名字即可猜測出函數的主要實現。後續會詳細介紹。另外還有兩個static函數,cmp函數完成了server權重比較,用於按照權重排序servers。get_peer完成以及從所有的伺服器中選出權值最高的伺服器。如果所有server當前權重都為0,那麼將所有server的當前權重恢複到設定權重值。
static ngx_int_t ngx_http_upstream_cmp_servers(const void *one,    const void *two);static ngx_uint_tngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
核心實現ngx_http_upstream_init_round_robin函數主要完成了配置中指定伺服器的初始化工作:1、伺服器屬性擷取。包括socket、設定權重值、失敗次數和失敗時間上限等等;2、區分單台伺服器。為後續做單獨處理做準備;3、如果配置中指定的是網域名稱,需要首先擷取到ip;4、正常server和backup server需要分開處理。

ngx_http_upstream_init_round_robin_peer完成了對伺服器的初始化工作。代碼中有些不易理解的地方,主要是對tried變數值的使用。tried中記錄了伺服器當前是否被嘗試串連過。他是一個位元影像。如果伺服器數量小於32,則只需在一個int中即可記錄下所有伺服器狀態。如果伺服器數量大於32,則需在記憶體池中申請記憶體來儲存。實現如下:

//建立過程    if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {        rrp->tried = &rrp->data;        rrp->data = 0;    } else {        n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))                / (8 * sizeof(uintptr_t));        rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));        if (rrp->tried == NULL) {            return NGX_ERROR;        }    }

//使用範例                n = rrp->current / (8 * sizeof(uintptr_t));                m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));                if (!(rrp->tried[n] & m)) {                    peer = &rrp->peers->peer[rrp->current]; 
ngx_http_upstream_create_round_robin_peer用於建立預設的伺服器資訊。其中,權重預設值為1,失敗次數上限預設值為1,失敗時間上限為10s。該函數可以認為是初始化函數的輔助函數,但其上遊調用是在Ngx_http_upstream.c中。ngx_http_upstream_get_round_robin_peer函數完成了擷取後端伺服器的功能,其代碼主要是邏輯處理,理解上沒有什麼難度,只是代碼有一定的冗餘。從代碼中可以讀到round robin的具體策略:1)對server按照權重由高到低排序; 2)取其中權重最大的server,並將權重減一;3)對於權重相同的情況,優先取排在後面的server。另外需要注意的地方是最後有個對backup伺服器的處理:當正常伺服器都失敗時,會落到backup組中。ngx_http_upstream_free_round_robin_peer函數將伺服器的標誌欄位都恢複到初始狀態,以便後續使用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.