<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
此時,對於修改代價而言,nginx的upstream模組體現出了它的優勢,因為它天生就快。作為附帶,nginx的設定系統提供的層次化和鬆耦合使得系統的擴充套件性也達到比較高的程度。
從本質上說,upstream屬於handler,只是他不產生自己的內容,而是通過請求後端伺服器得到內容,所以才稱為upstream(上游)。請求並取得響應內容的整個過程已經被封裝到nginx內部,所以upstream模組只需要開發若干回撥函數,完成構造請求和解析響應等具體的工作。
upstream模組回撥函數列舉如下:
函數名稱 | 描述 |
---|---|
create_request | 生成傳送到後端伺服器的請求緩衝(緩衝鏈),在初始化upstream 時使用 |
reinit_request | 在某臺後端伺服器出錯的情況,nginx會嘗試另一臺後端伺服器。 nginx選定新的伺服器以後,會先呼叫此函數,以重新初始化 upstream模組的工作狀態,然後再次進行upstream連線 |
process_header | 處理後端伺服器返回的資訊頭部。所謂頭部是與upstream server 通訊的協定規定的,比如HTTP協定的header部分,或者memcached 協定的響應狀態部分 |
abort_request | 在使用者端放棄請求時被呼叫。不需要在函數中實現關閉後端服務 器連線的功能,系統會自動完成關閉連線的步驟,所以一般此函 數不會進行任何具體工作 |
finalize_request | 正常完成與後端伺服器的請求後呼叫該函數,與abort_request 相同,一般也不會進行任何具體工作 |
input_filter | 處理後端伺服器返回的響應正文。nginx預設的input_filter會 將收到的內容封裝成為緩衝區鏈ngx_chain。該鏈由upstream的 out_bufs指標域定位,所以開發人員可以在模組以外通過該指標得到後端伺服器返回的正文資料。memcached模組實現了自己的 input_filter,在後面會具體分析這個模組。 |
input_filter_init | 初始化input filter的上下文。nginx預設的input_filter_init 直接返回 |
upstream模組使用的就是handler模組的接入方式。
同時,upstream模組的指令系統的設計也是遵循handler模組的基本規則:設定該模組才會執行該模組。
那麼,upstream模組的特別之處究竟在哪裡呢?那就是upstream模組的處理常式,upstream模組的處理常式進行的操作都包含一個固定的流程:(以memcached模組舉例,在memcached的處理常式ngx_http_memcached_handler中)
建立upstream資料結構:
ngx_http_upstream_t *u; if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream;
設定模組的tag和schema。schema現在只會用於紀錄檔,tag會用於buf_chain管理:
ngx_str_set(&u->schema, "memcached://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module;
設定upstream的後端伺服器列表資料結構:
mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u->conf = &mlcf->upstream;
設定upstream回撥函數:
u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter;
建立並設定upstream環境資料結構:
ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_ctx = ctx;
完成upstream初始化並進行收尾工作:
r->main->count++; ngx_http_upstream_init(r); return NGX_DONE;
任何upstream模組,簡單如memcached,複雜如proxy、fastcgi都是如此。
不同的upstream模組在這6步中的最大差別會出現在第2、3、4、5上。
其中第2、4兩步很容易理解,不同的模組設定的標誌和使用的回撥函數肯定不同。第5步也不難理解。
只有第3步是有點費解的,不同的模組在取得後端伺服器列表時,策略的差異非常大,有如memcached這樣簡單明瞭的,也有如proxy那樣邏輯複雜的。
第6步不同模組之間通常是一致的。將count加1,然後返回NGX_DONE。
nginx遇到這種情況,雖然會認為當前請求的處理已經結束,但是不會釋放請求使用的記憶體資源,也不會關閉與使用者端的連線。
之所以需要這樣,是因為nginx建立了upstream請求和使用者端請求之間一對一的關係,在後續使用ngx_event_pipe將upstream響應傳送回使用者端時,還要使用到這些儲存著使用者端資訊的資料結構。
將upstream請求和使用者端請求進行一對一系結,這個設計有優勢也有缺陷。優勢就是簡化模組開發,可以將精力集中在模組邏輯上,而缺陷同樣明顯,一對一的設計很多時候都不能滿足複雜邏輯的需要。
回撥函數:(依然是以memcached模組的處理常式為例)
#define LF (u_char) 'n' for (p = u->buffer.pos; p < u->buffer.last; p++) { if (*p == LF) { goto found; } }
如果在已讀入緩衝的資料中沒有發現LF(‘n’)字元,函數返回NGX_AGAIN,表示頭部未完全讀入,需要繼續讀取資料。nginx在收到新的資料以後會再次呼叫該函數。
nginx處理後端伺服器的響應頭時只會使用一塊快取,所有資料都在這塊快取中,所以解析頭部資訊時不需要考慮頭部資訊跨越多塊快取的情況。而如果頭部過大,不能儲存在這塊快取中,nginx會返回錯誤資訊給使用者端,並記錄error log,提示快取不夠大。
ngx_http_memcached_process_header的重要職責是將後端伺服器返回的狀態翻譯成返回給使用者端的狀態。例如:
u->headers_in.content_length_n = ngx_atoof(start, p - start); ··· u->headers_in.status_n = 200; u->state->status = 200; ··· u->headers_in.status_n = 404; u->state->status = 404;
u->state用於計算upstream相關的變數。比如u->state->status將被用於計算變數“upstream_status”的值。u->headers_in將被作為返回給使用者端的響應返回狀態碼。而u->headers_in.content_length_n則是設定返回給使用者端的響應的長度。
在這個函數中一定要在處理完頭部資訊以後需要將讀指標pos後移,否則這段資料也將被複制到返回給使用者端的響應的正文中,進而導致正文內容不正確。
ngx_http_memcached_process_header函數完成響應頭的正確處理,應該返回NGX_OK。如果返回NGX_AGAIN,表示未讀取完整資料,需要從後端伺服器繼續讀取資料。返回NGX_DECLINED無意義,其他任何返回值都被認為是出錯狀態,nginx將結束upstream請求並返回錯誤資訊。
ngx_http_memcached_filter_init:修正從後端伺服器收到的內容長度。因為在處理header時沒有加上這部分長度。
ngx_http_memcached_filter:
memcached模組是少有的帶有處理正文的回撥函數的模組。
因為memcached模組需要過濾正文末尾CRLF “END” CRLF,所以實現了自己的filter回撥函數。
處理正文的實際意義是將從後端伺服器收到的正文有效內容封裝成ngx_chain_t,並加在u->out_bufs末尾。
nginx並不進行資料拷貝,而是建立ngx_buf_t資料結構指向這些資料記憶體區,然後由ngx_chain_t組織這些buf。這種實現避免了記憶體大量搬遷,也是nginx高效的原因之一。
到此這篇關於Nginx中upstream模組的具體用法的文章就介紹到這了,更多相關Nginx upstream模組內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45