目录结构
.
├── docker-compose.yaml
├── nginx
│ └── nginx.conf
└── script
├── run.sh
└── splash_listener.py
docker-compose.yaml
version: "3"
services:
nginx:
image: nginx
container_name: splash_nginx
restart: always
ports:
- 8050:80
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- splash1
- splash2
listener:
image: python:3.8
hostname: listener
volumes:
- ./script:/app
command: bash /app/run.sh
depends_on:
- splash1
- splash2
splash1:
hostname: splash1
container_name: splash_1
image: scrapinghub/splash
restart: always
splash2:
hostname: splash2
container_name: splash_2
image: scrapinghub/splash
restart: always
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
client_max_body_size 10m;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
upstream tomcat_client {
server splash1:8050 weight=1;
server splash2:8050 weight=1;
}
server {
server_name "";
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
location / {
proxy_pass http://tomcat_client;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
splash_listener.py
# -*- coding:utf-8 -*-
# @Author: wmy
# @Time: 2020/7/3
# @Description:
import sys
import subprocess
import requests
import logging
class Listener(object):
def __init__(self):
self.splash_timeout = 10
self.splash_ping_times = 2
self.logger = self.get_logger()
self.splash_servers = [
{
'host': 'splash1',
'port': '8050',
'name': 'splash_1',
},
{
'host': 'splash2',
'port': '8050',
'name': 'splash_2',
},
]
def get_logger(self, name='splash_listener', level=logging.INFO):
"""
获得一个logger
:param name:
:param level:
:return:
"""
logger = logging.getLogger(name)
logger.setLevel(level)
stream_handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s: - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
return logger
def ping_splash(self, splash_host, splash_port):
"""
尝试连接splash,测试splash服务是否正常
:return: 正常,True,无法访问,False
"""
splash_url = 'http://{}:{}'.format(splash_host, splash_port)
try:
resp = requests.get(splash_url, timeout=self.splash_timeout)
except Exception as e:
self.logger.error(u'请求出错.{}'.format(e))
return False
if resp.status_code != 200:
self.logger.error(u'状态码异常.{}'.format(resp.status_code))
return False
return True
def listen_splash(self):
"""
监听splash,尝试连接splash,直到成功或者失败self.splash_ping_times次。
:return: 成功,True,失败,False
"""
for splash in self.splash_servers:
mark = False
# check splash
for i in range(self.splash_ping_times):
if self.ping_splash(splash['host'], splash['port']):
mark = False
else:
mark = True
if mark:
# restart splash
subprocess.Popen(args=['docker', 'restart', splash['name']])
self.logger.error(u'{} splash服务异常,重启服务'.format(splash['name']))
else:
self.logger.info(u'{} splash服务正常'.format(splash['name']))
if __name__ == '__main__':
import time
while True:
Listener().listen_splash()
time.sleep(60*5)
run.sh
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
python /app/splash_listener.py