يعني PoolTimeout أن HTTPX لم يحصل على اتصال من المجمّع خلال مدة الانتظار المضبوطة. لا يثبت ذلك انتهاء مهلة اتصال TCP جديد بالبروكسي. ربما لا يزال الطلب الثاني ينتظر داخل عمليتك.

يسهل تكرار هذا عندما يسمح العميل باتصال واحد وتُترك الاستجابة المتدفقة الأولى مفتوحة. بدء طلب آخر لا يحرّر ذلك الاتصال تلقائيًا.

اجعل مسؤولية الاستجابة المتدفقة واضحة

import httpx

limits = httpx.Limits(
    max_connections=1,
    max_keepalive_connections=1,
)
timeout = httpx.Timeout(
    connect=5, read=10, write=10, pool=1
)

with httpx.Client(
    proxy="http://203.0.113.10:8080",
    trust_env=False,
    limits=limits,
    timeout=timeout,
) as client:
    with client.stream("GET", "https://example.com/") as response:
        print(response.status_code)
        for chunk in response.iter_bytes():
            print(len(chunk))

    next_response = client.get("https://example.com/")
    print(next_response.status_code)

استبدل عنوان البروكسي التوثيقي قبل التشغيل. يبدأ الطلب التالي بعد الخروج من سياق التدفق. يغلق هذا الخروج الاستجابة حتى لو خرجت الشيفرة من الحلقة أو أثارت استثناءً.

في التدفق اليدوي، مثل client.send(request, stream=True)، تكون الشيفرة مسؤولة عن الإغلاق النهائي. مع AsyncClient، يُنتظر التنظيف اليدوي المقابل باستخدام response.aclose(). إغلاق استجابة لم تُقرأ يحرّر السعة، لكنه قد يتطلب التخلص من الاتصال الأساسي بدل إعادة استخدامه.

اقرأ اسم الاستثناء

يتعلق ConnectTimeout بإنشاء الاتصال. ويتعلق ReadTimeout بانتظار بيانات الاستجابة. ويتعلق PoolTimeout بالحصول على خانة اتصال. تسجيل «مهلة البروكسي» فقط يفقد التمييز اللازم لاختيار الإصلاح.

افحص الاستجابات المفتوحة والمهام المتزامنة وحدود الاتصالات قبل تغيير عناوين IP لنقاط الاتصال. قد يلائم المجمّع الأكبر عبئًا متزامنًا مشروعًا، لكنه لا يصلح استجابات لا تُغلق أبدًا. إنه يمنح التطبيق سعة أكبر ليشغلها فقط.

احتفظ بالعميل قابلًا لإعادة الاستخدام عبر عبء العمل. إعادة إنشائه كي يبدو كل طلب ناجحًا قد تخفي مشكلة في دورة الحياة وتفقد إعادة استخدام الاتصالات.

مقالات ذات صلة