跳转到内容

分离工作节点

对于拥有大量关注者的高流量实例,您可以通过将Web服务器与后台工作器分离来 提高性能。这使您能够根据工作负载独立扩展每个组件。

在以下情况下,工作器分离是有益的:

  • 您有数千个关注者并且活动传递缓慢
  • 您的实例处理大量联合流量(大量传入/传出的帖子)
  • 在高峰活动时间Web服务器响应性下降
  • 您希望跨多个服务器进行横向扩展

Hollo由五个主要组件组成:

  1. Web服务器:处理HTTP请求(API、Web UI)
  2. Fedify消息队列:处理ActivityPub inbox/outbox消息
  3. 导入工作器:处理后台数据导入作业
  4. 清理工作器:处理后台清理作业
  5. 远程回复抓取工作器:缓慢抓取远程回复集合

默认情况下(NODE_TYPE=all),所有五个都在单个进程中运行。 您可以使用NODE_TYPE环境变量来分离它们:

NODE_TYPEWeb服务器Fedify队列导入工作器清理工作器回复工作器
all(默认)
web
worker

所有节点共享相同的PostgreSQL数据库,该数据库使用LISTEN/NOTIFY 作为消息队列后端进行实时消息传递。

以下是运行单独的Web和工作节点的compose.yaml示例:

services:
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: hollo
POSTGRES_PASSWORD: password
POSTGRES_DB: hollo
volumes:
- ./data/postgres:/var/lib/postgresql/data
web:
image: ghcr.io/dahlia/hollo:latest
restart: unless-stopped
depends_on:
- db
ports:
- "3000:3000"
environment:
- NODE_TYPE=web
- DATABASE_URL=postgresql://hollo:password@db/hollo
- SECRET_KEY=${SECRET_KEY}
- DRIVE_DISK=fs
- FS_STORAGE_PATH=/data/storage
- STORAGE_URL_BASE=https://hollo.example.com/assets
- BEHIND_PROXY=true
volumes:
- ./data/storage:/data/storage
worker:
image: ghcr.io/dahlia/hollo:latest
restart: unless-stopped
depends_on:
- db
environment:
- NODE_TYPE=worker
- DATABASE_URL=postgresql://hollo:password@db/hollo
- SECRET_KEY=${SECRET_KEY}
- DRIVE_DISK=fs
- FS_STORAGE_PATH=/data/storage
- STORAGE_URL_BASE=https://hollo.example.com/assets
volumes:
- ./data/storage:/data/storage

要运行多个工作节点,请添加更多工作服务:

services:
# ... db和web服务 ...
worker-1:
image: ghcr.io/dahlia/hollo:latest
restart: unless-stopped
depends_on:
- db
environment:
- NODE_TYPE=worker
# ... 其他环境变量 ...
worker-2:
image: ghcr.io/dahlia/hollo:latest
restart: unless-stopped
depends_on:
- db
environment:
- NODE_TYPE=worker
# ... 其他环境变量 ...

PostgreSQL的LISTEN/NOTIFY确保每条消息只由一个工作器处理。

对于手动安装,您可以使用不同的NODE_TYPE值运行单独的进程。

Terminal window
NODE_TYPE=web pnpm prod

这仅在配置的端口上启动Web服务器。

Terminal window
NODE_TYPE=worker pnpm prod
# 或
pnpm worker

这将启动Fedify消息队列和导入工作器,但不启动Web服务器。

如果您使用systemd,请创建单独的服务文件:

[Unit]
Description=Hollo Web Server
After=network.target postgresql.service
[Service]
Type=simple
User=hollo
WorkingDirectory=/opt/hollo
Environment="NODE_TYPE=web"
EnvironmentFile=/opt/hollo/.env
ExecStart=/usr/bin/pnpm prod
Restart=on-failure
[Install]
WantedBy=multi-user.target
[Unit]
Description=Hollo Worker
After=network.target postgresql.service
[Service]
Type=simple
User=hollo
WorkingDirectory=/opt/hollo
Environment="NODE_TYPE=worker"
EnvironmentFile=/opt/hollo/.env
ExecStart=/usr/bin/pnpm worker
Restart=on-failure
[Install]
WantedBy=multi-user.target

然后启用并启动两个服务:

Terminal window
sudo systemctl enable hollo-web hollo-worker
sudo systemctl start hollo-web hollo-worker

对于Docker Compose:

Terminal window
# 查看Web节点日志
docker compose logs -f web
# 查看工作节点日志
docker compose logs -f worker

对于systemd:

Terminal window
# 查看Web节点日志
sudo journalctl -u hollo-web -f
# 查看工作节点日志
sudo journalctl -u hollo-worker -f

当工作节点启动时,您应该看到:

Worker started (Fedify queue + Import worker + Cleanup worker + Remote reply scrape worker)

观察有关处理活动、导入、清理和远程回复抓取的消息,以确认工作器正常运行。

问题:您可以访问Web UI,但传入的活动(关注、点赞、帖子)未被处理。

解决方案:确保至少有一个使用NODE_TYPE=worker的工作节点正在运行。

问题:工作节点退出并显示错误。

解决方案:检查:

  • DATABASE_URL是否正确且数据库可访问
  • 数据库是否应用了最新的迁移
  • 存储配置(DRIVE_DISKFS_STORAGE_PATH等)是否正确

问题:处理联合活动存在延迟。

解决方案:添加更多工作节点以并行处理消息。PostgreSQL的消息队列将在所有可用工作器之间分配工作。

问题:工作节点无法访问上传的文件。

解决方案:确保:

  • 所有节点(Web和工作器)都可以访问相同的存储
  • 对于文件系统存储:存储卷已挂载到所有节点
  • 对于S3存储:所有节点具有相同的S3凭据
  • Web节点:轻量级,可以使用最少的资源运行(512MB-1GB RAM)
  • 工作节点:资源密集型,特别是在高联合活动期间(建议1GB-2GB RAM)
  • 数据库:由所有节点共享;确保它有足够的资源 (对于繁忙的实例建议2GB+ RAM)
  • 并发:每个工作器最多并发处理10条消息 (通过ParallelMessageQueue配置)
  • NODE_TYPE=all(默认)开始,直到遇到性能问题
  • 监控资源使用情况以确定何时需要分离
  • 使用NODE_TYPE=web时至少运行一个专用工作节点
  • 在Web节点前使用反向代理(nginx、Caddy)进行负载均衡
  • 保持存储对所有节点可访问(共享卷或S3)
  • 监控所有节点的日志以查找错误和性能问题