FastAPI × Uvicorn：最強のAPI高速化コンビ誕生！

[![Group122.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/774af4b2-3830-ca93-de9c-6653b2590b51.png)](https://leapcell.io/?lc_t=q_unvicorn)


# Uvicornとは何か？

[![uvicorn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/b92cf2c5-86f8-03ab-0c65-5f03b283eb8c.png)](https://leapcell.io/?lc_t=q_unvicorn)


**答え**：Uvicornは、uvloopとhttptoolsを基盤とした、非常に高速なASGI（Asynchronous Server Gateway Interface）サーバーです。これは、asyncioに基づいて開発された軽量で効率的なWebサーバーフレームワークです。
Uvicornは当初、2つの目標を掲げて設計されました。
- uvloopとhttptoolsを使って、極めて高速なasyncioサーバーを実装すること。
- ASGIに基づく最小限のアプリケーションインターフェースを実装すること。
現在、これはHTTP、WebSocket、Pub/Subブロードキャストをサポートしており、他のプロトコルやメッセージタイプに拡張することも可能です。
公式サイト：uvicorn (https://uvicorn.org/)

# uvloopとhttptoolsとは何か？
**答え**：uvloopは、標準ライブラリのasyncio内のイベントループを置き換えるために使用されます。これはCythonで実装されており、非常に高速で、asyncioの速度を2～4倍速くすることができます。あなたはasyncioに精通していると思います。なぜなら、非同期コードを書く際にはそれが不可欠だからです。
httptoolsは、Node.jsのHTTPパーサーのPython実装です。

# ASGIサーバーとは何か？
**答え**：ASGI（Asynchronous Server Gateway Interface）は、ネットワークプロトコルサービスとPythonアプリケーションの間の標準的なインターフェースです。これは、HTTP、HTTP2、WebSocketなどの複数の一般的なプロトコルタイプを処理することができます。
ASGIプロトコル：https://asgi.readthedocs.io/en/latest/specs/main.html

# Uvicornの概要
**答え**：現在、Pythonには非同期ゲートウェイプロトコルインターフェースが欠けていました。ASGIの登場により、このギャップが埋められました。これからは、共通の標準を使って全ての非同期フレームワーク用のツールを実装することができます。ASGIは、PythonがWebフレームワーク分野でNode.JSやGolangと競争するのを助け、高性能なI/O集中型タスクを実現することを目指しています。ASGIはHTTP2とWebSocketをサポートしていますが、WSGIはそれをサポートしていません。
Uvicornは現在、HTTP1.1とWebSocketをサポートしており、HTTP2のサポートも計画されています。

# Uvicornの使い方
- **インストール**
`pip install uvicorn` を実行します。

- **新しい`example.py` ファイルを作成する**
```python
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!',
    })
```
- **コマンドラインからUvicornを起動する**
`uvicorn example:app` を実行します。

- **スクリプト形式で起動する**
```python
import uvicorn

async def app(scope, receive, send):
   ...

if __name__ == "__main__":
    uvicorn.run("example:app", host="127.0.0.1", port=8000, log_level="info")
```

Uvicornは複数のコマンドをサポートしており、`uvicorn --help` で表示できます。
```
➜  ~ uvicorn --help
Usage: uvicorn [OPTIONS] APP

Options:
  --host TEXT                     Bind socket to this host.  [default:
                                  127.0.0.1]
  --port INTEGER                  Bind socket to this port. If 0, an available
                                  port will be picked.  [default: 8000]
  --uds TEXT                      Bind to a UNIX domain socket.
  --fd INTEGER                    Bind to socket from this file descriptor.
  --reload                        Enable auto-reload.
  --reload-dir PATH               Set reload directories explicitly, instead
                                  of using the current working directory.
  --reload-include TEXT           Set glob patterns to include while watching
                                  for files. Includes '*.py' by default; these
                                  defaults can be overridden with `--reload-
                                  exclude`. This option has no effect unless
                                  watchfiles is installed.
  --reload-exclude TEXT           Set glob patterns to exclude while watching
                                  for files. Includes '.*,.py[cod],.sw.*,
                                  ~*' by default; these defaults can be
                                  overridden with `--reload-include`. This
                                  option has no effect unless watchfiles is
                                  installed.
  --reload-delay FLOAT            Delay between previous and next check if
                                  application needs to be. Defaults to 0.25s.
                                  [default: 0.25]
  --workers INTEGER               Number of worker processes. Defaults to the
                                  $WEB_CONCURRENCY environment variable if
                                  available, or 1. Not valid with --reload.
  --loop [auto|asyncio|uvloop]    Event loop implementation.  [default: auto]
  --http [auto|h11|httptools]     HTTP protocol implementation.  [default:
                                  auto]
  --ws [auto|none|websockets|wsproto]
                                  WebSocket protocol implementation.
                                  [default: auto]
  --ws-max-size INTEGER           WebSocket max size message in bytes
                                  [default: 16777216]
  --ws-max-queue INTEGER          The maximum length of the WebSocket message
                                  queue.  [default: 32]
  --ws-ping-interval FLOAT        WebSocket ping interval in seconds.
                                  [default: 20.0]
  --ws-ping-timeout FLOAT         WebSocket ping timeout in seconds.
                                  [default: 20.0]
  --ws-per-message-deflate BOOLEAN
                                  WebSocket per-message-deflate compression
                                  [default: True]
  --lifespan [auto|on|off]        Lifespan implementation.  [default: auto]
  --interface [auto|asgi3|asgi2|wsgi]
                                  Select ASGI3, ASGI2, or WSGI as the
                                  application interface.  [default: auto]
  --env-file PATH                 Environment configuration file.
  --log-config PATH               Logging configuration file. Supported
                                  formats:.ini,.json,.yaml.
  --log-level [critical|error|warning|info|debug|trace]
  --access-log / --no-access-log  Enable/Disable access log.
  --use-colors / --no-use-colors  Enable/Disable colorized logging.
  --proxy-headers / --no-proxy-headers
                                  Enable/Disable X-Forwarded-Proto,
                                  X-Forwarded-For, X-Forwarded-Port to
                                  populate remote address info.
  --server-header / --no-server-header
                                  Enable/Disable default Server header.
  --date-header / --no-date-header
                                  Enable/Disable default Date header.
  --forwarded-allow-ips TEXT      Comma separated list of IPs to trust with
                                  proxy headers. Defaults to the
                                  $FORWARDED_ALLOW_IPS environment variable if
                                  available, or '127.0.0.1'.
  --root-path TEXT                Set the ASGI 'root_path' for applications
                                  submounted below a given URL path.
  --limit-concurrency INTEGER     Maximum number of concurrent connections or
                                  tasks to allow, before issuing HTTP 503
                                  responses.
  --backlog INTEGER               Maximum number of connections to hold in
                                  backlog
  --limit-max-requests INTEGER    Maximum number of requests to service before
                                  terminating the process.
  --timeout-keep-alive INTEGER    Close Keep-Alive connections if no new data
                                  is received within this timeout.  [default:
                                  5]
  --timeout-graceful-shutdown INTEGER
                                  Maximum number of seconds to wait for
                                  graceful shutdown.
  --ssl-keyfile TEXT              SSL key file
  --ssl-certfile TEXT             SSL certificate file
  --ssl-keyfile-password TEXT     SSL keyfile password
  --ssl-version INTEGER           SSL version to use (see stdlib ssl module's)
                                  [default: 17]
  --ssl-cert-reqs INTEGER         Whether client certificate is required (see
                                  stdlib ssl module's)  [default: 0]
  --ssl-ca-certs TEXT             CA certificates file
  --ssl-ciphers TEXT              Ciphers to use (see stdlib ssl module's)
                                  [default: TLSv1]
  --header TEXT                   Specify custom default HTTP response headers
                                  as a Name:Value pair
  --version                       Display the uvicorn version and exit.
  --app-dir TEXT                  Look for APP in the specified directory, by
                                  adding this to the PYTHONPATH. Defaults to
                                  the current working directory.
  --h11-max-incomplete-event-size INTEGER
                                  For h11, the maximum number of bytes to
                                  buffer of an incomplete event.
  --factory                       Treat APP as an application factory, i.e. a
                                  () -> <ASGI app> callable.
  --help                          Show this message and exit.
➜  ~
```

## 設定とサーバーインスタンス
設定とサーバーのライフサイクルをより細かく制御するには、`uvicorn.Config`と`uvicorn.Server`を使います。
```python
import uvicorn

async def app(scope, receive, send):
   ...

if __name__ == "__main__":
    config = uvicorn.Config("main:app", port=5000, log_level="info")
    server = uvicorn.Server(config)
    server.run()
```
既に実行中の非同期環境からUvicornを起動したい場合は、`uvicorn.Server.serve()`を使います。
```python
import asyncio
import uvicorn

async def app(scope, receive, send):
   ...

async def main():
    config = uvicorn.Config("main:app", port=5000, log_level="info")
    server = uvicorn.Server(config)
    await server.serve()

if __name__ == "__main__":
    asyncio.run(main())
```

## Uvicornを使ったFastAPIプロジェクトの起動
```python
import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app=app)
```

# FastAPIがUvicornを使う理由は？
FastAPIは、現代的で高性能なWebフレームワークです。これは、Pythonの非同期プログラミング機能を使って、Webアプリケーションの性能を高めています。一方、Uvicornは、uvloopとhttptoolsで実装された高性能なASGIサーバーで、HTTPリクエストを非同期で処理することができます。FastAPIがUvicornをデフォルトのWebサーバーとして使うのは、Uvicornが非常に高速で、信頼性が高く、使いやすいからです。多数の同時接続を処理する際にも、安定して効率的に機能します。さらに、UvicornはWebSocketやHTTP/2などの新機能をサポートしており、FastAPIが提唱する現代的なWeb開発哲学と合致しています。したがって、FastAPIのWebサーバーとしてUvicornを使うのは、素晴らしい選択肢です。

### [Leapcell: ウェブホスティング、非同期タスク、Redis向け次世代サーバーレスプラットフォーム](https://leapcell.io/?lc_t=q_unvicorn)

[![barndpic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/a5c1223c-b81e-5c05-be9a-1edfc31c5e96.png)](https://leapcell.io/?lc_t=q_unvicorn)


最後に、FastAPIサービスをデプロイするのに最適なプラットフォーム、[Leapcell](https://leapcell.io/?lc_t=q_unvicorn)を紹介します。

[Leapcell](https://leapcell.io/?lc_t=q_unvicorn)には以下の特徴があります：
- **1. 多言語サポート**
JavaScript、Python、Go、またはRustで開発できます。

- **2. 無制限のプロジェクトを無料でデプロイ**
使用量に応じて支払えばよく、リクエストがなければ料金はかかりません。

- **3. 比類なきコスト効率**
使いた分だけ支払い、アイドル時の料金はかかりません。
例：25ドルで平均応答時間60msで694万件のリクエストをサポートします。

- **4. 簡素化された開発者体験**
直感的なUIで簡単にセットアップできます。
完全自動化されたCI/CDパイプラインとGitOps統合。
アクション可能な洞察のためのリアルタイムメトリクスとロギング。

- **5. 簡単なスケーラビリティと高性能**
自動スケーリングで高い同時性を容易に処理できます。
オペレーションオーバーヘッドはゼロ － 開発に集中できます。

[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/9cca08b7-c82f-5e1f-351d-1d7851c66964.png)](https://leapcell.io/?lc_t=q_unvicorn)


[Docsでもっと詳細を見る！](https://docs.leapcell.io/)

Leapcell Twitter: [https://x.com/LeapcellHQ](https://x.com/LeapcellHQ)