本文目录导读:

我来详细介绍Symfony Scheduler组件的使用和配置。
什么是Symfony Scheduler
Symfony Scheduler是Symfony框架的任务调度组件,用于管理定时任务、周期性任务和一次性任务,它提供了比cron更灵活和强大的任务调度能力。
安装
composer require symfony/scheduler
基本配置
启用调度器
在 config/packages/scheduler.yaml 中配置:
# config/packages/scheduler.yaml
framework:
scheduler:
enabled: true
创建任务
创建任务类
// src/Scheduler/MyTask.php
namespace App\Scheduler;
use Symfony\Component\Scheduler\Attribute\AsCronTask;
use Symfony\Component\Scheduler\Attribute\AsPeriodicTask;
#[AsCronTask('*/5 * * * *')] // 每5分钟执行一次
#[AsPeriodicTask('10 minutes')] // 每10分钟执行一次
class MyTask
{
public function __invoke(): void
{
// 执行任务逻辑
$this->doSomething();
}
private function doSomething(): void
{
// 你的业务逻辑
file_put_contents('/tmp/scheduler.log',
sprintf("Task executed at %s\n", date('Y-m-d H:i:s')),
FILE_APPEND
);
}
}
高级用法
使用Schedule对象
// src/Scheduler/TaskProvider.php
namespace App\Scheduler;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\RecurringMessage;
use Symfony\Component\Scheduler\ScheduleProviderInterface;
class TaskProvider implements ScheduleProviderInterface
{
public function getSchedule(): Schedule
{
$schedule = new Schedule();
// 添加周期性任务
$schedule->add(
RecurringMessage::every('5 minutes', new SendNewsletter())
);
// 添加Cron表达式任务
$schedule->add(
RecurringMessage::cron('0 0 * * *', new DailyReport())
);
// 添加一次性任务
$schedule->add(
RecurringMessage::at(new \DateTimeImmutable('2024-12-31 23:59:59'), new NewYearTask())
);
return $schedule;
}
}
任务类型定义
// src/Message/SendNewsletter.php
namespace App\Message;
class SendNewsletter
{
public function __construct(
private string $newsletterType,
private array $recipients = []
) {}
public function getNewsletterType(): string
{
return $this->newsletterType;
}
public function getRecipients(): array
{
return $this->recipients;
}
}
消息处理器
// src/MessageHandler/SendNewsletterHandler.php
namespace App\MessageHandler;
use App\Message\SendNewsletter;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
class SendNewsletterHandler
{
public function __invoke(SendNewsletter $message): void
{
// 处理邮件发送
$type = $message->getNewsletterType();
$recipients = $message->getRecipients();
// 发送邮件逻辑
foreach ($recipients as $recipient) {
// 发送邮件
}
}
}
使用Cron表达式
// 常用的Cron表达式
#[AsCronTask('* * * * *')] // 每分钟
#[AsCronTask('*/5 * * * *')] // 每5分钟
#[AsCronTask('0 * * * *')] // 每小时
#[AsCronTask('0 0 * * *')] // 每天午夜
#[AsCronTask('0 0 * * 0')] // 每周日
#[AsCronTask('0 0 1 * *')] // 每月1号
#[AsCronTask('0 */2 * * *')] // 每2小时
#[AsCronTask('0 0 * * 1-5')] // 工作日午夜
使用周期性时间间隔
// 使用人类可读的时间格式
#[AsPeriodicTask('5 minutes')] // 每5分钟
#[AsPeriodicTask('1 hour')] // 每小时
#[AsPeriodicTask('1 day')] // 每天
#[AsPeriodicTask('2 weeks')] // 每2周
#[AsPeriodicTask('1 month')] // 每月
// 使用DateInterval
#[AsPeriodicTask('P1D')] // 每天
#[AsPeriodicTask('PT1H')] // 每小时
#[AsPeriodicTask('PT30M')] // 每30分钟
运行调度器
启动调度器消费者
# 在后台运行调度器 php bin/console scheduler:consume # 指定调度器名称 php bin/console scheduler:consume default # 使用进程管理器(Supervisor)配置
Supervisor配置
# /etc/supervisor/conf.d/symfony-scheduler.conf [program:symfony-scheduler] command=php /path/to/your/project/bin/console scheduler:consume --time-limit=3600 directory=/path/to/your/project autostart=true autorestart=true stderr_logfile=/var/log/symfony/scheduler.err.log stdout_logfile=/var/log/symfony/scheduler.out.log numprocs=2 process_name=%(program_name)s_%(process_num)02d
完整示例
邮件通知任务
// src/Scheduler/EmailNotificationTask.php
namespace App\Scheduler;
use Symfony\Component\Scheduler\Attribute\AsPeriodicTask;
use Psr\Log\LoggerInterface;
#[AsPeriodicTask('1 hour')]
class EmailNotificationTask
{
public function __construct(
private LoggerInterface $logger
) {}
public function __invoke(): void
{
try {
// 检查待发送邮件
$pendingEmails = $this->getPendingEmails();
foreach ($pendingEmails as $email) {
$this->sendEmail($email);
$this->markAsSent($email);
}
$this->logger->info('Email notification task completed', [
'count' => count($pendingEmails)
]);
} catch (\Exception $e) {
$this->logger->error('Email notification failed', [
'error' => $e->getMessage()
]);
}
}
private function getPendingEmails(): array
{
// 从数据库获取待发送邮件
return [];
}
private function sendEmail(array $email): void
{
// 发送邮件逻辑
}
private function markAsSent(array $email): void
{
// 标记为已发送
}
}
数据清理任务
// src/Scheduler/CleanupTask.php
namespace App\Scheduler;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Scheduler\Attribute\AsCronTask;
#[AsCronTask('0 3 * * *')] // 每天凌晨3点执行
class CleanupTask
{
public function __construct(
private EntityManagerInterface $entityManager
) {}
public function __invoke(): void
{
// 清理30天前的日志
$this->cleanOldLogs();
// 清理过期会话
$this->cleanExpiredSessions();
// 清理临时文件
$this->cleanTempFiles();
}
private function cleanOldLogs(): void
{
$date = new \DateTime('-30 days');
$this->entityManager
->createQuery('DELETE FROM App\Entity\Log l WHERE l.createdAt < :date')
->setParameter('date', $date)
->execute();
}
private function cleanExpiredSessions(): void
{
// 清理过期session
}
private function cleanTempFiles(): void
{
// 清理临时文件
$tempDir = sys_get_temp_dir() . '/app';
if (is_dir($tempDir)) {
array_map('unlink', glob("$tempDir/*"));
}
}
}
最佳实践
错误处理
#[AsPeriodicTask('5 minutes')]
class RobustTask
{
public function __invoke(): void
{
try {
// 任务逻辑
} catch (\Exception $e) {
// 记录日志
$this->logger->error('Task failed', [
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
// 发送告警通知
$this->notifyAdmin($e);
// 重新抛出异常(可选)
throw $e;
}
}
}
任务锁
use Symfony\Component\Lock\LockFactory;
#[AsPeriodicTask('10 minutes')]
class LockedTask
{
public function __construct(
private LockFactory $lockFactory
) {}
public function __invoke(): void
{
$lock = $this->lockFactory->createLock('task-lock');
if (!$lock->acquire()) {
// 任务已在运行,跳过
return;
}
try {
// 执行任务
$this->doWork();
} finally {
$lock->release();
}
}
}
监控和日志
#[AsPeriodicTask('1 hour')]
class MonitoredTask
{
public function __invoke(): void
{
$startTime = microtime(true);
// 执行任务
$this->doWork();
$duration = microtime(true) - $startTime;
// 记录性能指标
$this->logger->info('Task completed', [
'duration' => $duration,
'memory_usage' => memory_get_peak_usage(true)
]);
}
}
注意事项
- 确保只有一个实例运行:使用锁机制防止并发执行
- 监控执行时间:避免任务重叠执行
- 处理异常:确保异常不会导致整个调度器崩溃
- 记录日志:便于问题排查和性能监控
- 使用Supervisor:保证调度器持续运行
- 考虑分布式环境:在多服务器环境中需要使用分布式锁
Symfony Scheduler为PHP项目提供了强大、灵活的任务调度能力,相比传统cron更加易于维护和扩展。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播