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;
    }
}
相关推荐
2501_9157167210 小时前
Nginx网关讲解_小白版
运维·nginx
悦儿遥遥雨11 天前
PXE + Kickstart 无人值守批量部署系统
linux·javascript·nginx
大E帝国子民11 天前
OpenCloudOS Server 9 安装 Nginx 完整指南
前端·网络·nginx
weixin_307779132 天前
Linux下Nginx故障系统化检查Shell脚本
linux·运维·服务器·nginx·自动化
小南家的青蛙3 天前
使用Nginx中配置CRL
nginx·crl
从此以后自律3 天前
项目 Docker + Nginx 云端完整部署细节
nginx·docker·容器
donoot3 天前
一次 Nginx 502 问题的深度排查:从 SELinux 到容器网络
nginx·docker·selinux·反向代理·502 bad gateway
難釋懷4 天前
Nginx浏览器强制缓存
运维·nginx·缓存
ITKEY_4 天前
macOS brew 安装的nginx 文件在哪里?
运维·nginx·macos
Felix-lxd4 天前
Ubuntu 22.04 配置 Nginx
linux·nginx·ubuntu