You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
|
# 自动扣款任务诊断报告
|
|
|
|
|
|
|
|
|
|
|
|
## 问题描述
|
|
|
|
|
|
`admin/project` 页面的自动扣款任务(`autoCheckout`)有两天没有按照预期得到结果。
|
|
|
|
|
|
|
|
|
|
|
|
## 发现的问题
|
|
|
|
|
|
|
|
|
|
|
|
### 1. **日志文件缺失**
|
|
|
|
|
|
- 最新的日志文件是 `storage/logs/daily_auto_checkout-2021-04-11.log`
|
|
|
|
|
|
- 说明最近没有执行记录,可能的原因:
|
|
|
|
|
|
- Laravel 调度器没有运行
|
|
|
|
|
|
- 任务执行时发生异常但没有记录
|
|
|
|
|
|
|
|
|
|
|
|
### 2. **代码缺少异常处理**
|
|
|
|
|
|
- 原代码中 `autoCheckout()` 方法没有 try-catch 包裹
|
|
|
|
|
|
- 如果执行过程中出现异常,会导致任务静默失败,且没有错误日志
|
|
|
|
|
|
|
|
|
|
|
|
### 3. **潜在的空指针问题**
|
|
|
|
|
|
- 代码中 `$customer = $item->customer` 可能为 null
|
|
|
|
|
|
- 如果 customer 为 null,访问 `$customer->balance` 会导致致命错误
|
|
|
|
|
|
|
|
|
|
|
|
### 4. **缺少详细的执行日志**
|
|
|
|
|
|
- 原代码只在开始和成功时记录日志
|
|
|
|
|
|
- 缺少失败、跳过等情况的详细记录
|
|
|
|
|
|
|
|
|
|
|
|
## 已实施的改进
|
|
|
|
|
|
|
|
|
|
|
|
### 1. **添加完整的异常处理**
|
|
|
|
|
|
- 在 `autoCheckout()` 方法外层添加 try-catch
|
|
|
|
|
|
- 在调度器调用处也添加异常处理
|
|
|
|
|
|
- 所有异常都会记录到日志
|
|
|
|
|
|
|
|
|
|
|
|
### 2. **添加空值检查**
|
|
|
|
|
|
- 检查 `$customer` 是否为 null
|
|
|
|
|
|
- 如果为空,记录警告日志并跳过该订单项
|
|
|
|
|
|
|
|
|
|
|
|
### 3. **增强日志记录**
|
|
|
|
|
|
- 记录任务开始和结束
|
|
|
|
|
|
- 记录处理的订单项数量
|
|
|
|
|
|
- 记录成功、跳过、失败的统计
|
|
|
|
|
|
- 记录每个订单项的详细处理情况
|
|
|
|
|
|
- 异常时记录完整的堆栈跟踪
|
|
|
|
|
|
|
|
|
|
|
|
### 4. **添加数据库事务**
|
|
|
|
|
|
- 每个订单项的扣款操作使用事务包裹
|
|
|
|
|
|
- 确保数据一致性
|
|
|
|
|
|
|
|
|
|
|
|
## 排查步骤
|
|
|
|
|
|
|
|
|
|
|
|
### 1. **检查 Laravel 调度器是否运行**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 检查 crontab 是否配置了调度器
|
|
|
|
|
|
crontab -l | grep "schedule:run"
|
|
|
|
|
|
|
|
|
|
|
|
# 应该看到类似这样的配置:
|
|
|
|
|
|
# * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
如果没有配置,需要添加:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
* * * * * cd /Users/weizongsong/www/tiantian2 && php artisan schedule:run >> /dev/null 2>&1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. **检查调度器状态**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 查看调度器列表
|
|
|
|
|
|
php artisan schedule:list
|
|
|
|
|
|
|
|
|
|
|
|
# 手动运行一次调度器(测试)
|
|
|
|
|
|
php artisan schedule:run
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. **检查日志文件**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 查看最新的自动扣款日志
|
|
|
|
|
|
ls -lah storage/logs/daily_auto_checkout*.log
|
|
|
|
|
|
|
|
|
|
|
|
# 查看日志内容
|
|
|
|
|
|
tail -f storage/logs/daily_auto_checkout-$(date +%Y-%m-%d).log
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. **手动测试任务**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 在 PHP 交互式环境中测试
|
|
|
|
|
|
php artisan tinker
|
|
|
|
|
|
>>> (new \App\Models\OrderItems())->autoCheckout();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. **检查缓存**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 检查缓存中的 last_id
|
|
|
|
|
|
php artisan tinker
|
|
|
|
|
|
>>> cache('last_auto_checkout_order_item_id')
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 可能的原因总结
|
|
|
|
|
|
|
|
|
|
|
|
1. **调度器未运行**(最可能)
|
|
|
|
|
|
- crontab 未配置或配置错误
|
|
|
|
|
|
- 服务器时间不正确
|
|
|
|
|
|
- 调度器进程被杀死
|
|
|
|
|
|
|
|
|
|
|
|
2. **代码执行异常**
|
|
|
|
|
|
- 数据库连接问题
|
|
|
|
|
|
- 数据完整性问题(customer 为 null)
|
|
|
|
|
|
- 其他运行时错误
|
|
|
|
|
|
|
|
|
|
|
|
3. **时间范围问题**
|
|
|
|
|
|
- 任务只在 14:00-23:59 之间执行
|
|
|
|
|
|
- 如果当前时间不在这个范围内,任务不会执行
|
|
|
|
|
|
|
|
|
|
|
|
4. **没有待处理的订单**
|
|
|
|
|
|
- 所有订单都已处理
|
|
|
|
|
|
- 查询条件不匹配
|
|
|
|
|
|
|
|
|
|
|
|
## 建议的监控措施
|
|
|
|
|
|
|
|
|
|
|
|
1. **添加任务执行监控**
|
|
|
|
|
|
- 可以添加一个健康检查接口
|
|
|
|
|
|
- 记录最后一次成功执行的时间
|
|
|
|
|
|
|
|
|
|
|
|
2. **设置告警**
|
|
|
|
|
|
- 如果超过一定时间没有执行,发送告警
|
|
|
|
|
|
- 监控日志中的错误数量
|
|
|
|
|
|
|
|
|
|
|
|
3. **定期检查**
|
|
|
|
|
|
- 定期检查日志文件
|
|
|
|
|
|
- 确认任务正常执行
|
|
|
|
|
|
|
|
|
|
|
|
## 改进后的代码位置
|
|
|
|
|
|
|
|
|
|
|
|
- `app/Models/OrderItems.php` - `autoCheckout()` 方法
|
|
|
|
|
|
- `app/Console/Kernel.php` - 调度器配置
|
|
|
|
|
|
|
|
|
|
|
|
## 下一步行动
|
|
|
|
|
|
|
|
|
|
|
|
1. ✅ 已添加异常处理和详细日志
|
|
|
|
|
|
2. ⏳ 检查并配置 Laravel 调度器
|
|
|
|
|
|
3. ⏳ 查看改进后的日志输出
|
|
|
|
|
|
4. ⏳ 确认任务正常执行
|
|
|
|
|
|
|