我有一个Chrome容器(使用this Dockerfile部署),可以根据请求从App容器呈现页面。
基本流程是:
ws://chrome.example.com:9222/devtools/browser/13400ef6-648b-4618-8e4c-b5c73db2a122
)puppeteer.connect({ browserWSEndpoint: webSocketUrl })
连接到Chrome实例并与之通信; 对于单个Chrome容器,这非常有效。
但我正在尝试扩展以在Docker群中拥有多个Chrome容器。
问题是,我认为,App收到的websocket url特定于在该特定Chrome容器中运行的实例,因此当App使用它时(现在有多个Chrome容器),websocket请求来自App不一定会被路由到正确的Chrome容器。
处理此问题的最佳方法是什么?
答案 0 :(得分:12)
你的基本设计是正确的,但你遇到的问题是会话“粘性”。但是,我们不应该尝试将后续请求重新路由回适当的计算机,而应该寻找一种方法来避免" pre"请求。
这样做的最佳方法是让您的Chrome泊坞窗图片为中间人提供所有http“升级”请求。这个http动作是所有WebSocket连接在更改协议之前发出的,包括puppeteer库(它只是一个引擎盖下的WebSocket客户端)。这样做还可以避免需要进行预连接调用,因为在升级时会发生代理到Chrome,而是暴露应用程序使用的URL。这是使用http-proxy模块执行此操作的一个非常基本的示例:
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = new httpProxy.createProxyServer();
http
.createServer()
.on('upgrade', async(req, socket, head) => {
const browser = await puppeteer.launch();
const target = browser.wsEndpoint();
proxyy.ws(req, socket, head, { target })
})
.listen(3000);
这种方法还有其他好处:您可以限制并发甚至注入脚本以便稍后运行。那些需要更多一点和准备,但总体思路保持不变。这也使得负载平衡变得微不足道,因为不需要使路由变得粘滞。
如果您对实施所有工作感兴趣,那么主要是在browserless回购中为您完成的。它甚至允许诸如并发限制,会话时间限制和includes a feature-rich IDE之类的事情。您可以找到更多docs on that project here。