336 lines
7.7 KiB
Markdown
336 lines
7.7 KiB
Markdown
# 定时任务暂停指南
|
||
|
||
## 概述
|
||
|
||
项目中的PDF标签缓存定时任务是通过 `LabelPdfCacheBackgroundService` 实现的,它是一个 ASP.NET Core `BackgroundService`,每5分钟执行一次。
|
||
|
||
---
|
||
|
||
## 定时任务信息
|
||
|
||
### 基本参数
|
||
- **服务类**: `LabelPdfCacheBackgroundService`
|
||
- **执行间隔**: 5分钟
|
||
- **功能**: 处理待处理的PDF缓存任务
|
||
- **执行方法**: `ProcessPendingTasksAsync()`
|
||
|
||
### 当前工作流程
|
||
1. 每5分钟检查一次待处理任务
|
||
2. 获取失效的缓存、未处理的任务、新订单
|
||
3. 批量处理这些任务
|
||
4. 同步保存PDF缓存,异步识别条码
|
||
|
||
---
|
||
|
||
## 暂停定时任务的方法
|
||
|
||
### 方法1:修改配置文件(推荐用于生产环境)
|
||
|
||
#### 步骤1:修改 appsettings.json
|
||
|
||
在 `appsettings.json` 或 `appsettings.Production.json` 中添加一个配置开关:
|
||
|
||
```json
|
||
{
|
||
"BackgroundServices": {
|
||
"LabelPdfCacheServiceEnabled": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 步骤2:修改 Program.cs
|
||
|
||
修改Program.cs中的注册代码:
|
||
|
||
```csharp
|
||
// 从这样:
|
||
builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();
|
||
|
||
// 改为:
|
||
var enableLabelPdfCache = builder.Configuration.GetValue<bool>("BackgroundServices:LabelPdfCacheServiceEnabled", true);
|
||
if (enableLabelPdfCache)
|
||
{
|
||
builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();
|
||
}
|
||
```
|
||
|
||
#### 优点
|
||
- 无需重新编译代码
|
||
- 支持配置热更新
|
||
- 适合生产环境
|
||
|
||
#### 缺点
|
||
- 需要修改两个文件
|
||
- 需要重启应用
|
||
|
||
---
|
||
|
||
### 方法2:使用环境变量
|
||
|
||
#### 步骤1:修改 Program.cs
|
||
|
||
```csharp
|
||
var enableLabelPdfCache =
|
||
!string.Equals(
|
||
Environment.GetEnvironmentVariable("DISABLE_LABEL_PDF_CACHE"),
|
||
"true",
|
||
StringComparison.OrdinalIgnoreCase);
|
||
|
||
if (enableLabelPdfCache)
|
||
{
|
||
builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();
|
||
}
|
||
```
|
||
|
||
#### 步骤2:设置环境变量
|
||
|
||
**Windows命令行:**
|
||
```bash
|
||
set DISABLE_LABEL_PDF_CACHE=true
|
||
```
|
||
|
||
**Linux/Mac:**
|
||
```bash
|
||
export DISABLE_LABEL_PDF_CACHE=true
|
||
```
|
||
|
||
**Docker:**
|
||
```dockerfile
|
||
ENV DISABLE_LABEL_PDF_CACHE=true
|
||
```
|
||
|
||
#### 优点
|
||
- 不需要修改配置文件
|
||
- 容易在Docker容器中配置
|
||
- 支持运行时切换
|
||
|
||
#### 缺点
|
||
- 需要修改代码
|
||
- 需要重启应用
|
||
|
||
---
|
||
|
||
### 方法3:创建暂停/恢复接口(最灵活)
|
||
|
||
#### 优点
|
||
- 可以在运行时动态控制
|
||
- 无需重启应用
|
||
- 最灵活,适合生产环境
|
||
|
||
#### 缺点
|
||
- 需要修改更多代码
|
||
- 状态只在内存中保存,重启后会重置
|
||
|
||
---
|
||
|
||
## 方法对比
|
||
|
||
| 方法 | 修改代码 | 重启应用 | 实时性 | 推荐场景 |
|
||
|------|--------|--------|-------|---------|
|
||
| 方法1:配置文件 | 中等 | 是 | 低 | 生产环境固定配置 |
|
||
| 方法2:环境变量 | 中等 | 是 | 低 | Docker容器部署 |
|
||
| 方法3:管理接口 | 高 | 否 | 高 | 需要灵活控制 |
|
||
|
||
---
|
||
|
||
## 使用方法3的API调用示例
|
||
|
||
### JavaScript/Fetch
|
||
```javascript
|
||
// 暂停定时任务
|
||
async function pauseBackgroundService() {
|
||
const response = await fetch('http://localhost:5002/api/label/background-service/pause', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
}
|
||
});
|
||
const data = await response.json();
|
||
console.log(data);
|
||
}
|
||
|
||
// 恢复定时任务
|
||
async function resumeBackgroundService() {
|
||
const response = await fetch('http://localhost:5002/api/label/background-service/resume', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
}
|
||
});
|
||
const data = await response.json();
|
||
console.log(data);
|
||
}
|
||
|
||
// 获取定时任务状态
|
||
async function getBackgroundServiceStatus() {
|
||
const response = await fetch('http://localhost:5002/api/label/background-service/status');
|
||
const data = await response.json();
|
||
console.log(data);
|
||
}
|
||
```
|
||
|
||
### Python
|
||
```python
|
||
import requests
|
||
|
||
BASE_URL = "http://localhost:5002/api/label"
|
||
|
||
# 暂停定时任务
|
||
def pause_service():
|
||
response = requests.post(f"{BASE_URL}/background-service/pause")
|
||
print(response.json())
|
||
|
||
# 恢复定时任务
|
||
def resume_service():
|
||
response = requests.post(f"{BASE_URL}/background-service/resume")
|
||
print(response.json())
|
||
|
||
# 获取定时任务状态
|
||
def get_status():
|
||
response = requests.get(f"{BASE_URL}/background-service/status")
|
||
print(response.json())
|
||
```
|
||
|
||
### cURL
|
||
```bash
|
||
# 暂停定时任务
|
||
curl -X POST http://localhost:5002/api/label/background-service/pause
|
||
|
||
# 恢复定时任务
|
||
curl -X POST http://localhost:5002/api/label/background-service/resume
|
||
|
||
# 获取定时任务状态
|
||
curl -X GET http://localhost:5002/api/label/background-service/status
|
||
```
|
||
|
||
---
|
||
|
||
## 预期响应
|
||
|
||
### 成功暂停
|
||
```json
|
||
{
|
||
"status": "success",
|
||
"message": "后台定时任务已暂停",
|
||
"data": {
|
||
"isRunning": false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 成功恢复
|
||
```json
|
||
{
|
||
"status": "success",
|
||
"message": "后台定时任务已恢复",
|
||
"data": {
|
||
"isRunning": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### 获取状态
|
||
```json
|
||
{
|
||
"status": "success",
|
||
"message": "获取后台服务状态成功",
|
||
"data": {
|
||
"isRunning": true,
|
||
"service": "LabelPdfCacheBackgroundService",
|
||
"interval": "5 minutes"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
1. **数据不会丢失** - 暂停定时任务只是停止周期性执行,已有的待处理任务不会被删除
|
||
|
||
2. **可以手动处理** - 暂停后可以通过 `/batch-parse` 接口手动触发处理
|
||
|
||
3. **性能考虑** - 长时间暂停可能导致待处理任务堆积
|
||
|
||
4. **内存状态** - 如果使用方法3,重启应用后服务会自动恢复运行
|
||
|
||
5. **监控建议** - 建议定期检查任务状态,确保没有任务堆积
|
||
|
||
---
|
||
|
||
## 常见场景
|
||
|
||
### 场景1:维护期间暂停
|
||
如需进行数据库维护或其他重要操作,可以暂停定时任务避免并发冲突:
|
||
|
||
```bash
|
||
# 暂停
|
||
curl -X POST http://localhost:5002/api/label/background-service/pause
|
||
|
||
# 执行维护操作
|
||
# ...
|
||
|
||
# 恢复
|
||
curl -X POST http://localhost:5002/api/label/background-service/resume
|
||
```
|
||
|
||
### 场景2:定点手动处理
|
||
暂停自动定时任务,改为手动通过API按需处理:
|
||
|
||
```bash
|
||
# 暂停自动任务
|
||
curl -X POST http://localhost:5002/api/label/background-service/pause
|
||
|
||
# 手动触发解析(当需要时)
|
||
curl -X POST http://localhost:5002/api/label/batch-parse \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"mode":"all","limit":500}'
|
||
```
|
||
|
||
### 场景3:监控异常时暂停
|
||
如发现定时任务出现异常,可以快速暂停避免继续出错:
|
||
|
||
```bash
|
||
# 检查状态
|
||
curl -X GET http://localhost:5002/api/label/background-service/status
|
||
|
||
# 如果出现异常,暂停
|
||
curl -X POST http://localhost:5002/api/label/background-service/pause
|
||
|
||
# 调查问题后恢复
|
||
curl -X POST http://localhost:5002/api/label/background-service/resume
|
||
```
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
### Q: 暂停后定时任务仍在执行
|
||
**A:** 可能使用的是方法1或方法2,需要重启应用才能生效
|
||
|
||
### Q: 暂停状态在重启后丢失
|
||
**A:** 这是正常的。如需持久化暂停状态,可以将状态保存到数据库
|
||
|
||
### Q: 恢复后任务堆积
|
||
**A:** 这是正常的。系统会逐个处理堆积的任务。可以调整 `ProcessPendingTasksAsync()` 的批处理大小来优化处理速度
|
||
|
||
---
|
||
|
||
## 推荐实施方案
|
||
|
||
根据部署环境选择:
|
||
|
||
- **开发环境**: 使用方法3(API接口),方便调试
|
||
- **生产环境单机**: 使用方法1(配置文件),稳定可靠
|
||
- **生产环境Docker**: 使用方法2(环境变量),配置灵活
|
||
- **生产环境微服务**: 使用方法3(API接口),需要分布式协调
|
||
|
||
---
|
||
|
||
## 参考信息
|
||
|
||
- **定时任务执行间隔**: 5分钟(见 `LabelPdfCacheBackgroundService.cs` 第18行)
|
||
- **处理方法**: `ProcessPendingTasksAsync()`
|
||
- **处理范围**: 失效缓存、待处理任务、新订单
|
||
- **错误处理**: 自动捕获异常,记录日志
|