STF 正式环境 docker 化集群部署

在本地开发STF,需依次安装Node.js,ADB ,RethinkDB,GraphicsMagick,ZeroMQ ,Protocol Buffers,yasm, pkg-config环境,如果部署到生产环境,每增加一台机器节点,都安装这些环境,那将是一个非常痛苦的过程。STF官方也推荐使用docker来搭建STF环境,服务器只需要安装docker,然后依次拉取以下镜像:
docker pull openstf/stf:latest
docker pull sorccu/adb:latest
docker pull rethinkdb:latest
docker pull openstf/ambassador:latest
docker pull nginx:latest
openstf/stf是stf的主镜像,sorccu/adb是adb工具,如果本地服务器已经有adb环境,可以不要此镜像,rethinkdb是stf数据库镜像,openstf/ambassador为网络代理工具,nginx是一个web服务器反向代理工具, stf依赖它将不同的url转发到不同模块上,没有nginx,生产环境中的stf是肯定不能正常工作的。拉取这些镜像以后,stf就可以直接在容器中运行了,不需要再安装stf的相关工具,openstf/stf镜像已经包含了所依赖的环境。
如果基于stf做了二次定制,要在服务器上进行docker部署,可不是一个stf local命令就开始使用了,需要以下步骤:
1.发布镜像
openstf/stf是STF官方push到docker官方仓库的镜像,如果进行了二次开发,理论上只需要替换该镜像即可。制作镜像首先需要DockerFile,在源码的根目录下,已经提供了现成的DockerFile,直接基于该File制作镜像,在DockerFile目录下,执行
sudo docker build -t dystf/stf:latest .
其中dystf/stf为镜像名称,latest为镜像版本。网速好的情况下,10分钟内可以制作好,网速不好的情况下,半个小时以上甚至失败都是有可能的,这个时候需要不断地重试,执行完后,执行sudo doker images可查看刚制作好的镜像:

如果新发布的镜像有问题,可以快速恢复到上个版本。每次修改代码以后,基于主服务器重新制定新的镜像,可将该镜像保存,然后可以分发到其他服务器上,其他服务器不需要再重新制定,方便快捷,sudo docker save 镜像ID> dystf_image.tar

2.集群化部署
如果只有10-15个设备的数据量,只需要一台服务器节点,直接启动stf local命令就可以了。当然实际生产环境中,绝对提供不止十几台的数量,有可能达到上百台,上百台的话,至少需要 10台服务器节点,一台服务器节点一般10台手机。所以只有通过集群部署来解决该问题,而且能够达到快速扩展新节点目的。
STF包含多个独立运行的进程,这些进程之间通过ZeroMQ和Protocol Buffers通信,每个进程节点叫做“unit”,这些单元可以分别部署到不同的服务器上,通过nigix配置来转发,详情可以看官方文档介绍。在我们的远程真机部署环境中,选了一台性能较好的服务器作为主节点,该服务器不连任何设备,provider节点作为设备的提供agent,它将设备上报给主服务器,并展示,如图:

主服务器节点部署以下单元模块:
rethinkdb.service
nginx.service
stf-app@.service
stf-auth@.service
stf-migrate.service
stf-processor@.service
stf-reaper.service
stf-storage-plugin-apk@.service
stf-storage-plugin-image@.service
stf-storage-temp@.service
stf-triproxy-app.service
stf-triproxy-dev.service
stf-websocket@.service
stf-api@.service

provider服务器节点部署以下单元模块:
adbd.service/adb环境
stf-provider@.service
stf-provider的作用就是给主框架提供手机,provider可以运行在同一台机器,也可以运行在其他机器,但是,这台机器一定要可直接访问的,因为手机屏幕其实就是从这里出来的。在provider机器上一定要先由adb的环境,毕竟安卓手机要依赖adb调试。

3.发布运行
主节点的启动运行:
基于第一步已经制作好的镜像,可执行以下shell命令进行容器的启动,$1参数为镜像名字和版本,如:dystf/stf:3.0, $2参数为主服务器ip
#停止所有正在运行的容器
sudo docker stop $(sudo docker ps -a -q)
sleep 3
#删除所有的容器
sudo docker rm -v $(sudo docker ps -a -q)
sleep 3
#启动nignx容器
sudo docker run -d –name nginx –net host -v /home/mtp/stf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro nginx:latest nginx
sleep 3
#启动rethinkdb
sudo docker run -d –name rethinkdb -v /srv/rethinkdb:/data –net host rethinkdb:2.3 rethinkdb –bind all –cache-size 8192 –http-port 8090 –no-update-check
sleep 3
#启动stf-migrate 初始化数据库表
sudo docker run -d –name stf-migrate $1 stf migrate
sleep 3
#start stf-app
sudo docker run -d –name stf-app –net host -e “SECRET=YOUR_SESSION_SECRET_HERE” $1 stf app –port 3100 –auth-url http://$2/auth/mock/ –websocket-url ws://$2/
sleep 3
#start stf-auth
sudo docker run -d –name stf-auth –net host -e “SECRET=YOUR_SESSION_SECRET_HERE” $1 stf auth-mock –port 3200 –app-url http://$2/
sleep 3
#start websocket
sudo docker run -d –name websocket –net host -e “SECRET=YOUR_SESSION_SECRET_HERE” $1 stf websocket –port 3600 –storage-url http://$2/ –connect-sub tcp://$2:7150 –connect-push tcp://$2:7170
sleep 3
#start stf-api
sudo docker run -d –name stf-api –net host -e “SECRET=YOUR_SESSION_SECRET_HERE” $1 stf api –port 3700 –connect-sub tcp://$2:7150 –connect-push tcp://$2:7170
sleep 3
#start storage-apk
sudo docker run -d –name storage-apk –net host $1 stf storage-plugin-apk –port 3300 –storage-url http://$2/
sleep 3
#start storage-images
sudo docker run -d –name storage-image –net host $1 stf storage-plugin-image –port 3400 –storage-url http://$2/
sleep 3
#start storage-temp
sudo docker run -d –name storage-temp –net host -v /mnt/storage:/data $1 stf storage-temp –port 3500 –save-dir /data
sleep 3
#start triproxy-app
sudo docker run -d –name triproxy-app –net host $1 stf triproxy app –bind-pub “tcp://:7150″ –bind-dealer “tcp://:7160″ –bind-pull “tcp://:7170″
sleep 3
#start stf-processer
sudo docker run -d –name stf-processer –net host $1 stf processor stf-processer –connect-app-dealer tcp://$2:7160 –connect-dev-dealer tcp://$2:7260
sleep 3
#start triproxy-dev
sudo docker run -d –name triproxy-dev –net host $1 stf triproxy dev –bind-pub “tcp://
:7250″ –bind-dealer “tcp://:7260″ –bind-pull “tcp://:7270″
sleep 3
#start stf-reaper
sudo docker run -d –name stf-reaper –net host $1 stf reaper dev –connect-push tcp://$2:7270 –connect-sub tcp://$2:7150 –heartbeat-timeout 30000
启动完成后可通过sudo docker ps -a 查看正在运行的容器:

provider节点的运行:
以镜像 dystf/stf:latest,主节点10.118.97.X,provider节点10.118.97.Y为例子,该服务器节点已安装adb环境,所以不需要启动adbd.service容器:
sudo docker run -d –name provider-34 –net host dystf/stf:latest stf provider –name “provider-34” –connect-sub tcp://10.118.97.X:7250 –connect-push tcp://10.118.97.X:7270 –storage-url http://10.118.97.X –public-ip 10.118.97.Y –min-port=15000 –max-port=25000 –heartbeat-interval 20000 –screen-ws-url-pattern “ws://10.118.97.X/d/agentX/<%= serial %>/<%= publicPort %>/”
通过sudo docker ps -a查看结果:

4.添加新provider节点
添加新的设备,需要增加新的服务器节点,新的节点只需几分钟便可接入完成:
第一步:安装docker环境,adb环境。
第二部:导入镜像,在上面第一步中,将主服务器已经发布好的镜像dystf_image.tar scp 到该服务器上,然后导入该镜像:
sudo docker load < /Users/mtp/dystf_image.tar
刚导入的镜像没有名字和版本,需要对其打标,dystf/stf:latest为打标的名字和版本
sudo docker tag $(sudo docker images –filter “dangling=true” -q) dystf/stf:latest
第三部:启动stf-provider,如上命令。
第四部:配置nginx
在主服务器的nginx.conf文件下,添加刚启动的provider节点配置,添加:
location ~ “/d/新节点启动名称,如上例的agentX/([/]+)/(?[0-9]{5})/$” {
proxy_pass http://新节点IP2:$port/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
}
配置完成后,重启ngnix,新节点所连接的设备即可上报给主服务器。