与多个Chrome Docker容器进行Websocket通信 [英] Websocket communication with multiple Chrome Docker containers

查看:215
本文介绍了与多个Chrome Docker容器进行Websocket通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Chrome容器(使用此Dockerfile 部署)

I have a Chrome container (deployed using this Dockerfile) that renders pages on request from an App container.

基本流程是:


  • App向Chrome发送一个http请求,并作为响应收到要使用的websocket网址(例如 ws://chrome.example.com:9222 / devtools / browser / 13400ef6-648b-4618-8e4c- b5c73db2a122

  • 应用程序随后使用该websocket网址与Chrome进一步通信,并接收呈现的页面。我使用木偶库连接到Chrome实例并与之通信> puppeteer.connect({browserWSEndpoint:webSocketUrl});

  • App sends an http request to Chrome and in response receives a websocket url to use (e.g. ws://chrome.example.com:9222/devtools/browser/13400ef6-648b-4618-8e4c-b5c73db2a122)
  • App then uses that websocket url to communicate further with Chrome, and to receive the rendered page. I am using the puppeteer library to connect to and communicate with the Chrome instance, using puppeteer.connect({ browserWSEndpoint: webSocketUrl });

对于单个Chrome容器,这确实有效好。

For a single Chrome container this works really well.

但是我正在尝试扩大规模,以便在Docker群中具有多个Chrome容器。

But I'm trying to scale things up to have multiple Chrome containers in a Docker swarm.

我认为问题是,App接收到的websocket URL特定于在该特定Chrome容器中运行的实例,因此,当App使用它(并且现在有多个Chrome容器)时,来自App的websocket请求不会

The problem is, I think, that the websocket url received by App is specific to the instance running in that particular Chrome container, so when it is used by App (and where there are now multiple Chrome containers), the websocket requests from App will not necessarily be routed to the right Chrome container.

处理此问题的最佳方法是什么?

What is the best way of dealing with this?

推荐答案

您的基本设计正确,但是您遇到的问题是会话粘性。但是,与其尝试将后续请求重新路由回适当的计算机,不如寻找一种避免预请求的方法。

You’ve got the basic design correct, but the issue you’re experiencing is with session "stickiness". However, instead of trying to re-route subsequent requests back to the appropriate machine, we should look for a way to avoid the "pre" request.

这样做是让您的Chrome泊坞窗图片位于所有http升级请求的中间位置。此http动作是所有WebSocket连接在更改协议(包括puppeteer库,它只是一个WebSocket客户端)之前发出的内容。这样做还可以避免进行预连接呼叫,因为到Chrome的代理将发生在升级过程中,而不是公开要使用的URL。这是一个使用 http-proxy 模块执行此操作的基本示例:

The best way to do that is to have your Chrome docker image man-in-the-middle all http "upgrade" requests. This http action is what all WebSocket connections emit prior to changing protocols including the puppeteer library (which is just a WebSocket client under-the-hood). Doing this will also obviate the need for a pre-connect call since the proxying to Chrome will happen on upgrade vs exposing a URL for the app to use. Here's a pretty basic example of doing this with the http-proxy module:

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);

这种方法还有其他好处:您可以限制并发甚至注入脚本等操作。稍后运行。这些虽然需要更多和准备,但总体思路仍然相同。

There's other benefits with this approach as will: you can limit things like concurrency and even inject scripts to be ran at a later time. Those require a little more though and preparation, but the overall idea remains the same. This also makes load-balancing trivial since there's not need to make routing sticky.

如果这是您对实现所有工作都感兴趣的工作,那么在很大程度上,这是很麻烦的,因为不需要使路由变得棘手。 无浏览器回购。它甚至允许并发限制,会话时间限制以及包含功能丰富的IDE 之类的东西。您可以在此处找到有关该项目的更多文档。

If this is something you're interested in implementing all that works is largely done for you in the browserless repo. It even allows for things like concurrency limitations, session time limitations, and includes a feature-rich IDE. You can find more docs on that project here.

这篇关于与多个Chrome Docker容器进行Websocket通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆