天天看點

用docker搭建selenium grid分布式環境實踐之路

用docker搭建selenium grid分布式環境實踐之路

最近需要測試zoom視訊會議,同時模拟100個人加入會議。經過了解,zoom提供了直接通過url連結加入會議的方式(隻能通過chrome浏覽器或者FireFox浏覽器,因為用的協定是webrtc)。

順着這個思路考慮可以通過Selenium自動化,同時啟動多個浏覽器程序,每個程序代表一個視訊會議使用者,達到模拟多方會議的效果。不過有以下兩個難點:

需要多個chrome浏覽器程序同時存活,在電腦上啟動一個chrome浏覽器程序差不多要消耗220M左右。

視訊會議的音頻和視訊源的問題。

針對視訊會議的音頻和視訊源的問題,chrome浏覽器有比較好的支援,在Selenium腳本中初始化Chrome浏覽器的參數中,隻需要加入如下配置:

chrome_options.add_argument("--use-fake-ui-for-media-stream")

chrome_options.add_argument("--use-fake-device-for-media-stream")

就能在加入視訊會議之後,使用虛拟的視訊和音頻。不過有個問題需要考慮,這個虛拟視訊和真實的視訊會議中的視訊品質看上去是有差距的,會不會對測試結果造成影響,我們這裡暫時不讨論這個話題。

現在唯一比較頭疼的是怎麼實作100個chrome浏覽器程序,可能你會覺得,這不就是資源問題嗎?加伺服器不就搞定了?!但是假如有了伺服器資源之後,怎麼做任務排程呢?好在有Selenium Grid,它是Selenium的三大元件,專門用來執行分布式測試。

于是基于Selenium Grid設計了個測試方案:

将某台伺服器作為Hub,也就是master

将剩下的機器作為node,注冊到hub機器。

本地采用多程序執行Selenium自動化腳本(我使用python語言實作的)。

按照上面的設計思路,理論上是能夠模拟出100人同時加入會議的。接下來我們就正式開始用docker搭建Selenium Grid分布式環境的探索之路。

selenium jar包直接啟動節點

其實,最開始我是直接使用jar包啟動節點的,起幾個節點還能接受,但是節點多了之後會特别麻煩,比如:想重新開機下節點,則需要手動全部kill掉,然後再一個個啟動。

隻要是手動重複的工作,就能腳本化。于是我寫了兩個shell腳本,一個腳本是根據傳參啟動對應數量的節點;另一個腳本是将所有的節點程序全部kill掉。主要腳本如下圖所示:

雖然用腳本也能輕松的執行,但還是不友善。首先啟動節點後,會增加好多java程序,并且沒辦法檢視單個節點的日志,因為所有節點的日志都同時在控制台列印。于是考慮用docker來管理Selenium grid節點。

用docker指令直接啟動

在github上有現成的鏡像: 

https://github.com/SeleniumHQ/docker-selenium

 。然後說明文檔中也列出了所有可用的鏡像名稱,因為我主要使用chrome浏覽器,所有安裝了: selenium/hub 、 selenium/node-chrome、 selenium/node-chrome-debug 三個鏡像,其中selenium/node-chrome-debug鏡像會啟動一個VNC Server,在腳本執行過程中,本地可以連上VNC Server,通過界面檢視伺服器的腳本執行情況。 使用指令:

$ docker pull selenium/hub

$ docker pull selenium/node-chrome

$ docker pull selenium/node-chrome-debug

啟動hub的指令如下:

$ docker run -d -p 4444:4444 -e GRID_MAX_SESSION=100 --name hub selenium/hub

啟動本地節點(hub和node在一台機器上)的指令如下:

$ docker run -d -p 5555:5555 -e NODE_MAX_INSTANCES=5 -e NODE_MAX_SESSION=5 --shm-size=2g --link hub:hub --name node1 selenium/node-chrome

啟動遠端節點(hub和node不在一台機器上)的指令如下:

$ docker run -d -p port:5555 -e HUB_HOST=remote_ip -e HUB_PORT=remote_port -e REMOTE_HOST=

http://ip:port

-e NODE_MAX_INSTANCES=5 -e NODE_MAX_SESSION=5 --shm-size=2g --name node1 selenium/node-chrome

這裡需要注意,網上很多教程提供的啟動指令都是hub和node在一台機器上,假如需要hub和node在不同的機器上,按照網上的教程,雖然啟動不會報錯,但是節點和hub之間的網絡是不通的。

不過直接使用docker指令雖然可以單獨檢視單個節點的日志,但是卻和使用jar包的方式面對一樣的問題:啟動多個節點,非常不友善,需要手動執行多次指令。有沒有更好的方案呢?當然有,可以使用docker-compose對docker容器進行整合。

docker-compose 啟動

docker compose是docker的一個指令行工具,用來定義和運作多個容器組成的應用。相當于我們可以将多個docker指令放到一個檔案裡,然後由docker-compose一鍵執行。

同樣的,也需要分兩種情況:

Hub和node在一台機器上

可以使用如下的配置檔案docker-compose.yml

version: "3"

services:

selenium-hub:

image: selenium/hub
container_name: selenium-hub
ports:
  - "4444:4444"
environment:
  - GRID_MAX_SESSION=50
  - GRID_TIMEOUT=900
  - START_XVFB=false           

chrome:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
depends_on:
  - selenium-hub
environment:
  - HUB_HOST=selenium-hub
  - HUB_PORT=4444
  - NODE_MAX_INSTANCES=5
  - NODE_MAX_SESSION=5           

然後在控制台執行指令:

$ docker-compose up -d //-d表示在背景運作

如果想同時啟動多個節點該怎麼辦呢?非常簡單:

$ docker-compose up -d --scale chrome=num //num是要啟動節點的數量

如果想關閉節點,可以執行如下指令:

$ docker-compose down

Hub和node不在一台機器上

可以使用如下配置檔案docker-compose.yml

# selenium-chrome-1

selenium-chrome-node-1:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
ports:
  - "5556:5555"
restart: always
stdin_open: true
environment:
  HUB_HOST: hub_ip
  HUB_PORT: 4444
  NODE_MAX_INSTANCES: 5
  NODE_MAX_SESSION: 5
  REMOTE_HOST: http://節點ip:5556
  GRID_TIMEOUT: 60000
shm_size: "2gb"           

# selenium-chrome-2

selenium-chrome-node-2:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
ports:
  - "5555:5555"
restart: always
stdin_open: true
container_name: node1
environment:
  HUB_HOST: hub_ip
  HUB_PORT: 4444
  NODE_MAX_INSTANCES: 5
  NODE_MAX_SESSION: 5
  REMOTE_HOST: http://節點ip:5555
  GRID_TIMEOUT: 60000
shm_size: "2gb"           

# selenium-chrome-3

selenium-chrome-node-3:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
ports:
  - "5557:5555"
restart: always
stdin_open: true
environment:
  HUB_HOST: hub_ip
  HUB_PORT: 4444
  NODE_MAX_INSTANCES: 5
  NODE_MAX_SESSION: 5
  REMOTE_HOST: http://節點ip:5557
  GRID_TIMEOUT: 60000
shm_size: "2gb"           

# selenium-chrome-4

selenium-chrome-node-4:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
ports:
  - "5558:5555"
restart: always
stdin_open: true
environment:
  HUB_HOST: hub_ip
  HUB_PORT: 4444
  NODE_MAX_INSTANCES: 5
  NODE_MAX_SESSION: 5
  REMOTE_HOST: http://節點ip:5558
  GRID_TIMEOUT: 60000
shm_size: "2gb"
           

# selenium-chrome-5

selenium-chrome-node-5:

image: selenium/node-chrome
volumes:
  - /dev/shm:/dev/shm
ports:
  - "5559:5555"
restart: always
stdin_open: true
environment:
  HUB_HOST: hub_ip
  HUB_PORT: 4444
  NODE_MAX_INSTANCES: 5
  NODE_MAX_SESSION: 5
  REMOTE_HOST: http://節點ip:5559
  GRID_TIMEOUT: 60000
shm_size: "2gb"           

啟動節點的指令是(前提是hub需要提前啟動):

$ docker-compose up -d

關閉節點的指令是:

遺留問題

按照我上面這種方式搭建Selenium Grid環境,本地節點可以正常執行,但是遠端的節點卻經常逾時,不過從

http://hub_ip:4444/grid/console

界面上看到的節點網絡全部都是通的。

之前查過一些資料,貌似需要使用Docker Swarm,它是一個docker叢集管理工具, 将若幹台 Docker 主機抽象為一個整體,并且通過一個入口統一管理這些 Docker 主機上的各種 Docker 資源 。不過目前還沒研究它,後面如果用Docker Swarm有結論之後,我再寫文章同步給大家。

總結

用docker搭建selenium grid分布式環境,非常友善,基本是一行指令就能啟動或者關閉節點。希望我這篇文章能給大家提供一些思路,幫助大家在平時的工作中解決一些問題。

還是那句話,任何技術,隻要能幫你解決實際的問題,就是好的技術!

原文位址

https://www.cnblogs.com/zhouliweiblog/p/12572047.html