Queue یا صف سازوکاری برای جدا کردن تولید کار از زمان پردازش آن است. در یک فروشگاه، درخواست خرید نباید برای تولید PDF فاکتور، ارسال ایمیل و پردازش عکس منتظر بماند. کارها به صف میروند و Workerها آنها را دریافت میکنند.
صف، بروکر و ورکر چه تفاوتی دارند؟
| مفهوم | مسئولیت | نمونه |
|---|---|---|
| Queue | نگهداری ترتیب یا فهرست کارها | Redis List، Amazon SQS |
| Message Broker | انتقال و مسیریابی پیام | RabbitMQ، ActiveMQ |
| Worker | اجرای کار | Laravel Worker، Celery Worker |
| Event Stream | ثبت و بازخوانی جریان رخداد | Kafka، Redis Streams |
Job در لاراول
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class GenerateInvoice implements ShouldQueue {
use Queueable;
public function __construct(public int $orderId) {}
public function handle(): void {
// Generate invoice idempotently
}
}
GenerateInvoice::dispatch($order->id)->onQueue('invoices');
Listener قابل صف در لاراول
use Illuminate\Contracts\Queue\ShouldQueue;
class SendReceipt implements ShouldQueue {
public function handle(OrderPaid $event): void {
// Send receipt for this event
}
}
دستورات رایج Artisan
| دستور | کاربرد |
|---|---|
php artisan queue:work | شروع Worker |
php artisan queue:work redis --queue=emails --tries=3 | کار روی صف مشخص با سقف تلاش |
php artisan queue:restart | درخواست Restart از Workerهای فعال |
php artisan queue:failed | دیدن Jobهای ناموفق |
php artisan queue:retry all | تلاش دوباره همه Jobهای ناموفق |
php artisan queue:flush | پاکسازی فهرست Jobهای ناموفق، با احتیاط |
php artisan horizon | شروع Horizon روی Redis |
php artisan horizon:status | بررسی وضعیت Horizon |
Python با Celery
# tasks.py
from celery import Celery
app = Celery('shop', broker='redis://localhost:6379/0')
@app.task
def generate_invoice(order_id: int):
print('Invoice for', order_id)
generate_invoice.delay(42)
celery -A tasks worker --loglevel=info
Go: الگوی ساده Worker و Channel
jobs := make(chan int, 100)
for i := 0; i < 4; i++ {
go func() {
for orderID := range jobs {
processInvoice(orderID)
}
}()
}
jobs <- 42
Channel مثال بالا داخل حافظه یک برنامه است و تضمین ماندگاری ندارد. برای صف پایدار در Go میتوان از Asynq با Redis، RabbitMQ یا دیگر سرویسهای سازگار استفاده کرد. در C# نیز BackgroundService و Channel برای پردازش درونبرنامهای و Hangfire یا MassTransit برای سناریوهای ماندگارتر رایجاند.
انتخاب ابزار
| ابزار | بهتر برای | نکته |
|---|---|---|
| لاراول Horizon | مانیتورینگ صفهای Redis در لاراول | فقط اتصالهای Redis را مدیریت میکند |
| RabbitMQ | صف با Routing و Ack انعطافپذیر | طراحی Exchange و Consumer |
| Kafka | رخدادهای قابل بازپخش و Stream در مقیاس بالا | جایگزین مستقیم همه صفهای Job نیست |
| Amazon SQS | صف مدیریتشده در ابر | Visibility Timeout و DLQ |
| Celery | کارهای پسزمینه پایتون | Worker و Broker جداگانه |
| Hangfire | کارهای پسزمینه .NET | Storage مناسب و Dashboard |
نکته فنی
پردازش صف را حداقل یکبار فرض کنید مگر اینکه تضمین دقیق دیگری دارید. شناسه یکتا، آیدمپوتنسی و مدیریت Retry ضروریاند.
اصطلاحات مرتبط: جاب، لسنر، ورکر، صف پیام، مسیج بروکر، ردیس، هورایزن لاراول، صف پیامهای ناموفق، تحویل حداقل یکبار پیام.