Nginx中的upstream模組如何使用
upstream模組簡介
nginx模組一般被分成三大類:handler、filter和upstream。在前面的章節中,讀者已經了解了handler、filter。利用這兩類模組,可以讓nginx輕鬆完成任何單機工作。
而upstream模組,將使nginx跨越單機的限制,完成網路資料的接收、處理和轉送。
資料轉送功能,為nginx提供了跨越單機的橫向處理能力,使nginx擺脫只能為終端節點提供單一功能的限制,使它具備了網路應用層級的拆分、封裝和整合的功能。
資料轉送是nginx有能力建構一個網路應用的關鍵元件。當然,鑑於開發成本的問題,一個網頁應用的關鍵元件一開始往往會採用高階程式語言開發。但是當系統到達一定規模,並且需要更重視效能的時候,為了達到所要求的效能目標,高階語言所發展的元件必須進行結構化修改。
此時,對於修改代價而言,nginx的upstream模組體現出了它的優勢,因為它天生就快。作為附帶,nginx的配置系統提供的層次化和鬆散耦合使得系統的擴展性也達到比較高的程度。
upstream模組介面
本質上說,upstream屬於handler,只是他不產生自己的內容,而是透過請求後端伺服器得到內容,所以才稱為upstream(上游) 。請求並且取得回應內容的整個過程已經被封裝到nginx內部,所以upstream模組只需要開發若干回呼函數,完成建構請求和解析回應等特定的工作。
upstream模組回呼函數列舉如下:
#函數名稱 | 描述 |
---|---|
create_request | 產生傳送到後端伺服器的請求緩衝(緩衝鏈),在初始化upstream 時使用 |
reinit_request | #在某台後端伺服器出錯的情況,nginx會嘗試另一台後端伺服器。 nginx選定新的伺服器以後,會先呼叫此函數,以重新初始化upstream模組的工作狀態,然後再進行upstream連線 |
##處理後端伺服器傳回的資訊頭部。所謂頭部是與upstream server 通訊的協定規定的,例如HTTP協定的header部分,或是memcached 協定的回應狀態部分 | |
memcached模組分析
memcache是高效能的分散式cache系統,得到了非常廣泛的應用。 memcache定義了一套私有通訊協議,使得無法透過HTTP請求來存取memcache。但協議本身簡單高效,而且memcache使用廣泛,所以大部分現代開發語言和平台都提供了memcache支持,方便開發者使用memcache。
nginx提供了ngx_http_memcached模組,提供從memcache讀取資料的功能,而不提供向memcache寫資料的功能。
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模組的處理函數為例)
ngx_http_memcached_create_request:很簡單的依照設定的內容產生一個key,接著產生一個「get $key」的請求,放在r->upstream->request_bufs裡面。
ngx_http_memcached_reinit_request:無需初始化。
ngx_http_memcached_abort_request:無需額外操作。
ngx_http_memcached_finalize_request:無需額外操作。
ngx_http_memcached_process_header:模組的業務重點函數。 memcache協定的頭部資訊被定義為第一行文本,程式碼如下:
#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模組如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

可以通過以下步驟查詢 Docker 容器名稱:列出所有容器(docker ps)。篩選容器列表(使用 grep 命令)。獲取容器名稱(位於 "NAMES" 列中)。

如何在 Windows 中配置 Nginx?安裝 Nginx 並創建虛擬主機配置。修改主配置文件並包含虛擬主機配置。啟動或重新加載 Nginx。測試配置並查看網站。選擇性啟用 SSL 並配置 SSL 證書。選擇性設置防火牆允許 80 和 443 端口流量。

確認 Nginx 是否啟動的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 檢查端口 80 是否開放;3. 查看系統日誌中 Nginx 啟動消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

Docker 容器啟動步驟:拉取容器鏡像:運行 "docker pull [鏡像名稱]"。創建容器:使用 "docker create [選項] [鏡像名稱] [命令和參數]"。啟動容器:執行 "docker start [容器名稱或 ID]"。檢查容器狀態:通過 "docker ps" 驗證容器是否正在運行。

在雲服務器上配置 Nginx 域名的方法:創建 A 記錄,指向雲服務器的公共 IP 地址。在 Nginx 配置文件中添加虛擬主機塊,指定偵聽端口、域名和網站根目錄。重啟 Nginx 以應用更改。訪問域名測試配置。其他注意事項:安裝 SSL 證書啟用 HTTPS、確保防火牆允許 80 端口流量、等待 DNS 解析生效。

在 Docker 中創建容器: 1. 拉取鏡像: docker pull [鏡像名] 2. 創建容器: docker run [選項] [鏡像名] [命令] 3. 啟動容器: docker start [容器名]

可以查詢 Nginx 版本的方法有:使用 nginx -v 命令;查看 nginx.conf 文件中的 version 指令;打開 Nginx 錯誤頁,查看頁面的標題。

啟動 Nginx 服務器需要按照不同操作系統採取不同的步驟:Linux/Unix 系統:安裝 Nginx 軟件包(例如使用 apt-get 或 yum)。使用 systemctl 啟動 Nginx 服務(例如 sudo systemctl start nginx)。 Windows 系統:下載並安裝 Windows 二進製文件。使用 nginx.exe 可執行文件啟動 Nginx(例如 nginx.exe -c conf\nginx.conf)。無論使用哪種操作系統,您都可以通過訪問服務器 IP
