رفتن به متن راهنما
همه‌ی راهنماها

سقف اجرای هم‌زمان و دورهٔ انتظار

تعداد عملیات هم‌زمان را با سقف اجرای هم‌زمان محدود کنید، ببینید اجارهٔ آن چه قولی می‌دهد و پس از درخواست سرور برای صبر، عملیات تازه را متوقف کنید.

برنامه Reqtide PHP 0.1.0آخرین بررسی زمان خواندن 5 دقیقه

در این صفحه

هر دو محافظت حالت خود را در یک پردازهٔ PHP نگه می‌دارند. سقف اجرای هم‌زمان (Bulkhead) فقط عملیات در جریان همان پردازه را می‌شمارد و دورهٔ انتظار هم فقط عملیات تازهٔ همان پردازه را متوقف می‌کند. محدودیت‌های Reqtide را ببینید.

بلوک‌های کد از examples/09-choosing-policies.php (opens in a new tab) گرفته شده‌اند. یک اسکریپت آن را اجرا می‌کند و با خروجی ثبت‌شده مقایسه می‌کند.

سقف اجرای هم‌زمان

یک وابستگی کند می‌تواند تمام ظرفیت اجرای هم‌زمان یک پردازه را اشغال کند و بقیهٔ کارها پشت آن منتظر بمانند. سقف هم‌زمانی تعداد عملیات در جریان را محدود می‌کند تا بقیهٔ پردازه به کارش ادامه دهد.

قطعه‌کدها از این تنظیم مشترک شروع می‌شوند:

PHP
/** Every pipeline below starts from the same two required options. */
$base = static fn(): PipelineBuilder => PipelineBuilder::profile('choosing', 'v1')
    ->partition('shop', 'prod', 'catalog-api')
    ->attemptTimeout(Duration::seconds(2), AttemptTimeoutRequirement::Cooperative);

$ok = static fn(): string => 'ok';
$context = static fn(CompiledPipeline $pipeline): ExecutionContext => $pipeline->newContext(Duration::seconds(30));

این قطعه فقط یک عملیات در جریان را مجاز می‌کند. تا وقتی عملیات بیرونی تنها slot را در دست دارد، فراخوانی درونی رد می‌شود:

PHP
echo "-- 2. Bulkhead: at most one operation in flight\n";
$pipeline = $base()->bulkhead(1, Duration::seconds(10))->compileInMemory(ExceptionClassifier::create());
$outer = $pipeline->execute(static function () use ($pipeline, $context): string {
    try {
        // Called while the outer operation still holds the only slot.
        return $pipeline->execute(static fn(): string => 'inner', $context($pipeline));
    } catch (AdmissionRejectedException $e) {
        return "inner call refused with {$e->reason()->value}";
    }
}, $context($pipeline));
echo "{$outer}\n";
Text
-- 2. Bulkhead: at most one operation in flight
inner call refused with concurrency_capacity_exhausted

امضای آن bulkhead(capacity, lease) است.

  • پارامتر capacity تعداد slotهاست.
  • هر تلاش تا وقتی اجرا می‌شود یک slot را نگه می‌دارد و وقتی تلاش به پایان برسد، slot آزاد می‌شود. در تأخیر بین تلاش‌های مجدد چیزی نگه داشته نمی‌شود.
  • پارامتر lease مشخص می‌کند اگر فراخوانی‌کننده از بین برود، slot تا چه مدت رزرو بماند. این مقدار باید بیش از 1 ثانیه از مهلت هر تلاش بیشتر باشد.

رد شدن، یک AdmissionRejectedException با دلیل concurrency_capacity_exhausted است. کد callable شما اجرا نشده است.

اجاره (lease) چه کاری نمی‌کند

تمام شدن اجاره، callbackی را که هنوز در حال اجراست متوقف نمی‌کند. slot دوباره آزاد می‌شود، پس ممکن است عملیات تازه‌ای شروع شود در حالی که callback اول هنوز کار می‌کند، و تعداد callbackهای در حال اجرا برای مدتی کوتاه از ظرفیت بیشتر شود. آزادسازی دیرهنگام نمی‌تواند slot نگه‌دارندهٔ جدیدتر را آزاد کند و هر مجوز دقیقاً یک بار تمام می‌شود. Reqtide نمی‌تواند کد شما را متوقف کند، پس callable را طوری بنویسید که مهلت هر تلاش را رعایت کند. Reqtide پیش از ارسال هر تلاش بررسی هم می‌کند که اجارهٔ slot هنوز بیشتر از تلاش دوام داشته باشد. اگر مرحله‌ای کند پیش از ارسال (مثلاً یک فراخوانی کند برای محدودیت نرخ) زمان را مصرف کرده باشد، تلاش فرستاده نمی‌شود و با AdmissionRejectedException و دلیل ownership_lease_insufficient تمام می‌شود. این بررسی از ساعت یکنواخت محلی استفاده می‌کند و توکن حصار (fence) نیست. برای اینکه callback دیرهنگام داده‌های شما را تغییر ندهد، حصار برای نوشتن در مقصد را ببینید.

دورهٔ انتظار

وقتی سرور جواب می‌دهد «آهسته‌تر، بعد از 60 ثانیه دوباره تلاش کن»، بقیهٔ عملیات همان پارتیشن هم باید صبر کنند و لازم نیست هر کدام جداگانه این را بفهمند. دورهٔ انتظار همین مکث مشترک است.

فراخوانی cooldown(cleanupGrace) آن را روشن می‌کند. مقدار cleanupGrace مدتی است که Reqtide بعد از پایان مکث، حالت را نگه می‌دارد. دورهٔ انتظار فقط وقتی فعال می‌شود که طبقه‌بند (classifier) شما انتظارها را با ExceptionClassifier::retryAfterFrom() گزارش کند. بدون آن، هرگز فعال نمی‌شود. Reqtide از HTTP خبر ندارد، پس تبدیل پاسخ 429 و هدر آن به Duration وظیفهٔ شماست.

قطعهٔ زیر همان پایپ‌لاینی را ادامه می‌دهد که در تلاش مجدد و سهمیه آمده است. آنجا عملیات اول به تعویق افتاد، چون انتظار 60 ثانیه‌ای در حداکثر تأخیر 100 میلی‌ثانیه‌ای سیاست تلاش مجدد جا نمی‌شود. عملیات دوم اصلاً callable را صدا نمی‌زند:

PHP
try {
    $pipeline->execute($throttled, $pipeline->newContext(Duration::seconds(30), $safety()));
} catch (AdmissionDeferredException $e) {
    echo "next operation deferred with {$e->reason()->value}; the callable ran {$calls} time(s) in total\n";
}
Text
next operation deferred with cooldown_exceeds_deadline; the callable ran 1 time(s) in total

هر مقدار مثبت Retry-After، دورهٔ انتظار مشترک پارتیشن را تمدید می‌کند. تا وقتی دورهٔ انتظار فعال باشد، Reqtide عملیات تازه را با cooldown_active به تعویق می‌اندازد. اگر انتظار در مهلت عملیات جا نشود، مثل مثال بالا، دلیل cooldown_exceeds_deadline است. در مجموع callable فقط یک بار اجرا شد.

ترتیب بررسی‌ها

دورهٔ انتظار بعد از مدارشکن و سقف هم‌زمانی و پیش از محدودیت نرخ بررسی می‌شود. اگر بررسی بعدی عملیات را رد کند، Reqtide مجوزهایی را که قبلاً گرفته آزاد می‌کند. مفاهیم را ببینید.

آزمون هر دو

سقف هم‌زمانی و دورهٔ انتظار به زمان وابسته‌اند. به‌جای صبر کردن، آن‌ها را با ساعت مجازی آزمون کنید. آزمون با ساعت مجازی را ببینید.