<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                Nginx版本:1.9.1 我的博客:[http://blog.csdn.net/zhangskd](http://blog.csdn.net/zhangskd) **什么是負載均衡** 我們知道單臺服務器的性能是有上限的,當流量很大時,就需要使用多臺服務器來共同提供服務,這就是所謂的集群。 負載均衡服務器,就是用來把經過它的流量,按照某種方法,分配到集群中的各臺服務器上。這樣一來不僅可以承擔 更大的流量、降低服務的延遲,還可以避免單點故障造成服務不可用。一般的反向代理服務器,都具備負載均衡的功能。 負載均衡功能可以由硬件來提供,比如以前的F5設備。也可以由軟件來提供,LVS可以提供四層的負載均衡(利用IP和端口), Haproxy和Nginx可以提供七層的負載均衡(利用應用層信息)。 ? 來看一個最簡單的Nginx負載均衡配置。 ~~~ http { upstream cluster { server srv1; server srv2; server srv3; } server { listen 80; location / { proxy_pass http://cluster; } } } ~~~ 通過上述配置,Nginx會作為HTTP反向代理,把訪問本機的HTTP請求,均分到后端集群的3臺服務器上。 此時使用的HTTP反向代理模塊是ngx_http_proxy_module。 一般在upstream配置塊中要指明使用的負載均衡算法,比如hash、ip_hash、least_conn。 這里沒有指定,所以使用了默認的HTTP負載均衡算法 - 加權輪詢。 ? **負載均衡流程圖** ? 在描述負載均衡模塊的具體實現前,先來看下它的大致流程: ? ![](https://box.kancloud.cn/2016-03-22_56f0c89f13acb.jpg) ? **負載均衡模塊** ? Nginx目前提供的負載均衡模塊: ngx_http_upstream_round_robin,加權輪詢,可均分請求,是默認的HTTP負載均衡算法,集成在框架中。 ngx_http_upstream_ip_hash_module,IP哈希,可保持會話。 ngx_http_upstream_least_conn_module,最少連接數,可均分連接。 ngx_http_upstream_hash_module,一致性哈希,可減少緩存數據的失效。 ? 以上負載均衡模塊的實現,基本上都遵循一套相似的流程。 ? **1. 指令的解析函數** 比如least_conn、ip_hash、hash指令的解析函數。 這些函數在解析配置文件時調用,主要用于: 檢查指令參數的合法性 指定peer.init_upstream函數指針的值,此函數用于初始化upstream塊。 ? **2. 初始化upstream塊** 在執行完指令的解析函數后,緊接著會調用所有HTTP模塊的init main conf函數。 在執行ngx_http_upstream_module的init main conf函數時,會調用所有upstream塊的初始化函數, 即在第一步中指定的peer.init_upstream,主要用于: 創建和初始化后端集群,保存該upstream塊的數據 指定peer.init,此函數用于初始化請求的負載均衡數據 ? 來看下ngx_http_upstream_module。 ~~~ ngx_http_module_t ngx_http_upstream_module_ctx = { ... ngx_http_upstream_init_main_conf, /* init main configuration */ ... }; ~~~ ~~~ static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf) { ... /* 數組的元素類型是ngx_http_upstream_srv_conf_t */ for (i = 0; i < umcf->upstreams.nelts; i++) { /* 如果沒有指定upstream塊的初始化函數,默認使用round robin的 */ init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream : ngx_http_upstream_init_round_robin; if (init(cf, uscfp[i] != NGX_OK) { return NGX_CONF_ERROR; } } ... } ~~~ **3. 初始化請求的負載均衡數據塊** 當收到一個請求后,一般使用的反向代理模塊(upstream模塊)為ngx_http_proxy_module, 其NGX_HTTP_CONTENT_PHASE階段的處理函數為ngx_http_proxy_handler,在初始化upstream機制的 函數ngx_http_upstream_init_request中,調用在第二步中指定的peer.init,主要用于: 創建和初始化該請求的負載均衡數據塊 指定r->upstream->peer.get,用于從集群中選取一臺后端服務器(這是我們最為關心的) 指定r->upstream->peer.free,當不用該后端時,進行數據的更新(不管成功或失敗都調用) ? 請求的負載均衡數據塊中,一般會有一個成員指向對應upstream塊的數據,除此之外還會有自己獨有的成員。 "The peer initialization function is called once per request. It sets up a data structure that the module will use as it tries to find an appropriate backend server to service that request; this structure is persistent across backend re-tries, so it's a convenient place to keep track of the number of connection failures, or a computed hash value. By convention, this struct is called ngx_http_upstream_<module_name>_peer_data_t." **4. 選取一臺后端服務器** 一般upstream塊中會有多臺后端,那么對于本次請求,要選定哪一臺后端呢? 這時候第三步中r->upstream->peer.get指向的函數就派上用場了: 采用特定的算法,比如加權輪詢或一致性哈希,從集群中選出一臺后端,處理本次請求。? 選定后端的地址保存在pc->sockaddr,pc為主動連接。 函數的返回值: NGX_DONE:選定一個后端,和該后端的連接已經建立。之后會直接發送請求。 NGX_OK:選定一個后端,和該后端的連接尚未建立。之后會和后端建立連接。 NGX_BUSY:所有的后端(包括備份集群)都不可用。之后會給客戶端發送502(Bad Gateway)。 ? **5. 釋放一臺后端服務器** 當不再使用一臺后端時,需要進行收尾處理,比如統計失敗的次數。 這時候會調用第三步中r->upstream->peer.get指向的函數。 函數參數state的取值: 0,請求被成功處理 NGX_PEER_FAILED,連接失敗 NGX_PEER_NEXT,連接失敗,或者連接成功但后端未能成功處理請求 ? 一個請求允許嘗試的后端數為pc->tries,在第三步中指定。當state為后兩個值時: 如果pc->tries不為0,需要重新選取一個后端,繼續嘗試,此后會重復調用r->upstream->peer.get。 如果pc->tries為0,便不再嘗試,給客戶端返回502錯誤碼(Bad Gateway)。 ? **在upstream模塊的回調** ? 負載均衡模塊的功能是從后端集群中選取一臺后端服務器,而具體的反向代理功能是由upstream模塊實現的, 比如和后端服務器建立連接、向后端服務器發送請求、處理后端服務器的響應等。 我們來看下負載均衡模塊提供的幾個鉤子函數,是在upstream模塊的什么地方回調的。 ? Nginx的HTTP反向代理模塊為ngx_http_proxy_module,其NGX_HTTP_CONTENT_PHASE階段的處理函數為 ngx_http_proxy_handler,每個請求的upstream機制是從這里開始的。 ~~~ ngx_http_proxy_handler ngx_http_upstream_create /* 創建請求的upstream實例 */ ngx_http_upstream_init /* 啟動upstream機制 */ ngx_htp_upstream_init_request /* 負載均衡模塊的入口 */ uscf->peer.init(r, uscf) /* 第三步,初始化請求的負載均衡數據塊 */ ... ngx_http_upstream_connect /* 可能會被ngx_http_upstream_next重復調用 */ ngx_event_connect_peer(&u->peer); /* 連接后端 */ pc->get(pc, pc->data); /* 第四步,從集群中選取一臺后端 */ ... /* 和后端建連成功后 */ c = u->peer.connection; c->data = r; c->write->handler = ngx_http_upstream_handler; /* 注冊的連接的讀事件處理函數 */ c->read->handler = ngx_http_upstream_handler; /* 注冊的連接的寫事件處理函數 */ u->write_event_handler = ngx_http_upstream_send_request_handler; /* 寫事件的真正處理函數 */ u->read_event_handler = ngx_http_upstream_process_header; /* 讀事件的真正處理函數 */ ~~~ 選定后端之后,在和后端通信的過程中如果發生了錯誤,會調用ngx_http_upstream_next來繼續嘗試其它的后端。 ~~~ ngx_http_upstream_next if (u->peer.sockaddr) { if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403 || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) state = NGX_PEER_NEXT; else state = NGX_PEER_FAILED; /* 第五步,釋放后端服務器 */ u->peer.free(&u->peer, u->peer.data, state); u->peer.sockaddr = NULL; } ~~~ ? **Reference** ? [1]. [http://www.evanmiller.org/nginx-modules-guide.html#proxying](http://www.evanmiller.org/nginx-modules-guide.html#proxying) [2]. [http://tengine.taobao.org/book/chapter_05.html#id5](http://tengine.taobao.org/book/chapter_05.html#id5) ?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看