Nginx流量同時轉(zhuǎn)發(fā)多后端(流量鏡像分發(fā))
一、背景
請注意,我這里標題提到的是一個請求流量被同時轉(zhuǎn)發(fā)到2個或者多個后端,而非負載均衡的場景!!!
負載均衡的場景我想就不用贅述了,定義一個upstrem, upstrem定了一組提供相同服務的server地址, 最后通過proxy_pass轉(zhuǎn)發(fā)到這個upstrem。 但是,這個是負載均衡的場景,那就意味著,無論你的算法如何,最終只會轉(zhuǎn)發(fā)到一個server目標上。
那文章標題提到的流量鏡像是什么場景呢? 那就是一次HTTP請求,被同時轉(zhuǎn)發(fā)到多個后端。 例如一次請求,既代理到A服務、也代理到B服務,發(fā)送了2次或者n次的情況。
為什么有這個流量鏡像分發(fā)需求呢? 我們有這么一個場景, 由于新版服務和舊版服務的代碼變更, 出于某種原因,既想保留舊版、也想保留新版做過渡, 所以想把前端的流量分發(fā)2次,這樣新舊系統(tǒng)的數(shù)據(jù)都能保存下來,不影響業(yè)務使用。 等過段時間,過渡期好了之后,再把舊版server下掉。
尋找了一些資料,openresty+lua也許能實現(xiàn),但是我測試不行。 最終發(fā)現(xiàn)了Nginx本身就有這個功能模塊。 這個就是mirror模塊。
二、Nginx mirror模塊
mirror模塊從Nginx1.13開始就是內(nèi)置了,所以只要是1.13版本以后就可以直接使用,不需要重新編譯nginx。
官方文檔地址: Module ngx_http_mirror_module
從配置樣例來看,很簡單。 首先代理的location / 還是先做主代理站點, proxy_pass到$backend, 之后再加一個mirror /mirror; 流量鏡像分發(fā)到/mirror的URL, 再看下面定了了/mirror的location定義, 這里面再次定義proxy_pass 到test_backend, 從而完成流量鏡像分發(fā)的目的。
三、實際配置測試
1、準備2個flask服務,8081、8082端口
1、flask-8081.py
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/api/data', methods=['GET', 'POST']) def save_request_data(): headers = dict(request.headers) if request.is_json: # 如果請求體是 JSON 格式 body = request.get_json(silent=True) elif request.content_type and 'form' in request.content_type.lower(): # 如果請求體是表單數(shù)據(jù) body = request.form.to_dict() else: # 其他類型的請求體(例如純文本) body = request.data.decode('utf-8') args = request.args.to_dict() data = { "headers": headers, "body": body, "args": args } with open('request_data.txt', 'a') as file: file.write(str(data)) file.write('\n') return jsonify({ "status": "success", "message": "Data has been saved." }) if __name__ == '__main__': app.run(host='0.0.0.0', port=8081, debug=True)
2、flask-8082.py
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/api/data', methods=['GET', 'POST']) def save_request_data(): headers = dict(request.headers) if request.is_json: # 如果請求體是 JSON 格式 body = request.get_json(silent=True) elif request.content_type and 'form' in request.content_type.lower(): # 如果請求體是表單數(shù)據(jù) body = request.form.to_dict() else: # 其他類型的請求體(例如純文本) body = request.data.decode('utf-8') args = request.args.to_dict() data = { "headers": headers, "body": body, "args": args } with open('request_data.txt', 'a') as file: file.write(str(data)) file.write('\n') return jsonify({ "status": "success", "message": "Data has been saved." }) if __name__ == '__main__': app.run(host='0.0.0.0', port=8082, debug=True)
2、修改nginx的配置文件
location /api/data/ { #優(yōu)先轉(zhuǎn)發(fā)172.16.0.3:8081 proxy_pass http://172.16.0.3:8081/api/data; #同時, 流量鏡像轉(zhuǎn)發(fā)到/mirror/, 172.16.0.3:8082 mirror /mirror/; } location /mirror/ { internal; proxy_pass http://172.16.0.3:8082/api/data; }
3、測試結(jié)果
CURL請求代理的nginx端口,然后分別查看8081、8082端口是否同時接收到相同的HTTP請求:
觀察8081端口程序日志輸出:
觀察8082端口程序日志 輸出:
由此發(fā)現(xiàn),我們在nginx發(fā)生的2次請求, 2個后端8081、8082同時收到了2次請求。 由此證明,我們的流量鏡像分發(fā)是符合預期的。
4、最終響應內(nèi)容是8081還是8082的內(nèi)容?
結(jié)論: 一切都以第一個proxy_pass的站點的實際響應結(jié)果為準,不管第二個被mirror流量分發(fā)站點的響應情況是否正常
服務運行情況以及響應信息表格如下:
8081 正常 | 8082正常 | 以8081內(nèi)容為準, 正常, 2臺都會轉(zhuǎn)發(fā) |
8081 正常 | 8082異常 | 以8081內(nèi)容為準, 正常, 8082不會在后臺轉(zhuǎn)發(fā) |
8081 異常 | 8082正常 | 以8081內(nèi)容為準, 異常, 8082會在后臺轉(zhuǎn)發(fā) |
8081 異常 | 8082異常 | 以8081內(nèi)容為準, 異常, 8082不會在后臺轉(zhuǎn)發(fā) |
四、總結(jié)
mirror流量鏡像分發(fā)的場景還是有實際存在意義的,要不然官方也不會把它納入到內(nèi)置模塊當中。具體的需求情況需要自己判定。
流量轉(zhuǎn)發(fā)畢竟是2次轉(zhuǎn)發(fā)過程,對于nginx的壓力、以及性能應該是會有損耗的,但是具體損耗沒測試過, 這個讀者朋友可以自行測試。
到此這篇關于Nginx流量同時轉(zhuǎn)發(fā)多后端(流量鏡像分發(fā))的文章就介紹到這了,更多相關Nginx 流量鏡像分發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
nginx配置教程之a(chǎn)dd_header的坑詳解
這篇文章主要給大家介紹了關于nginx配置教程之a(chǎn)dd_header坑的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-02-02基于Xen的VPS ubuntu+nginx+php安裝教程
跟蹤vps已經(jīng)很久了,但是因為需要特殊端口開服務,所以符合條件的多為Xen平臺的vps。眾多比較之后選擇了vpslink在西雅圖機房,速度還不錯。2010-07-07Centos7安裝、卸載nginx及配置,配置成系統(tǒng)服務方式(一步到位)
這篇文章主要介紹了Centos7安裝、卸載nginx及配置,配置成系統(tǒng)服務方式(一步到位),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12