如何在同一EC2实例运行Splash服务与Scrapy爬虫?求最佳实践
在EC2实例上部署Scrapy+Splash多进程应用的最佳实践
很高兴能帮到你!在单个EC2实例上同时运行Scrapy爬虫和Splash服务其实有几种成熟的方案,下面我会一步步讲解具体实现和最佳实践,帮你稳定部署应用:
一、前置准备
首先得把基础环境搭好:
- 在EC2实例上安装Docker(如果用容器方案)和Python环境(如果直接跑Scrapy),常规Linux安装流程即可。
- 配置EC2安全组:开放Splash默认的8050端口,但仅限EC2本机访问(来源设置为实例私有IP或
127.0.0.1/32),不要对外公开;同时确保实例能访问目标爬取网站(出站规则放开HTTP/HTTPS)。 - 把你的Scrapy项目传到EC2实例,比如用
scp命令或者Git克隆。
二、多进程运行方案(按推荐程度排序)
方案1:用Docker Compose统一管理(最推荐,生产环境友好)
Docker Compose可以把Splash和Scrapy两个服务定义在一个配置文件里,一键启动、管理,还能自动处理依赖关系。
- 安装Docker Compose:
sudo apt-get update && sudo apt-get install docker-compose -y # 以Ubuntu为例
- 在Scrapy项目根目录下创建
docker-compose.yml文件:
version: '3' services: # Splash服务配置 splash: image: scrapinghub/splash ports: - "127.0.0.1:8050:8050" # 只绑定本机IP,避免外部访问 restart: always # 容器意外退出自动重启 mem_limit: 2g # 根据实例配置限制内存,避免Splash占满资源 # Scrapy爬虫服务配置 scrapy-spider: build: . # 基于当前目录的Dockerfile构建镜像 depends_on: - splash # 确保Splash启动后再启动爬虫 restart: on-failure # 爬虫失败时自动重启,可根据需求调整为always volumes: - ./scrapy-output:/app/output # 挂载本地目录保存爬取结果,避免容器重启丢失数据 environment: - SPLASH_URL=http://splash:8050 # 告诉Scrapy连接Splash的Docker内部域名
- 在Scrapy项目根目录创建
Dockerfile:
# 基于轻量Python镜像构建 FROM python:3.10-slim # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制整个Scrapy项目 COPY . . # 启动爬虫的命令 CMD ["scrapy", "crawl", "your_spider_name"] # 替换成你的爬虫名称
- 启动服务:
docker-compose up -d # -d参数让服务后台运行
- 查看日志或管理服务:
# 查看所有服务日志 docker-compose logs -f # 重启单个服务 docker-compose restart scrapy-spider # 停止所有服务 docker-compose down
方案2:用Systemd托管服务(适合不想用容器跑Scrapy的场景)
如果希望Scrapy直接运行在EC2主机上,用Systemd可以实现服务的自动启动、重启和状态监控。
- 创建Splash的Systemd服务文件:
/etc/systemd/system/splash.service
[Unit] Description=Splash JavaScript Rendering Service After=network.target [Service] ExecStart=/usr/bin/docker run -p 127.0.0.1:8050:8050 scrapinghub/splash Restart=always # 意外退出自动重启 User=ubuntu # 替换成你的EC2用户名(比如ubuntu/ec2-user) TimeoutStopSec=30 [Install] WantedBy=multi-user.target
- 创建Scrapy爬虫的Systemd服务文件:
/etc/systemd/system/scrapy-spider.service
[Unit] Description=Scrapy Web Crawler Service After=splash.service # 依赖Splash服务,确保先启动Splash Requires=splash.service [Service] WorkingDirectory=/home/ubuntu/your-scrapy-project # 替换成你的Scrapy项目目录 ExecStart=/usr/bin/scrapy crawl your_spider_name # 替换成你的爬虫名称 Restart=on-failure # 爬虫失败时重启,按需调整 User=ubuntu # 日志输出到文件,方便排查问题 StandardOutput=append:/var/log/scrapy-spider.log StandardError=append:/var/log/scrapy-spider.log [Install] WantedBy=multi-user.target
- 启用并启动服务:
# 重新加载Systemd配置 sudo systemctl daemon-reload # 设置开机自启并启动Splash sudo systemctl enable splash.service sudo systemctl start splash.service # 设置开机自启并启动Scrapy爬虫 sudo systemctl enable scrapy-spider.service sudo systemctl start scrapy-spider.service
- 查看服务状态或日志:
# 查看爬虫服务状态 sudo systemctl status scrapy-spider.service # 查看日志 journalctl -u scrapy-spider.service -f
方案3:手动后台运行(仅适合测试,不推荐生产)
如果只是临时测试,可以直接把两个进程放到后台运行:
- 启动Splash后台容器:
docker run -d -p 127.0.0.1:8050:8050 scrapinghub/splash
- 后台运行Scrapy爬虫:
# 用nohup让进程在SSH断开后继续运行 nohup scrapy crawl your_spider_name > scrapy_logs.out 2>&1 &
这种方式的缺点是进程意外退出后不会自动重启,也没有统一的管理方式,只适合短时间测试。
三、生产环境最佳实践建议
资源监控与限制:
- Splash比较消耗内存,建议根据EC2实例配置设置内存限制(比如Docker Compose里的
mem_limit),避免占满实例资源导致服务崩溃。 - 用AWS CloudWatch监控EC2的CPU、内存、磁盘使用率,设置告警阈值,比如内存使用率超过80%时触发告警。
- Splash比较消耗内存,建议根据EC2实例配置设置内存限制(比如Docker Compose里的
日志管理:
- 不管用哪种方案,都要做好日志收集。Docker日志可以配置日志驱动(比如
json-file),Systemd日志可以用journalctl导出,或者把日志上传到AWS CloudWatch Logs集中管理。 - 定期清理旧日志,避免占满磁盘空间。
- 不管用哪种方案,都要做好日志收集。Docker日志可以配置日志驱动(比如
数据持久化:
- 爬取的结果不要存在容器内部,用Docker Volumes或者挂载EC2的EBS卷保存,或者直接上传到AWS S3,确保实例重启或容器重建时数据不丢失。
安全加固:
- 不要对外公开Splash的8050端口,只允许EC2本机访问,避免被恶意调用消耗资源。
- 定期更新Docker镜像和Python依赖,修复安全漏洞。
- 给EC2实例分配最小权限的IAM角色,比如只允许访问S3的权限(如果需要上传爬取结果)。
定时任务(可选):
- 如果需要定期运行爬虫,可以用Cron(配合Systemd的oneshot服务)或者Docker的Cron容器。比如在Systemd服务里把
Type设为oneshot,然后用Cron定时触发systemctl start scrapy-spider.service。
- 如果需要定期运行爬虫,可以用Cron(配合Systemd的oneshot服务)或者Docker的Cron容器。比如在Systemd服务里把
版本控制与回滚:
- 把Scrapy项目代码、Docker配置文件都放到Git仓库,每次部署前拉取最新代码,方便回滚到之前的版本。
内容的提问来源于stack exchange,提问作者CLPatterson
相关产品推荐
相关产品推荐

