Связь Websocket с несколькими контейнерами Chrome Docker

У меня есть контейнер Chrome (развернутый с использованием этого файла Docker), который отображает страницы по запросу из контейнера App.

Основной поток:

  • Приложение отправляет HTTP-запрос в Chrome и в ответ получает URL-адрес websocket для использования (например, ws://chrome.example.com:9222/devtools/browser/13400ef6-648b-4618-8e4c-b5c73db2a122)
  • Затем приложение использует этот URL-адрес websocket для связи с Chrome и получения отображаемой страницы. Я использую библиотеку кукловодов для подключения к экземпляру Chrome и общения с ним, используя puppeteer.connect({ browserWSEndpoint: webSocketUrl });

Для одного контейнера Chrome это работает очень хорошо.

Но я пытаюсь масштабировать все, чтобы иметь несколько контейнеров Chrome в рое Docker.

Проблема в том, что URL-адрес websocket, полученный приложением, специфичен для экземпляра, запущенного в этом конкретном контейнере Chrome, поэтому, когда он используется в приложении (и там, где сейчас имеется несколько контейнеров Chrome), запросы веб-приложений из приложения будут не обязательно направляться в подходящий контейнер Chrome.

Каков наилучший способ справиться с этим?

Ответ 1

У вас правильный дизайн, но проблема, с которой вы сталкиваетесь, связана с "липкостью" сеанса. Однако вместо того, чтобы повторно перенаправить последующие запросы обратно на соответствующий компьютер, мы должны искать способ избежать запроса "pre".

Лучший способ сделать это - сделать ваше изображение докеры Chrome "посередине" всеми запросами "обновления" HTTP. Это действие http - это то, что все соединения WebSocket испускают до изменения протоколов, включая библиотеку кукловодов (которая является просто клиентом 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);

Существуют и другие преимущества такого подхода: вы можете ограничить такие вещи, как параллелизм, и даже запустить сценарии, которые будут запущены позднее. Те требуют немного больше и подготовки, но общая идея остается прежней. Это также делает балансировку нагрузки тривиальной, поскольку нет необходимости делать маршрутизацию липкой.

Если это то, что вы заинтересованы в реализации всех этих работ, в основном делается для вас в режиме без браузера. Он даже позволяет такие вещи, как ограничения параллелизма, ограничения времени сеанса и включает многофункциональную среду IDE. Здесь вы можете найти больше документов по этому проекту.

Ответ 2

Я установил без браузера на моей локальной машине. Конфигурация машины - i5, 2,60 ГГц и 16 ГБ оперативной памяти.

Я написал сценарий кукловода. Теперь я хочу использовать его для нагрузочного тестирования без браузера. Не могли бы вы помочь мне определить соответствующее количество экземпляров браузера, которые я могу использовать на одном компьютере.