Decoratorを使用してLocalHostで実行されているHTTPサーバーに関数呼び出しをオフロードするPythonパッケージ。マルチプロセッシング、ピクルス、フラスコ、ファーストアピ、アナイクなどと互換性があります。
1つまたは少数の関数が非常にリソース(CPUまたはメモリ)が集中的であるが、他の関数が並行して実行できるマルチスレッドまたはマルチプロセッシングアプリケーションのケースを想像してください。
例-API呼び出しに続いて、大規模なDLモデルを使用したトークン化と分類に続いて、さらにAPI呼び出しが続きます。
そのような場合、リクエストを提供するためにサーバー(通常はTorchServeまたはTFServingを使用)を作成し、サーバーへのPOSTリクエストに関数呼び出しを置き換えることは理にかなっています。
ServerHandlerは、同期サーバーを作成し、ランタイム中に呼び出しを機能に自動的に置き換えます。
リクエストは、その内で関数を実行するhttp.server.httpserverを実行するプロセスの1インスタンスに行われます。
Asyncserverhandlerも利用可能で、リクエストを非同期にします。
さまざまなプロセス、スレッド、マルチプロセス、フラスコ、FastaPI、およびAsyncイベントループから作られた呼び出しでさえ、同じサーバープロセスに対して行われます。
一般的に :
some code with a callable
コードを最初の引数の文字列として受け入れるServerHandlerまたはAsyncserverhandlerのいずれかのインスタンスと、2番目の引数として呼び出し可能な名前のインスタンスに置き換えることができます。
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" )デコレーター( @asyncserverhandler.decorator and @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にのみ使用します。
httpsではなくhttp。
入力のハッシュに基づいてポートを選択します。 (特に指定されていない場合)
最小限のコード変更。
ほぼすべてのcpython envsのほぼすべての機能と互換性があるはずです。 (どこで失敗するかわからない?問題を見つけた場合は問題を追加してください。)
メモリリークまたはエラー(サーバーから)は、最小限の単一スレッド、単一プロセス、およびPython Stdlibのデフォルトコンポーネントであるため、非常にありそうもない。
例外は、サーバーを閉じることなく5xxエラーを引き起こします。
別途指定がない限り、個別のプロセスでも同じサーバーの1インスタンスにリクエストを行います。 (特定のポートでサーバーを探しているからです。)。
新しいServerHandlerオブジェクトが新しいサーバーを起動するように、ポートを任意のポートに設定して、それ以外の場合は指定できます。
httpの投稿リクエスト:軽量、オーバーヘッドの数は少なく、信頼性がありません。
Asyncは良い機能です。
今テストで。
クラスへの引数としてコードの文字列を持つことは、装飾器が使用されない限り、Pythonicではありません。
内部関数のインポートは、装飾器を使用している場合でも理想的ではありません。
HTTP投稿リクエスト:不安、オーバーヘッドはほとんどありません。
サーバー内の例外は返送されません。
バッチはありません。
組み込みロギングはありません。 (追加できます)。サーバーを開始するための最大数秒の初期化遅延。 Async関数はサーバーでは機能しません。
サーバーが閉じる場合に自動サーバーの再起動はありません。
適切に閉じていないと、しばらくの間ロックされたリソースをロックしたままにしておくことがあります。
Popenまたはマルチプロセッシングが利用できない場合、問題が発生する可能性があります。
Jupyterまたはその他のネストされた非同期エラーの可能性はありますか? Nest-Asyncioと問題を調べてください。
ややハッキーな(ただし、合法的で完全に機能的な)回避策からの警告。
Delおよびatexit.Redister( del )でのサーバープロセスの閉鎖は、何らかの理由で失敗します(テストされておらず、ありそうもない)。
パッケージマネージャーPIPを使用して、auto_function_servingをインストールします
pip install auto_function_servingサーバーのコードはserverhandler.base_codeに保存され、いくつかの文字列フォーマットはブランクを埋めるために使用されます。
サーバープロセスは、Popen(または指定されている場合はマルチプロセッシング)で開始されます。最初に行うのは、インポートソケットとポートにバインドすることです。利用できない場合は、例外の後にコードが停止します。したがって、マシンで一度に実行されるサーバーのインスタンスのみがサーバーのみです。
サーバーから有効なGETリクエストを受け取ることができた後、機能の準備ができていることがわかります。
入力と出力はバイトとして送信され、ピクルを使用してオブジェクトに変換されます。
初期化中にポートがない場合(デフォルト)、50000から60000のポートが入力コードをハッシュして関数のソースから独立していることによって選択されます。さまざまな機能の衝突は可能ですが、ありそうもありません。複数のプロセスで同じ関数の衝突を使用して、1つのサーバープロセスのみが一度に実行されることを確認します。必要に応じてポートを指定できます。
小さな入力と出力のオーバーヘッド(数バイト) -
urllib.requestのリクエストの場合は〜2ms
aiohttp.clientsessionを使用した非同期リクエストの場合は〜4ms
大きな入力と出力のオーバーヘッド
0.5 MBの入力と出力(合計1MBの移動1MB)で〜10ms。
5 MBの入力と出力の場合は〜60ms(合計10 MBの転送)。
50 MBの入力と出力で〜600ms(合計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ソメモジュールに高価なグローバルローディングがない場合。
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は、asyncio.run()またはasyncio.get_event_loop()。run_until_complete()で通話を待つか使用する必要がある場合を除き、サーバーハンドラーと同じ使用法を持っています。
Asyncserverhandler.tcpconnector_limitを設定することにより、Asyncコールの数を制限できます。セマフォの使用も考慮すべきことです。
図書館:セロリ、TfServing、Torchserve、Flask
グローバルと地元の人々を幹部に送る
ASTツリー
プルリクエストは大歓迎です。
Apacheライセンス2.0