مرحبا يا هبر! أقدم إليكم ترجمة المقال "مقدمة إلى ASGI: ظهور نظام Async Python Web Ecosystem" بقلم Florimond Manca.

"السلاحف بالقرب من البركة" ، ريكارد بارهام على unsplash.com
بيثون لا يقتصر على علوم البيانات ، عاد بيثون تطوير الشبكة مع منعطف غير متزامن جديد في تطوير اللغة!
تجري العديد من الأحداث المهمة في نظام Python لتطوير الويب. أحد برامج التشغيل الرئيسية لهذه التغييرات هو ASGI - واجهة البوابة غير المتزامنة القياسية.
لقد ذكرت بالفعل ASGI عدة مرات في مدونتي ، على وجه الخصوص ، عندما أعلنت Bocadillo ( إطار عمل Python مفتوح المصدر غير متزامن - تقريبًا لكل ) . و tartiflette-starlette ( مكتبة لبناء واجهة برمجة تطبيقات GraphQL API عبر HTTP عبر ASGI - approx. . ) ، لكنني لم أكتب أبداً مقدمة مفصلة عنه. الآن سوف أفعل ذلك.
يستهدف هذا المقال الأشخاص المهتمين بأحدث الاتجاهات في تطوير Python على الويب. أريد أن أدعوكم في جولة سوف تتعلم منها ما هو ASGI وماذا يعني لتطوير الويب الحديث في عالم Python.
قبل أن نبدأ ، أود أن أخبرك أنني قمت مؤخرًا بتصميم رائع ، وهي قائمة رائعة لتتبع نظام ASGI البيئي الذي يتوسع باستمرار.
بدأ كل شيء مع المزامنة / الانتظار
على عكس JavaScript أو Go ، وقت ظهورها ، لم توفر Python القدرة على تنفيذ التعليمات البرمجية بشكل غير متزامن. لفترة طويلة ، لا يمكن تنفيذ التعليمات البرمجية المتوازية في Python إلا بمساعدة المعالجة متعددة الخيوط أو متعددة المعالجات ، أو باستخدام مكتبات شبكات متخصصة مثل eventlet أو gevent أو Twisted. (في عام 2008 ، كان لدى Twisted واجهة برمجة تطبيقات لل coroutines غير المتزامن ، على سبيل المثال ، في شكل inlineCallbacks
و deferredGenerator
)
لقد تغير كل شيء في بيثون 3.4+. في Python 3.4 ، تم تضمين asyncio في المكتبة القياسية ، مما أدى إلى دعم تعدد المهام التعاوني على أساس المولدات yield from
بناء الجملة.
في وقت لاحق في بيثون 3.5 ، تمت إضافة بناء جملة async/await
. وبفضل هذا ، ظهر coroutines الأصلي ، بغض النظر عن التنفيذ الأساسي ، مما أدى إلى اندفاع الذهب حول التزامن في بيثون.
بدأ السباق المجنون! منذ إصدار الإصدار 3.5 ، قام المجتمع بتزامن كل شيء في مكانه حرفيًا. إذا كنت مهتمًا ، يتم سرد العديد من المشاريع الناتجة في lio-libs و asyncio رائع .
كما قد تعتقد ، فإن هذا يعني أيضًا أن خوادم الويب وتطبيقات Python تتجه نحو عدم التزامن. في الواقع ، كل الرجال اللطفاء يفعلون ذلك! ( حتى Django ) ( Habr: Django 3.0 سيكون غير متزامن ، تم إصداره بالفعل في 12/02/2019 - تقريبا. )
ASGI مراجعة
فكيف ASGI تنسجم مع كل هذا؟
يمكن اعتبار ASGI من المستوى الأعلى كارتباط يسمح لخوادم وتطبيقات Python غير المتزامنة بالتفاعل مع بعضها البعض. يكرر العديد من الأفكار المعمارية من WSGI ، وغالبًا ما يتم تقديمه كخليفة له مع عدم التزامن المدمج.
هذه هي الطريقة التي يمكن تمثيلها على الرسم البياني:

على مستوى عالٍ للغاية ، يعد ASGI واجهة للتواصل بين التطبيقات والخوادم. ولكن في الواقع ، كل شيء أكثر تعقيدًا قليلاً.
لفهم كيف يعمل ASGI حقًا ، دعنا نلقي نظرة على مواصفات ASGI .
يتكون ASGI من عنصرين مختلفين:
- خادم بروتوكول - يستمع على مآخذ وتحويلها إلى اتصالات ورسائل الأحداث داخل كل اتصال.
- تطبيق ( تطبيق ) ، يعيش داخل خادم البروتوكول ، يتم إنشاء مثيله مرة واحدة لكل اتصال ويقوم بمعالجة رسائل الأحداث فور حدوثها.
وبالتالي ، وفقًا للمواصفات ، فإن ما يشير إليه ASGI حقًا هو تنسيق الرسالة وكيف ينبغي نقل هذه الرسائل بين التطبيق وخادم البروتوكول الذي يقوم بتشغيله.
الآن يمكننا عمل نسخة أكثر تفصيلاً من المخطط:

هناك العديد من التفاصيل الأكثر إثارة للاهتمام في البروتوكول. على سبيل المثال ، يمكنك إلقاء نظرة على مواصفات HTTP و WebSocket .
بالإضافة إلى ذلك ، على الرغم من أن المواصفات تركز بشدة على التفاعل بين الخادم والتطبيق ، إلا أن ASGI يتمكن من تغطية العديد من الجوانب.
وصلنا إلى هذا في غضون دقيقة ، ولكن أولاً ...
أساسيات ASGI
الآن وبعد أن رأينا كيف تتوافق ASGI مع نظام Python على الويب ، دعونا نلقي نظرة فاحصة على كيفية ترجمة هذا إلى رمز.
يعتمد ASGI على نموذج بسيط: عندما يتصل العميل بخادم ، يتم إنشاء مثيل تطبيق. ثم يتم نقل البيانات الواردة إلى التطبيق ويتم إرسال جميع البيانات التي يتم إرجاعها مرة أخرى.
إن نقل البيانات إلى التطبيق هنا يعني في الواقع الاتصال بالتطبيق كما لو كانت وظيفة ، أي: شيء يأخذ بعض المدخلات وإرجاع الإخراج.
في الواقع ، كل ما يمثله تطبيق ASGI هو أمر قابل للاستدعاء (يسمى كائن). يتم تحديد المعلمات الخاصة بالكائن المسمى ، مرة أخرى ، بواسطة مواصفات ASGI :
async def app(scope, receive, send): ...
توقيع هذه الوظيفة هو بالضبط ما تعنيه كلمة "أنا" في "ASGI": الواجهة التي يجب أن يطبقها التطبيق حتى يتمكن الخادم من الاتصال بها.
لنلقِ نظرة على معلمات الوظيفة:
scope
هو قاموس يحتوي على معلومات حول طلب وارد. محتوياته مختلفة لاتصالات HTTP و WebSocket .receive
هي وظيفة غير متزامن لتلقي رسائل حول أحداث ASGI.send
هي وظيفة غير متزامن لإرسال رسائل حول أحداث ASGI.
في الواقع ، تسمح لك هذه المعلمات بتلقي ( receive()
) وإرسال ( send()
) بيانات عبر قناة الاتصال التي يدعمها خادم البروتوكول ، وكذلك فهم السياق الذي تم إنشاء هذه القناة فيه (أو scope
).
لا أعرف عنك ، لكني معجب حقًا بالمظهر العام لهذه الواجهة وبنيتها. في أي حال ، الآن دعونا نلقي نظرة على نموذج التعليمات البرمجية.
عرض الكود!
للحصول على فكرة عملية عما يبدو عليه ASGI ، قمتُ بإنشاء مشروع بسيط على ASGI العاري يوضح تطبيق HTTP يخدمه uvicorn (خادم ASGI شائع):
async def app(scope, receive, send): assert scope["type"] == "http" await send({ "type": "http.response.start", "status": 200, "headers": [ [b"content-type", b"text/plain"], ] }) await send({ "type": "http.response.body", "body": b"Hello, world!", })
شفرة المصدر - https://glitch.com/edit/#!/asgi-hello-world
هنا نستخدم send()
لإرسال استجابة HTTP إلى العميل: أولاً نرسل الرؤوس ، ثم نص الاستجابة.
أعترف أنه نظرًا لجميع هذه القواميس والبيانات الثنائية الأولية ، فإن ASGI العارية ليست ملائمة جدًا للعمل.
لحسن الحظ ، هناك خيارات من المستوى الأعلى - وذلك عندما أبدأ الحديث عن Starlette .
Starlette هو مشروع رائع حقًا ، وفي رأيي ، جزء أساسي من النظام البيئي ASGI.
باختصار ، يوفر مجموعة من المكونات عالية المستوى ، مثل الطلبات والإجابات ، التي يمكنك استخدامها للتخلص من بعض تفاصيل ASGI. هنا ، ألق نظرة على "عالم الترحيب" في Starlette:
لدى Starlette كل ما تتوقعه من إطار ويب حقيقي - التوجيه ، الوسيطة ، إلخ. لكنني قررت عرض هذه النسخة المخففة للإشارة إلى القوة الحقيقية لـ ASGI ، والتي ...
السلاحف على طول الطريق
مفهوم مثير للاهتمام وتغيير القواعد في ASGI هو السلاحف على طول الطريق ، وهو تعبير اخترع في الأصل (على ما أظن؟) بقلم أندرو غودوين ، الذي أنشأ Django Migrations ويعمل حاليًا على Django لدعم عدم التزامن .
ولكن ماذا يعني هذا بالضبط؟
نظرًا لأن ASGI عبارة عن مجموعة تجريدية تتيح لنا تحديد السياق الذي نحن فيه وتلقي البيانات وإرسالها في أي وقت ، هناك فكرة أن ASGI يمكن استخدامها ليس فقط بين الخوادم والتطبيقات ، ولكن أيضًا في أي مكان في الحزمة.
على سبيل المثال ، كائن Response
Starlette هو تطبيق ASGI نفسه. في الواقع ، يمكننا تقصير الكود في المثال التطبيق أعلاه لهذا:
كيف سخيفة لا تبدو؟
لكن مهلا ، هذا ليس كل شيء.
تتمثل النتيجة الأعمق لـ "السلاحف على طول الطريق" في أنه يمكننا إنشاء جميع أنواع التطبيقات والبرامج الوسيطة والمكتبات وغيرها من المشاريع والتأكد من توافقها طالما أنها جميعًا تنفذ واجهة تطبيق ASGI.
(بالإضافة إلى ذلك ، من تجربتي الشخصية في بناء Bocadillo ، يؤدي قبول واجهة ASGI في كثير من الأحيان (إن لم يكن دائمًا) إلى رمز أكثر نظافة)
على سبيل المثال ، يمكننا إنشاء برنامج وسيط ASGI (أي تطبيق يلف تطبيقًا آخر) لعرض الوقت الذي استغرقه إكمال الطلب:
لاستخدامها ، نحن ببساطة التفاف التطبيق معها ...
... وسوف تعمل بطريقة سحرية فقط.
$ uvicorn app:app INFO: Started server process [59405] INFO: Waiting for application startup. INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ... INFO: ('127.0.0.1', 62718) - "GET / HTTP/1.1" 200 Took 1.00 seconds
إنه TimingMiddleware
أنه في TimingMiddleware
يمكنك التفاف أي تطبيق ASGI. يعد التطبيق الداخلي في هذا المثال بسيطًا للغاية ، ولكنه قد يكون مشروعًا حقيقيًا ومتكاملًا (تخيل المئات من واجهات برمجة التطبيقات ونقاط نهاية WebSocket) - لا يهم طالما أن الواجهة متوافقة مع ASGI.
(هناك إصدار من هذه الوسيطة أكثر استعدادًا للاستخدام الصناعي: timit-asgi .)
لماذا يجب أن تهتم؟
على الرغم من أنني أعتقد أن التوافق حجة قوية جدًا ، إلا أن هناك العديد من المزايا لاستخدام المكونات المستندة إلى ASGI لإنشاء تطبيقات الويب Python.
- السرعة: إن الطبيعة غير المتزامنة لتطبيقات وخوادم ASGI تجعلها سريعة حقًا (على الأقل بالنسبة لبيثون) - نحن نتحدث عن 60 إلى 70 ألف طلب في الثانية (على افتراض أن Flask و Django يصلان فقط إلى 10-20 كيلو في وضع مماثل).
- الميزات: تمنحك خوادم ومنصات ASGI إمكانية الوصول إلى وظائف متوازية بشكل أساسي (WebSocket و Server-Sent Events و HTTP / 2) التي لا يمكن تنفيذها باستخدام رمز متزامن و WSGI.
- الاستقرار: ASGI كمواصفات موجودة منذ 3 سنوات ، ويعتبر الإصدار 3.0 مستقرًا جدًا. ونتيجة لذلك ، فإن الأجزاء الرئيسية للنظام الإيكولوجي تستقر.
من وجهة نظر المكتبات والأدوات ، لا أعتقد أنه يمكننا القول إننا وصلنا إلى المستوى المطلوب. ولكن بفضل مجتمع نشط للغاية ، لدي آمال كبيرة في أن يصل النظام البيئي لـ ASGI قريبًا إلى تكافؤ الوظائف مع النظام البيئي التقليدي المتزامن / WSGI.
أين يمكنني العثور على مكونات متوافقة مع ASGI؟
في الواقع ، المزيد والمزيد من الناس يبنون ويحسنون المشاريع القائمة على ASGI. من الواضح أن هذه الخوادم وأطر الويب ، ولكن هناك تطبيقات وسيطة موجهة نحو المنتج مثل Datasette أيضًا.
فيما يلي بعض الأمثلة للمكونات غير المستندة إلى الويب التي تهمني:
إنه لأمر مدهش أن نلاحظ أن النظام الإيكولوجي يتطور بنجاح ، ومع ذلك ، كان من الصعب علي شخصياً مواكبة التغييرات.
هذا هو السبب في أنني خلقت رهيبة asgi . آمل أن يساعد هذا الجميع على مواكبة كل الأشياء المدهشة التي تحدث في عالم ASGI. (ولأنه وصل إلى ما يقرب من 100 نجم في غضون أيام قليلة ، لدي شعور بأن هناك بالفعل حاجة لجمع معلومات حول موارد ASGI في مكان واحد.)
النتائج
على الرغم من أن هذا قد يبدو مثل تفاصيل التنفيذ ، إلا أنني متأكد من أن ASGI قد أرست الأساس لعصر جديد في تطوير الويب Python.
إذا كنت ترغب في معرفة المزيد عن ASGI ، تحقق من المنشورات المختلفة (المقالات والخطب) المدرجة في awesome-asgi
. إذا كنت ترغب في لمسها ، فجرب أيًا من المشاريع التالية:
تم إنشاء هذه المشاريع ودعمها من قبل Encode ، وبشكل رئيسي توم كريستي. هناك مناقشات مفتوحة حول إنشاء فريق دعم Encode ، لذلك إذا كنت تبحث عن فرصة للمشاركة في تطوير المصادر المفتوحة ، فستتاح لك هذه الفرصة!
استمتع بالسفر إلى عالم ASGI!