حزمة Python لإلغاء تحميل استدعاء وظيفة إلى خادم HTTP الذي يعمل على مضيف LocalHost تلقائيًا باستخدام ديكور. متوافق مع المعالجة المتعددة ، المخلل ، قارورة ، fastapi ، async وما إلى ذلك ..
تخيل حالة من تطبيق متعدد الخيوط أو متعددة المعالجة حيث تكون وظائف واحدة أو قليلة هي موارد كبيرة (وحدة المعالجة المركزية أو الذاكرة) مكثفة ، ولكن يمكن تشغيل الوظائف الأخرى بالتوازي.
مثال - استدعاء API متبوعًا بالرمز المميز والتصنيف باستخدام نموذج DL كبير متبوعًا بمكالمات API أخرى.
في مثل هذه الحالة ، سيكون من المنطقي إنشاء خادم (عمومًا باستخدام Torchserve أو TFServing) لخدمة الطلبات ، واستبدال مكالمة الوظيفة بطلب نشر إلى الخادم.
يقوم ServerHandler بإنشاء خادم متزامن ويحل محل أي مكالمات إلى الوظيفة تلقائيًا أثناء وقت التشغيل.
يتم تقديم الطلبات على مثيل واحد لعملية تشغيل http.server.httpserver التي تدير الوظيفة داخلها.
AsyncserverHandler متاح أيضًا مما يجعل الطلبات غير متزامنة.
حتى المكالمات التي تم إجراؤها من عمليات مختلفة ، يتم إجراء خيوط ، معالجة متعددة ، قارورة ، حلقات أحداث Fastapi و Async لنفس عملية الخادم.
على العموم :
some code with a callable
يمكن استبداله بمثيل إما serverHandler أو asyncserverhandler الذي يقبل الرمز كسلسلة في الوسيطة الأولى واسم القابل للاستدعاء كوسيطة ثانية.
from auto_function_serving . ServerHandler import ServerHandler
callable_name = ServerHandler ( """
some independent code with a callable
""" , "callable_name" )مثال :
import module1
import module2
def functionname ( someinput ):
a = module1 . function1 ( someinput )
return module2 . function2 ( a )يمكن استبداله بـ
from auto_function_serving . ServerHandler import AsyncserverHandler
functionname = AsyncServerHandler ( """
import module1
import module2
def functionname(someinput):
a = module1.function1(someinput)
return module2.function2(a)
""" , "functionname" , port = "Any" )Decorators ( @asyncserverhandler.decorator و @serverhandler.decorator) وتفاصيل AsyncServerHandler في المزيد من الاستخدامات.
from auto_function_serving . ServerHandler import ServerHandler
callable_name = ServerHandler ( """
some independent code with a callable
""" , "callable_name" , port = None , backend = 'Popen' , wait = 100 , backlog = 1024 )) يدير http.server.httpserver.
يمكن تحميل كائنات ServerHandler و AsyncServerHandler وتفريغها بالمخلل.
يستخدم popen أو المعالجة المتعددة لتشغيل الخادم.
يستخدم فقط تبعية خارجي واحد (AIOHTTP) ، وفقط للمتزامن.
http ، وليس https.
يختار منفذًا يعتمد على تجزئة المدخلات. (ما لم ينص على خلاف ذلك)
تغيير الحد الأدنى من الكود.
يجب أن تكون متوافقة مع جميع الوظائف تقريبا في جميع envs cpython تقريبا. (لست متأكدًا من أين يمكن أن تفشل؟ الرجاء إضافة مشكلة إذا وجدت واحدة.)
تسرب الذاكرة أو الأخطاء (من الخادم) غير مرجحة للغاية لأنها الحد الأدنى ، وعملية واحدة ، وعملية واحدة ، ومكون افتراضي من Python Stdlib.
الاستثناءات تسبب أخطاء 5xx دون إغلاق الخادم.
حتى العمليات المنفصلة ستقدم طلبات إلى مثيل واحد من الخادم نفسه ما لم يتم تحديده خلاف ذلك. (لأنه يبحث عن خادم على منفذ معين.).
يمكن تحديد خلاف ذلك عن طريق تعيين المنفذ على أي منفذ مجاني بحيث يبدأ كائن ServerHandler جديد خادمًا جديدًا.
طلبات نشر HTTP: خفيفة الوزن ، عدد قليل من MS النفقات العامة ، موثوقة.
Async هو ميزة جيدة.
الآن مع الاختبارات.
وجود سلسلة من الكود كوسيطة لفصل ليس من قبل ، ما لم يتم استخدام الديكور.
استيراد الوظائف الداخلية ليس مثاليًا ، حتى عند استخدام الديكور.
طلبات نشر HTTP: غير آمن ، قليل من MS النفقات العامة.
لا يتم إرسال استثناءات داخل الخادم.
لا تجميع.
لا تسجيل في ثناياه عوامل. (يمكن إضافة). تأخير التهيئة حتى بضع ثوان لبدء الخادم. لن تعمل وظائف ASYNC على الخادم.
لا إعادة تشغيل خادم تلقائي في حالة إغلاق الخادم.
قد تترك بعض الموارد مغلقة لفترة من الوقت (<1 دقيقة) إذا لم يتم إغلاقها بشكل صحيح.
قد تحدث المشكلات إذا لم تكن البوبن أو المعالجة المتعددة متوفرة.
محتمل أخطاء متشابكة متداخلة مع jupyter أو غيرها؟ يرجى النظر في Nest-asyncio والقضايا.
تحذيرات من الحلول المتسللة إلى حد ما (ولكن شرعية ووظيفية تماما).
فشل إغلاق عملية الخادم في del و atexit.redister ( del ) لسبب ما (تم اختباره ومن غير المرجح).
استخدم Package Manager PIP لتثبيت Auto_function_serving
pip install auto_function_serving يتم تخزين رمز الخادم في serverHandler.base_code ويتم استخدام بعض تنسيق السلسلة لملء الفراغات.
يتم بدء عملية الخادم باستخدام popen (أو المعالجة المتعددة إذا تم تحديدها). أول شيء يفعله هو استيراد المقبس وربط المنفذ - إذا لم يكن متاحًا ، يتوقف الرمز بعد استثناء. لذلك يتم تشغيل مثيل واحد فقط من الخادم في وقت واحد على الجهاز.
نحن نعلم أن الوظيفة جاهزة بعد أن نتمكن من تلقي طلب الحصول على جائزة صالح من الخادم.
يتم إرسال المدخلات والمخرجات على أنها بويات ، يتم تحويلها من وإلى كائنات باستخدام المخلل.
إذا لم يكن المنفذ في أي شيء أثناء التهيئة (الافتراضي) ، يتم اختيار منفذ من 50000 إلى 60000 عن طريق تجزئة رمز الإدخال لجعله مستقلًا عن مصدر الوظيفة. تصادمات وظائف مختلفة ممكنة ، ولكن من غير المحتمل. يتم استخدام تصادم نفس الوظيفة في عمليات متعددة للتأكد من تشغيل عملية خادم واحدة فقط في وقت واحد. يمكن تحديد المنفذ إذا لزم الأمر.
النفقات العامة للمدخلات والإخراج الصغيرة (بضع بايت) -
~ 2 مللي ثانية للطلبات مع urllib.request
~ 4ms لطلبات ASYNC مع AIOHTTP.CLITESENTERS
النفقات العامة للمدخلات والإخراج الكبيرة
~ 10 مللي ثانية للمدخلات والإخراج 0.5 ميغابايت (1 ميجابايت إجمالي النقل).
~ 60 مللي ثانية لمدة 5 ميغابايت الإدخال والإخراج (10 ميغابايت إجمالي النقل).
~ 600 مللي ثانية لـ 50 ميغابايت إدخال وإخراج (100 ميجابايت إجمالي النقل).
يمكن أيضًا استخدامه مع الديكور المقدم للوظائف مع عدم وجود تبعيات خارج الوظيفة.
from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
for i in range ( big_number )
someexpensivecomputationالواردات داخل الوظيفة ستعمل
from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
import numpy as np from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
if not hasattr ( someheavyfunction , 'RunOnce' ):
global np
import numpy as np
setattr ( someheavyfunction , 'RunOnce' , None )
... etcعندما لا يكون لدى SomeModule أي تحميل عالمي باهظ الثمن.
from auto_function_serving . ServerHandler import ServerHandler
from somemodule import someheavyfunction
someheavyfunction = ServerHandler . decorator ( someheavyfunction )يمكن تغيير عنوان IP عن طريق تعيين ServerHandler.ip_address (الافتراضي "127.0.0.1") قبل إنشاء مثيل جديد.
AsyncServerHandler متاح أيضًا والذي يستخدم AIOHTTP لجعل الطلبات غير متزامنة ، للاستخدام مع Fastapi وحالات الاستخدام غير المتزامنة الأخرى.
لدى AsyncServerHandler نفس الاستخدام مثل ServerHandler ، باستثناء المكالمات يجب أن تنتظر أو استخدام Asyncio.run () أو مع asyncio.get_event_loop (). run_until_complete ().
يمكن أن يكون عدد مكالمات ASYNC محدودًا عن طريق تعيين asyncserverhandler.tcpconnector_limit الذي يتحكم في حد TCPConnector (الافتراضي 100). إن استخدام Semaphore هو أيضًا شيء يجب مراعاته.
المكتبات: الكرفس ، tfserving ، torchserve ، قارورة
إرسال الكرات والسكان المحليين إلى Exec
أشجار AST
طلبات السحب موضع ترحيب.
ترخيص Apache 2.0