แพ็คเกจ Python เพื่อถ่ายการเรียกใช้ฟังก์ชั่นไปยังเซิร์ฟเวอร์ HTTP ที่ทำงานบน LocalHost โดยอัตโนมัติโดยใช้มัณฑนากรโดยอัตโนมัติ เข้ากันได้กับการประมวลผลแบบมัลติโปรเซสเซอร์, ดอง, ขวด, fastapi, async ฯลฯ ..
ลองนึกภาพกรณีของแอปพลิเคชั่นหลายเกลียวหรือมัลติโปรเซสเซอร์ที่มีฟังก์ชั่น 1 หรือไม่กี่ฟังก์ชั่นเป็นทรัพยากรอย่างหนัก (CPU หรือหน่วยความจำ) ที่เข้มข้น แต่ฟังก์ชั่นอื่น ๆ สามารถทำงานได้แบบขนาน
ตัวอย่าง - การโทร API ตามด้วย tokenization และการจำแนกประเภทโดยใช้โมเดล DL ขนาดใหญ่ตามด้วยการโทร API เพิ่มเติม
ในกรณีเช่นนี้มันจะสมเหตุสมผลที่จะสร้างเซิร์ฟเวอร์ (โดยทั่วไปใช้ Torchserve หรือ TFServing) เพื่อให้บริการคำขอและแทนที่การเรียกใช้ฟังก์ชันด้วยคำขอโพสต์ไปยังเซิร์ฟเวอร์
ServerHandler สร้างเซิร์ฟเวอร์ แบบซิงโครนัส และแทนที่การโทรใด ๆ ไปยังฟังก์ชั่นโดยอัตโนมัติในระหว่างการรันไทม์
คำขอจะทำกับ 1 อินสแตนซ์ของกระบวนการที่ใช้ http.server.httpserver ซึ่งเรียกใช้ฟังก์ชั่นภายใน
AsyncServerHandler ยังมีอยู่ซึ่งทำให้คำขอแบบอะซิงโครนัส
แม้แต่การโทรที่ทำจากกระบวนการที่แตกต่างกันเธรดการประมวลผลมัลติโปรเซสเซอร์ขวด Fastapi และลูปเหตุการณ์ Async จะทำกับกระบวนการเซิร์ฟเวอร์เดียวกัน
โดยทั่วไป:
some code with a callable
สามารถแทนที่ด้วยอินสแตนซ์ของ ServerHandler หรือ AsyncServerHandler ที่ยอมรับรหัสเป็นสตริงในอาร์กิวเมนต์แรกและชื่อของ callable เป็นอาร์กิวเมนต์ที่สอง
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 หรือ Multiprocessing เพื่อเรียกใช้เซิร์ฟเวอร์
ใช้การพึ่งพาภายนอกเพียงครั้งเดียว (AIOHTTP) และสำหรับ ASYNC เท่านั้น
http ไม่ใช่ https
เลือกพอร์ตตามแฮชของอินพุต (เว้นแต่จะระบุไว้เป็นอย่างอื่น)
การเปลี่ยนแปลงรหัสน้อยที่สุด
ควรเข้ากันได้กับฟังก์ชั่นเกือบทั้งหมดใน cpython เกือบทั้งหมด (ไม่แน่ใจว่าจะล้มเหลวได้ที่ไหนโปรดเพิ่มปัญหาหากคุณพบ)
การรั่วไหลของหน่วยความจำหรือข้อผิดพลาด (จากเซิร์ฟเวอร์) นั้นไม่น่าเป็นไปได้อย่างมากเนื่องจากมีเพียงเล็กน้อย, เธรดเดี่ยว, กระบวนการเดี่ยวและส่วนประกอบเริ่มต้นของ Python stdlib
ข้อยกเว้นทำให้เกิดข้อผิดพลาด 5xx โดยไม่ปิดเซิร์ฟเวอร์
แม้แต่กระบวนการแยกต่างหากก็จะทำการร้องขอเป็น 1 อินสแตนซ์ของเซิร์ฟเวอร์เดียวกันเว้นแต่จะระบุไว้เป็นอย่างอื่น (เพราะกำลังมองหาเซิร์ฟเวอร์บนพอร์ตเฉพาะ)
สามารถระบุเป็นอย่างอื่นโดยตั้งค่าพอร์ตเป็นพอร์ตฟรีใด ๆ เพื่อให้วัตถุ ServerHandler ใหม่เริ่มต้นเซิร์ฟเวอร์ใหม่
คำขอโพสต์ HTTP: น้ำหนักเบา, ค่าใช้จ่าย MS ไม่กี่ตัว, เชื่อถือได้
Async เป็นคุณสมบัติที่ดี
ตอนนี้มีการทดสอบ
การมีสตริงของรหัสเป็นอาร์กิวเมนต์ไปยังชั้นเรียนไม่ใช่ Pythonic เว้นแต่จะใช้มัณฑนากร
การนำเข้าฟังก์ชั่นภายในไม่เหมาะแม้ว่าจะมีการใช้งานมัณฑนากร
คำขอโพสต์ HTTP: ไม่ปลอดภัยค่าใช้จ่าย MS ไม่กี่ MS
ข้อยกเว้นภายในเซิร์ฟเวอร์จะไม่ถูกส่งกลับ
ไม่มีการแบตช์
ไม่มีการบันทึกแบบ inbuilt (สามารถเพิ่มได้) ความล่าช้าในการเริ่มต้นไม่กี่วินาทีในการเริ่มต้นเซิร์ฟเวอร์ ฟังก์ชั่น Async จะไม่ทำงานบนเซิร์ฟเวอร์
ไม่มีการรีสตาร์ทเซิร์ฟเวอร์อัตโนมัติในกรณีที่เซิร์ฟเวอร์ปิด
อาจปล่อยให้ทรัพยากรบางอย่างถูกล็อคอยู่พักหนึ่ง (<1 นาที) หากไม่ปิดอย่างถูกต้อง
ปัญหาอาจเกิดขึ้นได้หากไม่มีการประมวลผล POPEN หรือการประมวลผลหลายครั้ง
ข้อผิดพลาด async ที่เป็นไปได้ที่เป็นไปได้กับ Jupyter หรืออื่น ๆ ? โปรดดู Nest-Asyncio และปัญหา
คำเตือนจากวิธีแก้ปัญหาที่ค่อนข้างแฮ็ก (แต่ถูกต้องและใช้งานได้อย่างสมบูรณ์)
การปิดกระบวนการเซิร์ฟเวอร์ใน DEL และ ATEXIT.REDISTER ( DEL ) ล้มเหลวด้วยเหตุผลบางอย่าง (ทดสอบและไม่น่าเป็นไปได้)
ใช้ Package Manager Pip เพื่อติดตั้ง Auto_Function_Serving
pip install auto_function_serving รหัสสำหรับเซิร์ฟเวอร์จะถูกเก็บไว้ใน ServerHandler.base_code และการจัดรูปแบบสตริงบางอย่างใช้เพื่อเติมในช่องว่าง
กระบวนการเซิร์ฟเวอร์เริ่มต้นด้วย POPEN (หรือการประมวลผลหลายครั้งหากระบุ) สิ่งแรกที่ทำคือนำเข้าซ็อกเก็ตและผูกพอร์ต - หากไม่สามารถใช้งานได้รหัสหยุดหลังจากข้อยกเว้น ดังนั้นเพียง 1 อินสแตนซ์ของเซิร์ฟเวอร์ทำงานครั้งละบนเครื่อง
เรารู้ว่าฟังก์ชั่นพร้อมหลังจากเราสามารถรับคำขอได้รับที่ถูกต้องจากเซิร์ฟเวอร์
อินพุตและเอาต์พุตจะถูกส่งเป็นไบต์แปลงเป็นและจากวัตถุโดยใช้ดอง
หากพอร์ตไม่มีในขณะที่เริ่มต้น (ค่าเริ่มต้น) พอร์ตจาก 50000 ถึง 60000 จะถูกเลือกโดยการแฮชรหัสอินพุตเพื่อให้เป็นอิสระจากแหล่งที่มาของฟังก์ชัน การชนกันของฟังก์ชั่นที่แตกต่างกันเป็นไปได้ แต่ไม่น่าเป็นไปได้ การชนกันของฟังก์ชั่นเดียวกันในหลาย ๆ กระบวนการใช้เพื่อให้แน่ใจว่ากระบวนการเซิร์ฟเวอร์เพียง 1 กระบวนการทำงานครั้งละ สามารถระบุพอร์ตได้หากจำเป็น
ค่าใช้จ่ายสำหรับอินพุตและเอาต์พุตขนาดเล็ก (ไม่กี่ไบต์) -
~ 2ms สำหรับคำขอด้วย urllib.request
~ 4ms สำหรับคำขอ async ด้วย aiohttp.clientsession
ค่าใช้จ่ายสำหรับอินพุตและเอาต์พุตขนาดใหญ่
~ 10ms สำหรับอินพุตและเอาต์พุต 0.5 MB (การถ่ายโอนทั้งหมด 1MB)
~ 60ms สำหรับอินพุตและเอาต์พุต 5 MB (การถ่ายโอนทั้งหมด 10 MB)
~ 600ms สำหรับอินพุตและเอาต์พุต 50 MB (การถ่ายโอนทั้งหมด 100 MB)
นอกจากนี้ยังสามารถใช้กับมัณฑนากรที่ให้ไว้สำหรับฟังก์ชั่นที่ไม่มีการพึ่งพานอกฟังก์ชั่น
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 และกรณีการใช้ async อื่น ๆ
AsyncServerHandler มีการใช้งานเหมือนกับ ServerHandler ยกเว้นการโทรจะต้องรอหรือใช้กับ asyncio.run () หรือกับ asyncio.get_event_loop () run_until_complete ()
จำนวนการโทรแบบ async สามารถถูก จำกัด ได้โดยการตั้งค่า asyncServerHandler.tcpconnector_limit ซึ่งควบคุมขีด จำกัด TCPConnector (ค่าเริ่มต้น 100) การใช้เซมาฟอร์ก็เป็นสิ่งที่ต้องพิจารณา
ห้องสมุด: ขึ้นฉ่าย, tfserving, torchserve, flask
การส่งลูกโลกและคนในท้องถิ่นไปยังผู้บริหาร
ต้นไม้ AST
ยินดีต้อนรับคำขอดึง
ใบอนุญาต Apache 2.0