Nginx流量同時(shí)轉(zhuǎn)發(fā)多后端(流量鏡像分發(fā))
一、背景
請(qǐng)注意,我這里標(biāo)題提到的是一個(gè)請(qǐng)求流量被同時(shí)轉(zhuǎn)發(fā)到2個(gè)或者多個(gè)后端,而非負(fù)載均衡的場(chǎng)景!!!
負(fù)載均衡的場(chǎng)景我想就不用贅述了,定義一個(gè)upstrem, upstrem定了一組提供相同服務(wù)的server地址, 最后通過proxy_pass轉(zhuǎn)發(fā)到這個(gè)upstrem。 但是,這個(gè)是負(fù)載均衡的場(chǎng)景,那就意味著,無論你的算法如何,最終只會(huì)轉(zhuǎn)發(fā)到一個(gè)server目標(biāo)上。

那文章標(biāo)題提到的流量鏡像是什么場(chǎng)景呢? 那就是一次HTTP請(qǐng)求,被同時(shí)轉(zhuǎn)發(fā)到多個(gè)后端。 例如一次請(qǐng)求,既代理到A服務(wù)、也代理到B服務(wù),發(fā)送了2次或者n次的情況。

為什么有這個(gè)流量鏡像分發(fā)需求呢? 我們有這么一個(gè)場(chǎng)景, 由于新版服務(wù)和舊版服務(wù)的代碼變更, 出于某種原因,既想保留舊版、也想保留新版做過渡, 所以想把前端的流量分發(fā)2次,這樣新舊系統(tǒng)的數(shù)據(jù)都能保存下來,不影響業(yè)務(wù)使用。 等過段時(shí)間,過渡期好了之后,再把舊版server下掉。
尋找了一些資料,openresty+lua也許能實(shí)現(xiàn),但是我測(cè)試不行。 最終發(fā)現(xiàn)了Nginx本身就有這個(gè)功能模塊。 這個(gè)就是mirror模塊。
二、Nginx mirror模塊
mirror模塊從Nginx1.13開始就是內(nèi)置了,所以只要是1.13版本以后就可以直接使用,不需要重新編譯nginx。
官方文檔地址: Module ngx_http_mirror_module


從配置樣例來看,很簡(jiǎn)單。 首先代理的location / 還是先做主代理站點(diǎn), proxy_pass到$backend, 之后再加一個(gè)mirror /mirror; 流量鏡像分發(fā)到/mirror的URL, 再看下面定了了/mirror的location定義, 這里面再次定義proxy_pass 到test_backend, 從而完成流量鏡像分發(fā)的目的。
三、實(shí)際配置測(cè)試
1、準(zhǔn)備2個(gè)flask服務(wù),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:
# 如果請(qǐng)求體是 JSON 格式
body = request.get_json(silent=True)
elif request.content_type and 'form' in request.content_type.lower():
# 如果請(qǐng)求體是表單數(shù)據(jù)
body = request.form.to_dict()
else:
# 其他類型的請(qǐng)求體(例如純文本)
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:
# 如果請(qǐng)求體是 JSON 格式
body = request.get_json(silent=True)
elif request.content_type and 'form' in request.content_type.lower():
# 如果請(qǐng)求體是表單數(shù)據(jù)
body = request.form.to_dict()
else:
# 其他類型的請(qǐng)求體(例如純文本)
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;
#同時(shí), 流量鏡像轉(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、測(cè)試結(jié)果
CURL請(qǐng)求代理的nginx端口,然后分別查看8081、8082端口是否同時(shí)接收到相同的HTTP請(qǐng)求:

觀察8081端口程序日志輸出:

觀察8082端口程序日志 輸出:

由此發(fā)現(xiàn),我們?cè)趎ginx發(fā)生的2次請(qǐng)求, 2個(gè)后端8081、8082同時(shí)收到了2次請(qǐng)求。 由此證明,我們的流量鏡像分發(fā)是符合預(yù)期的。
4、最終響應(yīng)內(nèi)容是8081還是8082的內(nèi)容?
結(jié)論: 一切都以第一個(gè)proxy_pass的站點(diǎn)的實(shí)際響應(yīng)結(jié)果為準(zhǔn),不管第二個(gè)被mirror流量分發(fā)站點(diǎn)的響應(yīng)情況是否正常
服務(wù)運(yùn)行情況以及響應(yīng)信息表格如下:
| 8081 正常 | 8082正常 | 以8081內(nèi)容為準(zhǔn), 正常, 2臺(tái)都會(huì)轉(zhuǎn)發(fā) |
| 8081 正常 | 8082異常 | 以8081內(nèi)容為準(zhǔn), 正常, 8082不會(huì)在后臺(tái)轉(zhuǎn)發(fā) |
| 8081 異常 | 8082正常 | 以8081內(nèi)容為準(zhǔn), 異常, 8082會(huì)在后臺(tái)轉(zhuǎn)發(fā) |
| 8081 異常 | 8082異常 | 以8081內(nèi)容為準(zhǔn), 異常, 8082不會(huì)在后臺(tái)轉(zhuǎn)發(fā) |
四、總結(jié)
mirror流量鏡像分發(fā)的場(chǎng)景還是有實(shí)際存在意義的,要不然官方也不會(huì)把它納入到內(nèi)置模塊當(dāng)中。具體的需求情況需要自己判定。
流量轉(zhuǎn)發(fā)畢竟是2次轉(zhuǎn)發(fā)過程,對(duì)于nginx的壓力、以及性能應(yīng)該是會(huì)有損耗的,但是具體損耗沒測(cè)試過, 這個(gè)讀者朋友可以自行測(cè)試。
到此這篇關(guān)于Nginx流量同時(shí)轉(zhuǎn)發(fā)多后端(流量鏡像分發(fā))的文章就介紹到這了,更多相關(guān)Nginx 流量鏡像分發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Linux環(huán)境下nginx搭建簡(jiǎn)易圖片服務(wù)器
這篇文章主要介紹了Linux環(huán)境下nginx搭建簡(jiǎn)易圖片服務(wù)器,需要的朋友可以參考下2014-10-10
nginx-rtmp-module構(gòu)建流媒體直播服務(wù)器實(shí)戰(zhàn)指南
本文主要介紹了nginx-rtmp-module構(gòu)建流媒體直播服務(wù)器實(shí)戰(zhàn)指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
Nginx配置移動(dòng)端和PC端自動(dòng)跳轉(zhuǎn)方式
文章介紹了如何通過Nginx配置PC端和移動(dòng)端自動(dòng)跳轉(zhuǎn),PC端和移動(dòng)端各有獨(dú)立的域名,PC端訪問任何域名時(shí)會(huì)跳轉(zhuǎn)到www.yxf.com,移動(dòng)端訪問任何域名時(shí)會(huì)跳轉(zhuǎn)到m.yxf.com,配置時(shí)需要修改Nginx的conf文件,使用302或301重定向2025-11-11
聊聊Django+uwsgi+nginx服務(wù)器部署問題
這篇文章主要介紹了Django+uwsgi+nginx服務(wù)器部署的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
Nginx配置本地圖片服務(wù)器的實(shí)現(xiàn)
本文主要介紹了Nginx配置本地圖片服務(wù)器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
解決Nginx 配置 proxy_pass 后 返回404問題
這篇文章主要介紹了Nginx 配置 proxy_pass 后 返回404問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01

