نمونه ای از پیکربندی سرور asynq برای پیادهسازی محدودیت نرخ پردازش وظایف
این صفحه نشان میدهد چگونه سرور asynq را برای پیادهسازی محدودیت نرخ پردازش وظایف پیکربندی کنیم.
لطفا توجه داشته باشید که این محدودیت نرخ برای هر نمونه سرور است و نه یک محدودیت نرخ سراسری.
در این مثال، ما از بسته golang.org/x/time/rate
برای نمایش محدودیت نرخ استفاده خواهیم کرد. تنظیمات کلیدی در تنظیمات اولیه سرور شما IsFailure
و RetryDelayFunc
هستند. ما یک نوع خطای سفارشی ایجاد خواهیم کرد و از خطاهای داده شده در توابع IsFailure
و RetryDelayFunc
استدعا خواهیم کرد.
package main
import (
"context"
"errors"
"fmt"
"log"
"math/rand"
"time"
"golang.org/x/time/rate"
"github.com/hibiken/asynq"
)
func main() {
srv := asynq.NewServer(
asynq.RedisClientOpt{Addr: ":6379"},
asynq.Config{
Concurrency: 10,
// اگر به محدودیت نرخ برمیگردد، خطا را به عنوان یک خطا شمرده نکنید.
IsFailure: func(err error) bool { return !IsRateLimitError(err) },
RetryDelayFunc: retryDelay,
},
)
if err := srv.Run(asynq.HandlerFunc(handler)); err != nil {
log.Fatal(err)
}
}
type RateLimitError struct {
RetryIn time.Duration
}
func (e *RateLimitError) Error() string {
return fmt.Sprintf("محدودیت نرخ رسیده است (تلاش مجدد در %v)", e.RetryIn)
}
func IsRateLimitError(err error) bool {
_, ok := err.(*RateLimitError)
return ok
}
func retryDelay(n int, err error, task *asynq.Task) time.Duration {
var ratelimitErr *RateLimitError
if errors.As(err, &ratelimitErr) {
return ratelimitErr.RetryIn
}
return asynq.DefaultRetryDelayFunc(n, err, task)
}
// محدودیت نرخ 10 رویداد در هر ثانیه با اجازه شلیکهای تا 30 رویداد را در نظر گرفته میشود.
var limiter = rate.NewLimiter(10, 30)
func handler(ctx context.Context, task *asynq.Task) error {
if !limiter.Allow() {
return &RateLimitError{
RetryIn: time.Duration(rand.Intn(10)) * time.Second,
}
}
log.Printf("[*] پردازش وظیفه %s", task.Payload())
return nil
}