<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之旅 廣告
                ### [upstream]()機制 Nginx提供的upstream機制,是nginx設計理念的忠實體現。異步、無阻塞,這是nginx的追求,任何對這種設計思想的違反,都會導致nginx達不到它預期的性能,包括nginx提供的fastCGI也是如此。 ? Upstream到底用來干什么呢?就是nginx在正常的請求處理過程中,需要訪問其他SERVER,這時,nginx提供了這樣的機制,把底層的http通訊全部做完。最重要的是,upstream保證了在這個請求中對其他SERVER的通訊,完全是無阻塞和異步的。個人認為,如果nginx沒有提供upstream,當開發者遇到這種情形要么自己寫一套多路復用IO處理機制來做,要么放棄異步去調用connection里的同步方法,就不能稱為真正的高性能異步WEB SERVER了。 ? Upstream實現得其實非常狹隘,因為nginx試圖把upstream做成一種proxy,也就是說nginx會對其他SERVER訪問后,對client的返回也接管,這個很惡心。如果你不需要這個功能,需要在ngx_http_upstream_process_header里,調用你的module處理response后就返回,不要繼續向下執行。 ? Upstream有六個需要module developer實現的方法,分別是: ???ngx_int_t?????????????????????(*create_request)(ngx_http_request_t *r); ???ngx_int_t?????????????????????(*reinit_request)(ngx_http_request_t *r); ???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, ????????????????????????????????????????ngx_table_elt_t *h, size_t prefix); ? upstream在真正實現HTTP通訊時會調用到這些函數。那么upstream的是如何進行的?首先,我們需要調用ngx_http_upstream_init來開始upstream之旅了。 ? ngx_http_upstream_init首先會去調用create_request函數,這時開發者可以在這里把HTTP請求構造好。構造完請求包后,nginx會去連接remote server,這又是一個異步事件,所以需要注冊回調函數為ngx_http_upstream_handler,也就是說,當連接成功建立后,nginx的epoll會調用ngx_http_upstream_handler來處理建立好的這個連接,同時把發送HTTP請求的處理函數注冊為ngx_http_upstream_send_request_handler。 ? 現在與remote server建立好連接了,ngx_http_upstream_handle調用ngx_http_upstream_send_request_handler來發送create_request完成的HTTP請求包了。這里實際完成發送請求任務的是ngx_http_upstream_send_request方法,而ngx_http_upstream_send_request又是調用ngx_output_chain來把請求發送出去。成功以后,開始等待讀事件的來臨,如果有數據返回,則調用ngx_http_upstream_process_header來處理remote server的response了,等到確認接收到完整的response后,會調用我們實現的process_header注冊函數來處理response。upstream處理完后會調用注冊的finalize_request函數來清理開發者需要做的工作。 ? ### [內存使用]() Nginx給用戶提供了內存池功能,所以developer在使用時,應當盡量避免繞過nginx內存池來操作內存。 ? 這里不去分析nginx內存池的實現,只簡要的說明如何使用它。 申請一塊內存時,必須先拿到內存池的指針,然后傳入內存塊大小,nginx實際上會移動指針指向內存池中的空閑內存,如果失敗則返回NULL,內存池大小有限且可配,所以我們必須每次申請內存都要檢查是否申請成功。 我們看下最簡單的一個分配buf函數: ~~~ ngx_buf_t * ngx_create_temp_buf(ngx_pool_t *pool, size_t size) { ??? ngx_buf_t*b; ??? b =ngx_calloc_buf(pool); ??? if (b ==NULL) { ??????? returnNULL; ??? } ??? b->start= ngx_palloc(pool, size); ??? if(b->start == NULL) { ??????? returnNULL; ??? } ??? b->pos =b->start; ??? b->last= b->start; ??? b->end =b->last + size; ???b->temporary = 1; ??? return b; } ~~~ 可以看到,很簡單的從內存池中申請到,釋放則由pool自動進行,很好的垃圾回收機制。 ### [配置文件的使用]() 在ngx_command_t中,定義好需要讀取的配置項名稱,以及處理該配置項的方法,這樣就可以nginx.conf里放置相應的配置項,在module里使用。 ? 例如: 在nginx.conf里加入下行配置: dmsargname dcname filesize blobid; ? 則需要在module里的ngx_command_t數組里分配如下: ~~~ ???????? { ????????????????? ngx_string("dmsargname"), ???????? NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1234, ????????????????? ngx_read_dmsargname, ????????????????? NGX_HTTP_LOC_CONF_OFFSET, ????????????????? offsetof(ngx_webex_DMD_loc_conf_t,argnameFromDC), ????????????????? NULL ???????? },????? ~~~ 實際的處理函數為ngx_read_dmsargname。NGX_CONF_TAKE1234意為最多讀取四個參數。 ? 讀取參數函數簡易實現: ~~~ static char * /* {{{ ngx_read_datastore */ ngx_read_dmsargname(ngx_conf_t *cf, ngx_command_t*cmd, void *conf) { ???????? ngx_http_core_loc_conf_t???*clcf; ???????? ngx_webex_DMD_loc_conf_t?*ulcf = conf; ???????? ngx_str_t??????????????????*value; ???????? value =cf->args->elts; ???????? clcf =ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); ???????? ulcf->argnameFromDC= value[1]; ???????? ulcf->argnameFilesize= value[2]; ???????? ulcf->argnameBlobID= value[3]; ??? returnNGX_CONF_OK; } ~~~ ? ### [Nginx]()封裝的常用數據結構 這個必須要說下,因為處理http請求時,必須處理head,無論是讀取head還是插入head,都需要和ngx_list_t這個數據結構打交道,nginx框架是把head都放到ngx_list_t??????????????????????headers;數據結構里的。 ? list一共有三種操作: ngx_list_create();//創建及初始化隊列 ngx_list_init();???????//初始化隊列 ngx_list_push();//找到下一個插入位置的指針并返回 很明顯,設計者為了靈活性,沒有提供遍歷方法,那么首先,應該怎么遍歷它?比如,拿到一個request后,最應該先分析head了。 ? 畫個圖看看: ngx_list_t <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="142" valign="top"><p class="MsoNormal"><span lang="EN-US">pool</span></p></td><td width="142" valign="top"><p class="MsoNormal"><span lang="EN-US">nalloc</span></p></td><td width="142" valign="top"><p class="MsoNormal"><span lang="EN-US">size</span></p></td><td width="142" valign="top"><p class="MsoNormal"><span lang="EN-US">part</span></p></td><td width="142" valign="top"><p class="MsoNormal"><span lang="EN-US">last</span></p></td></tr></tbody></table> <!--[if gte vml 1]> <![endif]-->![](image/56a5c7ce92dcb.gif) ngx_list_part_s <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="237" valign="top"><p class="MsoNormal"><span lang="EN-US">nelts</span></p></td><td width="237" valign="top"><p class="MsoNormal"><span lang="EN-US">elts</span></p></td><td width="237" valign="top"><p class="MsoNormal"><span lang="EN-US">next</span></p></td></tr></tbody></table> <!--[if gte vml 1]> <![endif]-->![](image/56a5c7ceca230.gif) ngx_table_elt_t <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="178" valign="top"><p class="MsoNormal"><span lang="EN-US">Key</span></p></td><td width="178" valign="top"><p class="MsoNormal"><span lang="EN-US">Value</span></p></td><td width="178" valign="top"><p class="MsoNormal"><span lang="EN-US">Hash</span></p></td><td width="178" valign="top"><p class="MsoNormal"><span lang="EN-US">lowcase</span></p></td></tr></tbody></table> ? [圖表]()<!--[if supportFields]>?SEQ圖表 /* ARABIC<![endif]-->5<!--[if supportFields]><![endif]-->-nginx封裝的list結構 ? 當然ngx_table_elt_t結構只是head里的ngx_list_t所用,實際上每個元素可以是任意類型,由elts指針所指。 ? ngx_list_t里的nalloc和size,分別表示元素桶的數量和每個元素的大小,所以這里大家可以看出,該數據結構是定長內存組成的了吧。元素桶這個概念,大家可以理解為ngx_list_part_s結構,這個結構里可以保存多個元素,元素數量由nelts決定。每個元素是由ngx_list_part_s->elts指向的,長度為ngx_list_t->size ? 給段遍歷list取得每個head的代碼看看: ~~~ ???????? part =&r->upstream->headers_in.headers.part; ???????? header= part->elts; ???????? for (i= 0; /* void */; i++) { ???????? ??????? if (i >= part->nelts) { ???????? ??????????? if (part->next == NULL) { ???????? ???????????????break; ???????? ??????????? } ???????? ??????????? part = part->next; ???????? ??????????? header = part->elts; ???????? ??????????? i = 0; ???????? ??????? } ????????????????? if(header[i].hash == 0) { ???????? ??????????? continue; ???????? ??????? } ????????????????? //header[i].key就是head的名字,header[i].value就是head的值了 } ~~~ ? [總結] 開發nginx module,可以非常靈活的實現自己需要的功能。很多時候我們需要修改源碼才能實現自己的特定功能,比如,nginx的thumbnail resize功能,不支持實時的對每一個請求按照指定的size來壓縮,實際上在它的代碼中完全可以做到,只需要稍微修改下源碼而已。 又如upstream,nginx把它當足是個proxy機制,如果我們想讓它只做為異步網絡調用,也只需要在upstream_process_header里做些改動。 ? 在需要某些特殊的功能時,我們最應該首先閱讀nginx的源碼,通常都會發現很多意想不到的收獲。 ? Nginx的性能確實不錯,對http協議的處理也很高效,在我們需要高性能webserver時,應該去優先考慮它。
                  <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>

                              哎呀哎呀视频在线观看