当前位置: 首页 > article >正文

Nginx流量同时转发多后端(流量镜像分发)

一、背景

        请注意,我这里标题提到的是一个请求流量被同时转发到2个或者多个后端,而非负载均衡的场景!!!

        负载均衡的场景我想就不用赘述了,定义一个upstrem, upstrem定了一组提供相同服务的server地址, 最后通过proxy_pass转发到这个upstrem。  但是,这个是负载均衡的场景,那就意味着,无论你的算法如何,最终只会转发到一个server目标上。

        

        那文章标题提到的流量镜像是什么场景呢?  那就是一次HTTP请求,被同时转发到多个后端。 例如一次请求,既代理到A服务、也代理到B服务,发送了2次或者n次的情况。

        

       为什么有这个流量镜像分发需求呢?  我们有这么一个场景, 由于新版服务和旧版服务的代码变更, 出于某种原因,既想保留旧版、也想保留新版做过渡, 所以想把前端的流量分发2次,这样新旧系统的数据都能保存下来,不影响业务使用。 等过段时间,过渡期好了之后,再把旧版server下掉。

        寻找了一些资料,openresty+lua也许能实现,但是我测试不行。 最终发现了Nginx本身就有这个功能模块。 这个就是mirror模块。

二、Nginx mirror模块

        mirror模块从Nginx1.13开始就是内置了,所以只要是1.13版本以后就可以直接使用,不需要重新编译nginx。

        官方文档地址: Module ngx_http_mirror_module

 

  从配置样例来看,很简单。 首先代理的location / 还是先做主代理站点, proxy_pass到$backend,  之后再加一个mirror  /mirror;  流量镜像分发到/mirror的URL,  再看下面定了了/mirror的location定义, 这里面再次定义proxy_pass 到test_backend, 从而完成流量镜像分发的目的。

三、实际配置测试

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():
        # 如果请求体是表单数据
        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():
        # 如果请求体是表单数据
        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/ {
       #优先转发172.16.0.3:8081
       proxy_pass http://172.16.0.3:8081/api/data;
       #同时, 流量镜像转发到/mirror/, 172.16.0.3:8082
       mirror /mirror/;
    }
    location /mirror/ {
       internal;
       proxy_pass http://172.16.0.3:8082/api/data;
    }

3、测试结果

   CURL请求代理的nginx端口,然后分别查看8081、8082端口是否同时接收到相同的HTTP请求:

   

   观察8081端口程序日志输出:

   观察8082端口程序日志 输出:

        由此发现,我们在nginx发生的2次请求, 2个后端8081、8082同时收到了2次请求。 由此证明,我们的流量镜像分发是符合预期的。

 4、最终响应内容是8081还是8082的内容?

        结论:   一切都以第一个proxy_pass的站点的实际响应结果为准,不管第二个被mirror流量分发站点的响应情况是否正常

        服务运行情况以及响应信息表格如下:

8081 正常8082正常以8081内容为准, 正常, 2台都会转发
8081 正常8082异常以8081内容为准, 正常,  8082不会在后台转发
8081 异常8082正常以8081内容为准, 异常, 8082会在后台转发
8081 异常8082异常以8081内容为准, 异常, 8082不会在后台转发

四、总结

        mirror流量镜像分发的场景还是有实际存在意义的,要不然官方也不会把它纳入到内置模块当中。具体的需求情况需要自己判定。

        流量转发毕竟是2次转发过程,对于nginx的压力、以及性能应该是会有损耗的,但是具体损耗没测试过, 这个读者朋友可以自行测试。


http://www.kler.cn/a/370932.html

相关文章:

  • 在 Webpack 中使用 预加载(Preloading) 技术可以通过动态导入(import())以及指定预加载的方式来进行优化
  • 【Rust自学】12.2. 读取文件
  • React:构建用户界面的JavaScript库
  • 如何使用 Excel 进行多元回归分析?
  • Linux 服务器挖矿木马防护实战:快速切断、清理与加固20250114
  • 最左前缀匹配原则
  • WPF+MVVM案例实战(十一)- 环形进度条实现
  • Flink CDC系列之:学习理解核心概念——Data Sink
  • RCNN系列算法
  • ES、BOM 和 DOM
  • java-web-day6-下-知识点小结
  • Android性能优化之2个帧率和卡顿监控方案(附实现代码)
  • 【网页内嵌PDF下载】PDF.js妙用
  • MFC tcpclient
  • STM32主从定时器输出个数、频率可调的脉冲
  • 知名数字中国战略布局与新质生产力培训师讲师培训讲师唐兴通数字经济数字化转型专家教授学者大数据AIGC大模型智能化战略数字时代商业模式创新
  • Hana 到 PostgreSQL 数据迁移同步
  • QT 从ttf文件中读取图标
  • 使用命令行自动生成markdown文档目录
  • 针对初学者的PyTorch项目推荐
  • 【论文阅读】Real-ESRGAN
  • 拥塞控制与TCP子问题(粘包问题,异常情况等)
  • OpenHarmony4.0配置应用开机自启
  • 软件工程之软件系统设计与软件开发方法
  • Pandas库学习Day20
  • 操作系统--进程