nginx动态匹配(分流)

如果实例是固定的几个,可以直接在nginx.conf中配置upstream进行负载均衡,但是如果这个实例是由用户动态添加的,这种方式就不行了。可以考虑:
1、nginx层Lua实现,存在以下问题

  • 需要安装lua
  • 重做nginx容器

2、python后端拦截器

前端请求 --> nginx代理到flask服务 --> python路由服务 --> 代码逻辑拿到实例地址 --> 转发请求到指定实例 --> 返回响应给前端

nifi-api_flask-1.py 与 nifi-api_flask-2.py

python 复制代码
from flask import Flask
from markupsafe import escape
app = Flask(__name__)

@app.route('/nifi-api', methods=['GET'])  # 没有声明请求方式,默认是get请求
def hello_world():
    return "<p>Hello, World!</p>"

@app.route('/nifi-api/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return f'User {escape(username)}'

@app.route('/nifi-api/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return f'Post {post_id}'

@app.route('/nifi-api/path/<path:subpath>')
def show_subpath(subpath):
    # show the subpath after /path/
    return f'Subpath {escape(subpath)}'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8001)

main_flask.py: dispatch_request不会自动处理post等请求,受到Flask-restful限制(GET/HEAD/OPTIONS),可分别get、post跳转到dispatch_request处理

python 复制代码
from flask import Flask, Blueprint, request, Response
from flask_restful import Api, Resource
import httpx
import random


# -------------------- 数据库查询函数 --------------------
def get_nifi_url_for_user(user_id: int):
    """
    根据 user_id 从数据库中查出对应的 NiFi 实例 URL
    """
    map_dict = {
        1: "http://192.168.208.131:8001",
        2: "http://192.168.208.131:8002",
    }
    return map_dict[user_id]
   
  
# -------------------- NiFi 动态代理类 --------------------
class NifiProxyApi(Resource):
    def get(self, path=None):
        return self.dispatch_request(path)
       
    def post(self, path=None):
        return self.dispatch_request(path)
       
    def put(self, path=None):
        return self.dispatch_request(path)
       
    def delete(self, path=None):
        return self.dispatch_request(path)
       
    def patch(self, path=None):
        return self.dispatch_request(path)
       
    def options(self, path=None):
        return self.dispatch_request(path)
   
    def dispatch_request(self, path=None):
        """
        统一入口,拦截所有 /nifi-api/<path:path> 请求
        根据用户查数据库,然后转发到对应 NiFi 实例
        """
        # 1. 获取用户 ID(可改为 JWT 或 session)
        user_id = random.choice([1, 2])
        print(f"user_id : {user_id}")
        if not user_id:
            return Response("缺少用户信息", status=401)
           
        # 2. 查数据库获取对应 NiFi 实例地址
        nifi_url = get_nifi_url_for_user(user_id)
        print(f"nifi_url: {nifi_url}")
        if not nifi_url:
            return Response("未找到该用户对应的 NiFi 实例", status=404)

        # 3. 构建目标 URL
        target_url = f"{nifi_url}/nifi-api/{path}" if path else f"{nifi_url}/nifi-api"
        method = request.method
        body = request.get_data()
        # 过滤掉 Host 避免冲突
        headers = {k: v for k, v in request.headers if k.lower() != 'host'}
        print(f"target_url: {target_url}, method: {method}, body: {body}, params: {request.args}")

        # 4. 转发请求到 NiFi
        with httpx.Client(verify=False) as client:
            resp = client.request(
                method=method,
                url=target_url,
                headers=headers,
                content=body,
                params=request.args
            )

        # 5. 过滤掉不适合直接返回给客户端的头部
        excluded_headers = ['content-encoding', 'transfer-encoding', 'connection']
        response_headers = [(k, v) for k, v in resp.headers.items() if k.lower() not in excluded_headers]

        # 6. 将 NiFi 响应返回给前端
        return Response(resp.content, resp.status_code, response_headers)


# -------------------- Flask 应用与路由注册 --------------------
app = Flask(__name__)
# Blueprint 路由前缀
bp = Blueprint("console", __name__, url_prefix="/console/api")
api = Api(bp)

# 注册 NiFi 代理接口,同时支持根路径和多级路径 给 <path:path> 提供默认值
api.add_resource(NifiProxyApi, "/nifi-api/","/nifi-api/<path:path>")
# 注册 Blueprint
app.register_blueprint(bp)

# -------------------- 主入口 --------------------
if __name__ == "__main__":
    # 监听 8000 端口,可自行修改
    app.run(host="0.0.0.0", port=8000, debug=True)

1

python 复制代码
server {
    listen 80;
    
    location /nifi-api {
        proxy_pass http://192.168.208.131:8000/console/api/nifi-api;
        autoindex off;
    
        proxy_set_header Host $host:$server_port;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        
        proxy_buffering off;
        proxy_cache off;
    }
    
    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}
相关推荐
锋行天下14 小时前
让nginx网关扛下所有攻击
前端·后端·nginx
代码熬夜敲Q15 小时前
Nginx相关
运维·服务器·nginx
念何架构之路16 小时前
接入层Nginx
运维·nginx
隔窗听雨眠1 天前
Nginx网关响应慢排查手记
java·服务器·nginx
難釋懷1 天前
Nginx自签名-图形化工具 XCA
运维·nginx
songjxin1 天前
Nginx 日志分析可视化面板
运维·nginx
qq_312920112 天前
如何将Nginx响应时间从500ms降至50ms
运维·nginx
linmengmeng_13142 天前
【总结】Docker 容器重建后 Nginx 502 问题排查与解决
nginx·docker·容器
難釋懷2 天前
Nginx-Https证书配置
运维·nginx·https