fix(api): 修复邮件队列超时并补齐调度进程
延长 SendEmailJob 超时并改为超时直接失败,补充重试退避、 失败日志与收件人脱敏,避免 send_email 队列批量超时重试。 新增 MAIL_TIMEOUT 与 QUEUE_RETRY_AFTER 配置,并抽出邮件运行时 配置与 HTML 内容服务,确保 Horizon 常驻进程使用最新邮件配置。 为 Docker、supervisor 与 compose 样例补齐 scheduler 进程,并在 节点管理端开启墙检测托管时立即触发一次检测,保证定时任务持续生效。
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Docker Compose images and ports
|
||||
XBOARD_IMAGE=ghcr.io/micah123321/xboard:new
|
||||
XBOARD_ADMIN_IMAGE=ghcr.io/micah123321/xboard-admin-frontend:new
|
||||
REDIS_IMAGE=redis:8-alpine
|
||||
WEB_PORT=7001
|
||||
ADMIN_PORT=7002
|
||||
WS_PORT=8076
|
||||
|
||||
# Admin frontend reverse proxy targets inside the compose network
|
||||
XBOARD_BACKEND_UPSTREAM=http://web:7001
|
||||
XBOARD_UPLOAD_UPSTREAM=https://pic.535888.xyz
|
||||
|
||||
# Laravel application
|
||||
APP_NAME=XBoard
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://your-domain.example
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
# Database: this template expects an external MySQL server
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=your-mysql-host
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=xboard
|
||||
DB_USERNAME=xboard
|
||||
DB_PASSWORD=change-me
|
||||
|
||||
# Redis: shared unix socket from the redis-data volume
|
||||
REDIS_HOST=/data/redis.sock
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=0
|
||||
|
||||
# Queue, cache and session
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
QUEUE_RETRY_AFTER=90
|
||||
SESSION_DRIVER=file
|
||||
MASS_EMAIL_HOURLY_LIMIT=500
|
||||
|
||||
# Mail
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.example.com
|
||||
MAIL_PORT=587
|
||||
MAIL_TIMEOUT=30
|
||||
MAIL_USERNAME=
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS=no-reply@example.com
|
||||
MAIL_FROM_NAME=XBoard
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
|
||||
# Backup and installation flags
|
||||
ENABLE_AUTO_BACKUP_AND_UPDATE=false
|
||||
GOOGLE_CLOUD_KEY_FILE=config/googleCloudStorageKey.json
|
||||
GOOGLE_CLOUD_STORAGE_BUCKET=
|
||||
INSTALLED=false
|
||||
@@ -0,0 +1,6 @@
|
||||
.env
|
||||
.docker/.data/
|
||||
storage/logs/
|
||||
storage/theme/
|
||||
plugins/
|
||||
*.log
|
||||
@@ -0,0 +1,134 @@
|
||||
# Xboard 服务器部署模板
|
||||
|
||||
这个目录是一套可复制到服务器的 Compose 部署模板,拓扑对齐当前生产用法:
|
||||
|
||||
- `web`: Laravel Octane HTTP 服务,默认发布宿主机 `7001`
|
||||
- `horizon`: 队列进程
|
||||
- `scheduler`: Laravel Scheduler,负责持续触发 `sync:server-gfw-checks` 等定时任务
|
||||
- `admin`: 独立管理端前端容器,默认发布宿主机 `7002`
|
||||
- `ws-server`: 节点 WebSocket 服务,默认发布宿主机 `8076`
|
||||
- `redis`: 通过 `redis-data` 卷提供 `/data/redis.sock`
|
||||
|
||||
模板默认不包含 MySQL。数据库继续使用宿主机、面板或云数据库中的外部 MySQL。
|
||||
|
||||
## 首次部署
|
||||
|
||||
服务器需要已安装 Docker,并支持 `docker compose` 命令。
|
||||
|
||||
```sh
|
||||
cd xboard-server
|
||||
sh ./scripts/init.sh
|
||||
vi .env
|
||||
sh ./scripts/deploy.sh
|
||||
```
|
||||
|
||||
`.env` 至少需要检查这些项:
|
||||
|
||||
- `APP_URL`: 对外访问域名,例如 `https://example.com`
|
||||
- `APP_KEY`: 新安装可留空后通过 `xboard:install` 生成;已安装实例必须填原来的值
|
||||
- `DB_HOST / DB_PORT / DB_DATABASE / DB_USERNAME / DB_PASSWORD`: 外部 MySQL 连接
|
||||
- `MAIL_*`: 邮件发送配置
|
||||
- `WEB_PORT / ADMIN_PORT / WS_PORT`: 宿主机端口,和现有服务冲突时修改
|
||||
- `XBOARD_UPLOAD_UPSTREAM`: 管理端图片上传反向代理目标
|
||||
|
||||
## 初始化或迁移数据库
|
||||
|
||||
全新安装时,先确认 `.env` 里的数据库指向正确,再执行交互式安装:
|
||||
|
||||
```sh
|
||||
docker compose exec web php artisan xboard:install
|
||||
```
|
||||
|
||||
已有数据库升级时,不要重新执行安装命令。需要迁移时执行:
|
||||
|
||||
```sh
|
||||
docker compose exec -T web php artisan migrate --force
|
||||
```
|
||||
|
||||
项目自带更新命令也会执行迁移、默认插件检查和缓存刷新:
|
||||
|
||||
```sh
|
||||
docker compose exec -T web php artisan xboard:update
|
||||
```
|
||||
|
||||
## 启动与更新
|
||||
|
||||
启动或重新拉起服务:
|
||||
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
更新镜像但不自动迁移数据库:
|
||||
|
||||
```sh
|
||||
sh ./scripts/update.sh
|
||||
```
|
||||
|
||||
更新镜像并显式执行数据库迁移:
|
||||
|
||||
```sh
|
||||
sh ./scripts/update.sh --migrate
|
||||
```
|
||||
|
||||
查看服务状态:
|
||||
|
||||
```sh
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
查看日志:
|
||||
|
||||
```sh
|
||||
docker compose logs -f web
|
||||
docker compose logs -f horizon
|
||||
docker compose logs -f scheduler
|
||||
docker compose logs -f ws-server
|
||||
docker compose logs -f admin
|
||||
```
|
||||
|
||||
## Scheduler 检查
|
||||
|
||||
自动墙检测依赖 `scheduler` 容器持续运行。该容器执行 `php artisan schedule:work`。节点开启墙检测托管后,`sync:server-gfw-checks` 默认每 30 分钟由 Laravel Scheduler 创建检测任务。
|
||||
|
||||
常用检查命令:
|
||||
|
||||
```sh
|
||||
docker compose ps scheduler
|
||||
docker compose logs -f scheduler
|
||||
docker compose exec -T web php artisan schedule:list
|
||||
```
|
||||
|
||||
手动触发一次墙检测同步:
|
||||
|
||||
```sh
|
||||
docker compose exec -T web php artisan sync:server-gfw-checks
|
||||
```
|
||||
|
||||
如果节点页一直显示“未检测”或“等待节点领取”,优先检查:
|
||||
|
||||
- `scheduler` 是否在线
|
||||
- `php artisan schedule:list` 是否能列出 `sync:server-gfw-checks`
|
||||
- `ws-server` 是否在线,节点端是否已连接
|
||||
- 节点是否是父节点;子节点不会单独创建检测任务
|
||||
- 目标节点是否开启了墙检测托管
|
||||
|
||||
## 管理端代理
|
||||
|
||||
`admin` 容器通过环境变量把管理端请求代理到后端:
|
||||
|
||||
```env
|
||||
XBOARD_BACKEND_UPSTREAM=http://web:7001
|
||||
XBOARD_UPLOAD_UPSTREAM=https://pic.535888.xyz
|
||||
```
|
||||
|
||||
在默认 Compose 网络内,`http://web:7001` 是后端服务地址,不需要改成宿主机 IP。只有上传服务需要按你的实际图片上传入口调整。
|
||||
|
||||
## 目录说明
|
||||
|
||||
- `.env`: 服务器真实配置,不应提交到仓库
|
||||
- `.docker/.data/`: Xboard 容器运行时数据
|
||||
- `storage/logs/`: Laravel 日志
|
||||
- `storage/theme/`: 主题资源
|
||||
- `plugins/`: 插件目录
|
||||
- `redis-data`: Docker 命名卷,保存 Redis socket 和持久化数据
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
sh ./scripts/init.sh
|
||||
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
echo "Docker Compose plugin is required. Install Docker with the 'docker compose' command."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
|
||||
echo "Deployment started."
|
||||
echo "Check scheduler with: sh ./scripts/status.sh"
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
mkdir -p .docker/.data storage/logs storage/theme plugins
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
cp .env.example .env
|
||||
echo "Created .env from .env.example."
|
||||
echo "Edit .env before starting services."
|
||||
else
|
||||
echo ".env already exists."
|
||||
fi
|
||||
|
||||
echo "Runtime directories are ready:"
|
||||
echo " .docker/.data"
|
||||
echo " storage/logs"
|
||||
echo " storage/theme"
|
||||
echo " plugins"
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
echo "Docker Compose plugin is required. Install Docker with the 'docker compose' command."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker compose ps
|
||||
|
||||
echo
|
||||
echo "Recent scheduler logs:"
|
||||
docker compose logs --tail=80 scheduler || true
|
||||
|
||||
echo
|
||||
echo "Laravel schedule list:"
|
||||
if ! docker compose exec -T web php artisan schedule:list; then
|
||||
echo "schedule:list failed. Ensure the web container is running and .env is valid."
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Manual GFW sync command:"
|
||||
echo " docker compose exec -T web php artisan sync:server-gfw-checks"
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
run_migrate=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--migrate)
|
||||
run_migrate=true
|
||||
;;
|
||||
-h|--help)
|
||||
echo "Usage: sh ./scripts/update.sh [--migrate]"
|
||||
echo " --migrate Run 'php artisan migrate --force' after containers are updated."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $arg"
|
||||
echo "Usage: sh ./scripts/update.sh [--migrate]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
echo ".env is missing. Run: sh ./scripts/init.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
echo "Docker Compose plugin is required. Install Docker with the 'docker compose' command."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
if [ "$run_migrate" = "true" ]; then
|
||||
docker compose exec -T web php artisan migrate --force
|
||||
else
|
||||
echo "Migration skipped. Re-run with --migrate when the release requires database migrations."
|
||||
fi
|
||||
|
||||
docker compose ps
|
||||
Reference in New Issue
Block a user