You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask与Bokeh Server共享端口部署:可行性及实现方案问询

Flask + Bokeh Server 共享8080端口部署方案

当然可行!完全不用让Flask和Bokeh Server各占独立端口,通过反向代理的思路就能让它们共享8080端口,完美适配管控严格的服务器环境。下面给你拆解具体的实现条件和步骤:

核心实现思路

让Flask作为对外的唯一入口(监听8080端口),内部把Bokeh相关的请求转发给本地运行的Bokeh Server(绑定localhost的非公开端口,比如5006)。这样外部只能访问8080端口,符合服务器的管控要求。

必须满足的条件

  • 依赖安装:服务器需要安装flask、requests、gevent、gevent-websocket和bokeh这些Python包,用来支持Flask的代理功能和WebSocket转发(Bokeh实时交互依赖WebSocket)。
  • Bokeh Server配置:必须让Bokeh Server只监听localhost(避免直接对外暴露),同时指定允许WebSocket连接的源为Flask的公开域名/端口,否则Bokeh的实时交互会失败。
  • Flask服务器选型:不能用Flask默认的Werkzeug服务器,必须用支持WebSocket的服务器(比如gevent的WSGIServer),因为要转发Bokeh的WebSocket请求。

具体实现步骤

1. 配置并启动Bokeh Server

在服务器上启动Bokeh Server时,加上这些关键参数:

bokeh serve --allow-websocket-origin=your-public-domain.com:8080 --port=5006 --host=localhost:5006 your_bokeh_app.py
  • --allow-websocket-origin:指定允许连接Bokeh WebSocket的源,必须是Flask对外的域名+端口(比如你的服务器域名是example.com,就填example.com:8080)。
  • --host=localhost:5006:让Bokeh Server只监听本地请求,外部无法直接访问5006端口。

2. 编写Flask代理代码

创建Flask应用,把/bokeh和/ws开头的请求转发给内部的Bokeh Server:

from flask import Flask, request, Response
import requests
from werkzeug.middleware.proxy_fix import ProxyFix
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket import create_connection
from urllib.parse import urljoin

app = Flask(__name__)
# 处理代理头,确保Bokeh能正确识别请求来源
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)

# 内部Bokeh Server的地址
BOKEH_SERVER_URL = "http://localhost:5006"

# 转发普通HTTP请求(比如Bokeh的静态资源、页面)
@app.route('/bokeh/<path:path>', methods=['GET', 'POST'])
def proxy_bokeh_http(path):
    target_url = f"{BOKEH_SERVER_URL}/bokeh/{path}"
    # 转发请求参数和头信息
    if request.method == 'GET':
        resp = requests.get(target_url, params=request.args, headers=request.headers)
    elif request.method == 'POST':
        resp = requests.post(target_url, data=request.form, headers=request.headers)
    # 返回Bokeh的响应内容
    return Response(resp.content, status=resp.status_code, headers=dict(resp.headers))

# 转发WebSocket请求(Bokeh实时交互的核心)
@app.route('/ws/<path:path>')
def proxy_bokeh_ws(path):
    client_ws = request.environ.get('wsgi.websocket')
    if not client_ws:
        return Response('Expected WebSocket request', status=400)
    
    # 转换为WebSocket协议的地址
    server_ws_url = urljoin(BOKEH_SERVER_URL.replace('http', 'ws'), f'/ws/{path}')
    server_ws = create_connection(server_ws_url)

    # 双向转发WebSocket消息
    def forward(from_ws, to_ws):
        while True:
            msg = from_ws.receive()
            if msg is None:
                break
            to_ws.send(msg)
    
    from gevent import spawn
    spawn(forward, client_ws, server_ws)
    spawn(forward, server_ws, client_ws)
    
    return ''

# 你的其他Flask路由可以写在这里
@app.route('/')
def home():
    return "Hello from Flask! <a href='/bokeh/your_bokeh_app'>View Bokeh App</a>"

if __name__ == '__main__':
    # 用gevent启动支持WebSocket的Flask服务器,监听8080端口
    server = pywsgi.WSGIServer(('0.0.0.0', 8080), app, handler_class=WebSocketHandler)
    server.serve_forever()

3. 验证部署

启动Flask应用后,外部访问http://your-public-domain.com:8080就能看到Flask的主页,点击链接就能访问嵌入的Bokeh应用,所有请求都通过8080端口转发,5006端口完全对外不可见。

额外注意事项

  • 服务器防火墙只需开放8080端口,5006端口保持关闭(因为只监听localhost),进一步提升安全性。
  • 如果你的服务器有Nginx等反向代理层,也可以让Nginx直接把Bokeh请求转发给内部的Bokeh Server,Flask和Nginx共享8080端口,但上面的方案是纯Python实现,不需要额外的Web服务器。

内容的提问来源于stack exchange,提问作者Russell Burdt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:10:09