🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

負荷分散

負荷分散とは、並列に運用されている機器間でできる限り負担が均等になるように、処理を分散し割り当てることです。 負荷分散は専用機器の使用、DNSサーバの設定、サーバに負荷分散ソフトウェアを導入することで実現できます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

4回答

9623閲覧

FastAPIが高負荷に耐えられない

KohnoseLami

総合スコア17

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

負荷分散

負荷分散とは、並列に運用されている機器間でできる限り負担が均等になるように、処理を分散し割り当てることです。 負荷分散は専用機器の使用、DNSサーバの設定、サーバに負荷分散ソフトウェアを導入することで実現できます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/01/29 18:24

前提・実現したいこと

高負荷に耐えられるAPIを作成したい

発生している問題・エラーメッセージ

Process SpawnProcess-1: Traceback (most recent call last): File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\multiprocessing\process.py", line 315, in _bootstrap self.run() File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\multiprocessing\process.py", line 108, in run self._target(*self._args, **self._kwargs) File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\subprocess.py", line 61, in subprocess_started target(sockets=sockets) File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\main.py", line 419, in run loop.run_until_complete(self.serve(sockets=sockets)) File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 629, in run_until_complete self.run_forever() File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 596, in run_forever self._run_once() File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 1854, in _run_once event_list = self._selector.select(timeout) File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\selectors.py", line 324, in select r, w, _ = self._select(self._readers, self._writers, [], timeout) File "C:\Users\ikki1\AppData\Local\Programs\Python\Python39\lib\selectors.py", line 315, in _select r, w, x = select.select(r, w, w, timeout) ValueError: too many file descriptors in select()

該当のソースコード

Python3

1from fastapi import FastAPI, Depends 2import uvicorn 3 4app = FastAPI() 5 6@app.get("/user/{user_id}") 7def hello(user_id): 8 9 return r 10 11if __name__ == "__main__": 12 uvicorn.run("api:app", host="0.0.0.0", reload=True, port=80)

試したこと

reloadを消してみたりしましたがFastAPIなどでは正直耐えられない負荷は耐えられないというふうな結論が出そうだったのでどうにか高負荷に耐える方法があるかを教えてほしいです。
関数の処理内は消しています。ただ単純にthreading+requestsでストレステストを行ったら落ちてしまうため知ってる方が居たら助けていただけると助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

errormaker74

2021/01/29 19:34

確認ですが`async def`を使えない理由があるのですか? https://fastapi.tiangolo.com/async/#in-a-hurry あともしかしてOSはWindowsでしょうか? Windowsの場合uvicornはパフォーマンスが出せないとどこかで見た気がします。
teamikl

2021/01/29 21:22

エラーログからwindowsで select を使ってるようなので、 IOCP を使ったイベントループにすることで改善の余地はありそうですが、 uvicorn の IOCP はサポート外れてるみたいですね。
KohnoseLami

2021/01/30 01:56

ありがとうございます! async defを使っていなかったのは単純に私の参考にしていた記事が使用しておらず付け足し忘れていました... OSはWindowsです! async defに変更したところエラーは出なくなりましたがやはりリクエストが順番に処理されてしまい大量のリクエストを捌くことができません...(エラーは出ませんが数リクエストで最新のリクエストが応答待ちになる) async defに変更するうえでその関数の中身はおそらく非同期に対応させなきゃいけないのでtime.sleepなどの処理を非同期のものに変更したのですがそうすると質問最初のエラーが出てしまいます。
guest

回答4

0

FastAPI 云々ではなく、ファイルディスクリプタの limit に
引っかかっているのではないでしょうか。

ulimit -n でソフトリミットを確認、
ulimit -Hn でハードリミットを確認
として上限に達しているようならリミット値を上げてみてはどうでしょうか。

投稿2021/01/29 18:54

68user

総合スコア2022

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KohnoseLami

2021/01/29 19:40

Linux環境ではなくWindows環境でのテストを行っているのですがその場合ではどうすれば良いでしょうか?... ちなみに負荷テストは秒速500リクエスト程度で実動作では秒速3000リクエスト程度まで対応したいです。 負荷テストには関数にrequests.getで投げる処理のみを書きwhile True:でthreading.Thread(target=).start()を行っています。
guest

0

Rocky Linuxあたりで、Web ServerをさくらVPSのレンタルサーバーを借りてはいかがでしょうか?

FastAPIは、Go言語のGinフレーク並に高速で御座います。

投稿2023/03/10 11:30

cloud9paiza

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

uvicorn は解らないので、直接的な回答ではありませんが
イベントループのバックエンドに関して。
(select/epoll/kqueue/iocp/io_uring 等)

スケーラビリティに関するストレステストを行うなら、
uvicorn のイベントループに uvloop が使える環境の構築が必要そうです。

Windows に拘るなら、Windows の場合は IOCP で改善できるポイントですが、

  • uvicorn のイベントループは uvloop, asyncio が選択できます。

 それぞれ、プラットフォーム毎にバックエンドが異なります。

  • asyncio では、IOCP を用いた実装 ProactorEventLoop があり、

 python3.8 では windows では asyncio のデフォルトのイベントループ。
ですが、uvicorn 側で SelectorEventLoop に強制的に戻されました。
同時にそれまであった uvicorn/loops/iocp.py もサポートを外れたようです。

  • uvloop は、windows ではインストール失敗

 インストール時ログ "uvloop does not support Window at the moment"

IOCP を選択するだけなら、uvicorn のループを asyncio にして、
asyncio のイベントループを ProactorEventLoop にする方法はあります。
但し、Python側のデフォルト挙動の変更が好ましくなかっただけのか、
他に問題があったのか、サポートが外れた理由は深く追ってません。


サーバーのスケーラビリティに関して、
select での課題と、それに対する各プラットフォームでの解決策
(epoll,kqueue,iocp ~) 辺りは概要だけでも把握しておくと良いです。

問題点は、FastAPI 自体ではなく、下のレイヤー (uvicorn/asyncio/select)

Linux だったとしても、uvicorn のループに
asyncio/SelectorEventLoop を使う構成であれば、select を使った実装になり、
同様のエラー (selectを使う際のスケーラビリティの問題) に遭遇するはずです。

敢えて解決策を挙げるなら、
質問の前提条件(windows)を覆すような回答に思われるかもしれませんが、
幅広くテストされてる環境(uvicornのループにuvloopが使える構成)を
構築されたほうが良いと思います。

投稿2021/01/31 03:48

teamikl

総合スコア8729

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

せっかくfastapiでasgiと組み合わせているんだから

def hello(user_id):

をまずは非同期

async def hello(user_id):

にしてはどうですか?

それからworkersお手本通り4つぐらい生やしてみては?

投稿2021/01/29 19:59

hentaiman

総合スコア6426

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KohnoseLami

2021/01/30 01:56

ありがとうございます! async defを使っていなかったのは単純に私の参考にしていた記事が使用しておらず付け足し忘れていました... OSはWindowsです! async defに変更したところエラーは出なくなりましたがやはりリクエストが順番に処理されてしまい大量のリクエストを捌くことができません...(エラーは出ませんが数リクエストで最新のリクエストが応答待ちになる) async defに変更するうえでその関数の中身はおそらく非同期に対応させなきゃいけないのでtime.sleepなどの処理を非同期のものに変更したのですがそうすると質問最初のエラーが出てしまいます。
hentaiman

2021/01/30 02:53

> リクエストが順番に処理されてしまい それが狙いの機能なので return rのrってなんですか?
KohnoseLami

2021/01/30 05:18

なるほど... では、追いつかない処理は行えないということでしょうか? rには関数内で処理、作成した辞書が含まれています!
hentaiman

2021/01/30 05:40

そうですね 実際どんな処理なんですか?fastapiでそんなに遅い処理を作る事も難しそうな気がするので、作った関数が余程重くて大量にアクセスに向かない処理なんじゃないですか? その場合はキャッシュ機構を用意したりスケールアウト・スケールアップを検討するものです。手元で開発してるとの事なので今質問者が出来るのはredisなどのキャッシュ機能を追加する事(キャッシュを活かせるように設計を見直す)だと思います。
hentaiman

2021/01/30 06:25

外部サービスに依存するならasyncで誤魔化す以外にどうしようもないでしょう 自前のAPIだとしてもネットワーク介するなら遅くなって当たり前なので仕方ないでしょう
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問