本文目录导读:

- 基础异常处理
- 使用
onFailure方法(Laravel 8+) - 使用
withoutOverlapping和onSuccess - 创建自定义异常处理器
- 使用 Laravel 内置的 ping 功能
- 综合示例:完善的异常处理
- 全局异常处理器
- 最佳实践建议
- 添加监控和警告
- 关键要点:
在Laravel中处理调度回调异常,有几种有效的方法:
基础异常处理
在调度任务中直接捕获
// app/Console/Kernel.php
use Illuminate\Support\Facades\Log;
use Throwable;
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
try {
// 你的定时任务逻辑
$this->processData();
} catch (Throwable $e) {
Log::error('定时任务执行失败', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
// 可以发送邮件或通知
// Notification::route('mail', 'admin@example.com')->notify(new TaskFailed($e));
}
})->everyMinute();
}
使用 onFailure 方法(Laravel 8+)
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
// 定时任务逻辑
})
->everyMinute()
->onFailure(function (Throwable $e) {
// 任务失败时的处理
Log::critical('调度任务失败', [
'exception' => $e->getMessage(),
'time' => now()->toDateTimeString()
]);
// 发送通知
// 报警、邮件等
});
}
使用 withoutOverlapping 和 onSuccess
$schedule->call(function () {
// 任务逻辑
})
->everyFiveMinutes()
->withoutOverlapping(10) // 防止任务重叠
->onSuccess(function () {
Log::info('任务执行成功');
})
->onFailure(function (Throwable $e) {
Log::error('任务执行失败: ' . $e->getMessage());
});
创建自定义异常处理器
创建自定义异常类
// app/Exceptions/ScheduleTaskException.php
namespace App\Exceptions;
use Exception;
class ScheduleTaskException extends Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
创建调度任务基类
// app/Console/Commands/BaseScheduleCommand.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Throwable;
abstract class BaseScheduleCommand extends Command
{
abstract protected function executeTask();
public function handle()
{
$startTime = microtime(true);
try {
$result = $this->executeTask();
$duration = round(microtime(true) - $startTime, 2);
Log::info('调度任务成功', [
'command' => static::class,
'duration' => $duration . '秒'
]);
return $result;
} catch (Throwable $e) {
Log::error('调度任务异常', [
'command' => static::class,
'message' => $e->getMessage(),
'line' => $e->getLine(),
'file' => $e->getFile()
]);
$this->sendFailureNotification($e);
return 1; // 返回非零值表示失败
}
}
protected function sendFailureNotification(Throwable $e)
{
// 发送邮件、Slack等通知
// Notification::route('mail', config('app.admin_email'))
// ->notify(new ScheduleTaskFailed($e));
}
}
使用 Laravel 内置的 ping 功能
$schedule->call(function () {
// 任务逻辑
})
->everyMinute()
->pingBefore('https://api.example.com/job/started')
->thenPing('https://api.example.com/job/finished')
->onFailure(function (Throwable $e) {
// 发送错误通知
Log::error('任务失败', $e->getMessage());
});
综合示例:完善的异常处理
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
$job = new ProcessDataJob();
$job->handle();
})
->name('process-data')
->withoutOverlapping(30) // 防止重叠
->runInBackground() // 后台运行
->onSuccess(function () {
Log::info('数据处理成功', ['time' => now()]);
})
->onFailure(function (Throwable $e) {
Log::error('数据处理失败', [
'message' => $e->getMessage(),
'time' => now()->toDateTimeString()
]);
// 发送错误通知
Notification::route('mail', config('mail.admin_address'))
->notify(new ScheduleTaskFailed($e));
// 或者发送到钉钉/Slack群
// Http::post(config('services.dingtalk.webhook'), [
// 'msgtype' => 'text',
// 'text' => [
// 'content' => '调度任务失败: ' . $e->getMessage()
// ]
// ]);
});
// 也可以设置重试
$schedule->call(function () {
try {
// 任务逻辑
} catch (Throwable $e) {
// 如果失败,在5分钟后重试
Log::warning('任务失败,准备重试', ['error' => $e->getMessage()]);
throw $e;
}
})
->everyMinute()
->retry(3, 60); // 重试3次,间隔60秒
}
全局异常处理器
// app/Exceptions/Handler.php
public function register()
{
$this->reportable(function (Throwable $e) {
if ($e instanceof ScheduleTaskException) {
Log::channel('schedule')->error('调度任务异常', [
'exception' => $e
]);
// 发送通知
$this->notifyAdmin($e);
}
});
}
protected function notifyAdmin(Throwable $e)
{
// 发送邮件/短信/微信通知
}
最佳实践建议
// 建议将调度任务拆分为独立的Job类
$schedule->job(new ProcessDataJob('param1', 'param2'))
->everyMinute()
->onFailure(function (Throwable $e) {
// 记录失败日志
Log::error('队列任务失败', ['message' => $e->getMessage()]);
// 可以计算连续失败次数,达到阈值后发送告警
cache()->increment('schedule:fail_count', 1);
$failCount = cache()->get('schedule:fail_count', 0);
if ($failCount >= 5) {
// 发送严重告警
alertAdmin("连续5次调度失败,最后一次错误: " . $e->getMessage());
// 重置计数
cache()->forget('schedule:fail_count');
}
});
添加监控和警告
use Carbon\Carbon;
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
$start = now();
try {
// 任务逻辑
$duration = now()->diffInSeconds($start);
// 如果执行时间过长,记录警告
if ($duration > 300) {
Log::warning('任务执行时间过长', ['duration' => $duration]);
}
} catch (Throwable $e) {
Log::error('任务执行失败', [
'message' => $e->getMessage(),
'start' => $start->toDateTimeString(),
'duration' => now()->diffInSeconds($start)
]);
throw $e;
}
})
->everyMinute()
->pingBefore('https://example.com/ping')
->thenPing('https://example.com/pong');
}
关键要点:
- 错误日志:始终记录完整的异常信息,包括堆栈
- 通知机制:配置邮件、Slack等通知渠道
- 重试策略:合理设置重试次数和间隔
- 防止重叠:使用
withoutOverlapping防止任务堆积 - 监控告警:持续监控任务健康状态
- 异常分类:区分业务异常和系统异常
这样就能全面捕获和处理调度任务的异常,确保系统的稳定性和可维护性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播