如何在多台服务器上扩展Selenoid集群?
问题描述
我有三台服务器,计划在其中两台部署Selenoid,从第三台服务器调用这个集群。目前我用以下代码随机指定服务器:
if randint(0, 1) == 1: host = "HOST_1" else: host = "HOST_2"
请问在webdriver.Remote / Selenoid中,有没有更优的指定最优服务器的方案?
当前调用代码如下:
from selenium import webdriver from selenium.webdriver.chrome.options import Options as ChromeOptions from selenium.webdriver.firefox.options import Options as FirefoxOptions from random import randint def get_chrome(): options = ChromeOptions() options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') options.add_argument('--headless') options.set_capability("browserName", "chrome") options.set_capability("browserVersion", "80.0_VNC") options.set_capability("selenoid:options", { "enableVNC": True, "enableVideo": True }) if randint(0, 1) == 1: host = "HOST_1" else: host = "HOST_2" driver = webdriver.Remote(command_executor='http://{}:4444/wd/hub'.format(host), options=options) return driver
我当前的Selenoid基础设施配置(docker-compose):
version: '3' services: selenoid: image: "aerokube/selenoid" network_mode: bridge restart: always shm_size: 2g ports: - "4444:4444" volumes: - "$PWD:/etc/selenoid/" # 假设当前目录包含browsers.json - "/var/run/docker.sock:/var/run/docker.sock" command: ["-limit", "12"] # 限制并行会话总数为12 selenoid-ui: image: "aerokube/selenoid-ui" network_mode: bridge restart: always links: - selenoid ports: - "8080:8080" command: ["--selenoid-uri", "http://selenoid:4444"]
最优方案推荐
1. 使用Selenoid自带集群负载均衡(推荐)
Selenoid原生支持集群模式,你可以在第三台服务器部署Selenoid Hub,让它作为统一入口管理两台Selenoid节点,自动实现负载均衡。
配置步骤:
在第三台服务器部署Selenoid Hub:
创建与节点一致的browsers.json文件,然后用Docker启动Hub:version: '3' services: selenoid-hub: image: "aerokube/selenoid:latest" network_mode: bridge restart: always ports: - "4444:4444" volumes: - "$PWD:/etc/selenoid/" command: ["-hub", "-nodes", "http://HOST_1:4444,http://HOST_2:4444"]其中
-nodes参数指定两台Selenoid节点的地址。修改调用代码:
无需再随机选择节点,直接将command_executor指向Hub地址即可:def get_chrome(): # 保持原有options配置不变 driver = webdriver.Remote(command_executor='http://HUB_HOST:4444/wd/hub', options=options) return driverHub会自动根据节点的空闲会话数分配请求,比随机选择更高效合理。
2. 基于节点负载动态选择
如果不想部署Hub,可以通过Selenoid的状态API获取节点负载,主动选择空闲会话最多的节点。
实现思路:
- 调用Selenoid节点的
/status接口,获取当前已用会话数和总限制数 - 计算每个节点的空闲会话数,选择空闲量最大的节点
- 若节点不可用则自动跳过,最后 fallback 到随机选择
修改后的代码示例:
import requests from selenium import webdriver from selenium.webdriver.chrome.options import Options as ChromeOptions from random import randint def get_best_selenoid_host(hosts): best_host = None max_free = -1 for host in hosts: try: resp = requests.get(f"http://{host}:4444/status", timeout=2) if resp.status_code == 200: status = resp.json() used = status.get("sessions", 0) total = status.get("limit", 12) free = total - used if free > max_free: max_free = free best_host = host except Exception: # 节点不可用时跳过 continue return best_host or hosts[randint(0, len(hosts)-1)] def get_chrome(): options = ChromeOptions() # 保持原有options配置不变 hosts = ["HOST_1", "HOST_2"] host = get_best_selenoid_host(hosts) driver = webdriver.Remote(command_executor=f'http://{host}:4444/wd/hub', options=options) return driver
3. 用Nginx反向代理做负载均衡
在第三台服务器部署Nginx,配置反向代理和负载均衡规则,将请求转发到两台Selenoid节点。
Nginx配置示例:
http { upstream selenoid_cluster { server HOST_1:4444; server HOST_2:4444; # 采用最少连接数策略,比默认轮询更优 least_conn; } server { listen 4444; location / { proxy_pass http://selenoid_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } }
修改调用代码:
直接将command_executor指向Nginx服务器地址即可:
driver = webdriver.Remote(command_executor='http://NGINX_HOST:4444/wd/hub', options=options)
Nginx的least_conn策略会自动把请求分配到当前连接数最少的节点,实现智能负载均衡。
内容的提问来源于stack exchange,提问作者mascai
相关产品推荐
相关产品推荐

