勉強として、FastAPIを使用して、実際にAPIを作成し、起動しようと思います。目標としては、本番運用用の設定まで行いたいと思います。
FastAPIとは
FastAPIとは、Pythonによる、Webアプリケーションフレームワークです。以下の特徴があるそうです。
- 高速
- コーディング高速化
- バグの少なさ
- 直感的
- 簡単
- 重複のなさ
- 堅牢
- 標準準拠
特に、標準準拠的に、OpenAPIによるドキュメントを自動生成してくれるのが良い感じに見えました。
どんなAPIを作るの?
あるキーワードAを入力したら、もともと持っているキーワードBと組み合わせて、googleで検索できるURL(クエリURL)を返すAPIを作ろうと思います。
例えば、”食べる” というAPIの入力があるとします。
このAPIの内部ではキーワードとして”ラーメン”(=R)を持っていたとします。
その場合、例えば、このAPIのURL「/queryURL/R?q=食べる」にアクセスすると、APIはgoogle検索に”ラーメン 食べる”としたときのURLを返却します。
具体的には以下になります。
{ queryURL: 'https://www.google.com/search?q=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3&oq=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3' }
環境
環境は以下を使用します。
- Python: 3.6.9
- pipenv: 2020.06
- FastAPI: 0.59.0
- nginx: 1.18.0
- gunicorn: 20.0.4
- systemd
構成は以下のようになります。
nginx -> (127.0.0.1:28168) -> gunicorn -> FastAPI(pipenv) -> app.py (systemd)
開発環境設定
最初は、以下で環境を設定しました。
$ pipenv install fastapi[all] uvicorn gunicorn sqlalchemy
sqlalchemy は今は使用しませんが、後で使用する予定です。
あと、Python3のバージョンによっては、dataclassesを入れる必要があるかもしれません。
ソース
ソースは以下に置いておきました。
https://github.com/KenichiTanino/query_url_web_api.git
テスト用起動方法
テスト用にAPIを起動するには以下にします。api:appの”api”はモジュールを指します。つまりapp/api.pyになっていたら”app.api”にします。”:app”は属性を指します。属性というのは、実際のところ、FastAPIを指す変数名です。
$ pipenv run uvicorn api:app --reload --host 0.0.0.0
Swagger UI
目玉のOpenAPIによるドキュメントです。
以下にアクセスすると、
http://192.168.132.128:8000/docs
以下のように表示します。以下を自動生成してくれるのはなかなか便利だと思いました。
設定方法
リポジトリのファイルから、本番まで設定する想定で、設定方法を書いていきます。
手順としては以下の流れになります。
- インストール(git cloneでファイル配置)
- systemd登録/起動(gunicorn起動)
- nginx登録
インストール
リポジトリを/usr/local/queryurlにcloneしたとします。
以下のようにインストールします。
### ユーザ作成(www-data:www-data) $ sudo useradd -U -M -s /sbin/nologin www-data $ cd /usr/local $ sudo git clone https://github.com/KenichiTanino/query_url_web_api.git queryurl $ cd queryurl $ export PIPENV_VENV_IN_PROJECT=true $ /usr/local/bin/pipenv sync $ mkdir log $ sudo chown -R www-data:www-data /usr/local/queryurl
systemd(gunicorn)
gunicornを起動するsystemdユニットファイルは以下の通りです。
[Unit] Description = queryURL service ( gunicorn - fastapi ) Requires=queryurl.socket After = network-online.target ConditionPathExists = /usr/local/queryurl [Service] User=www-data Group=www-data WorkingDirectory = /usr/local/queryurl ExecStart = /usr/local/bin/pipenv run gunicorn --config /usr/local/queryurl/gunicorn.py api:app ExecReload = /bin/kill -s HUP $MAINPID ExecStop = /bin/kill -s TERM $MAINPID PrivateTmp = true [Install] WantedBy = multi-user.target
難しい所はありませんが、ExecStartは/usr/local/bin/pipenvを前提としています。環境に合わせて変更してください。
etc/gnucorn.pyは以下にしています。
import multiprocessing import os name = "gunicorn" accesslog = "/usr/local/queryurl/log/log_access.txt" errorlog = "/usr/local/queryurl/log/log_error.txt" bind = "127.0.0.1:28168" worker_class = "uvicorn.workers.UvicornWorker" workers = multiprocessing.cpu_count() * 2 + 1 worker_connections = 1024 backlog = 2048 max_requests = 5120 timeout = 360 keepalive = 2 debug = os.environ.get("DEBUG", "false") == "true" reload = debug preload_app = False daemon = False
systemd 登録/起動
以下でunitファイルを有効化し、永続的に起動できるようにします。
$ sudo systemctl enable /usr/local/queryurl/etc/queryurl.service $ sudo systemctl daemon-reload $ sudo systemctl start queryurl.service
nginx登録
nginx.conf(部分)は以下のようにします。
location /query_url { proxy_pass http://127.0.0.1:28168; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Real-IP $remote_addr; }
動作確認
動作しているかどうかは、以下で確認します。
$ curl -G "https://www.tech-law-pyscho.info/query_url/query/G" --data-urlencode "q=テスト" {"queryURL":"https://www.google.com/search?q=%E8%A1%8C%E6%94%BF%E6%9B%B8%E5%A3%AB+%E3%83%86%E3%82%B9%E3%83%88"}
おわりに
ここではまずnginxに登録してアクセスできるところまで設定しました。
次は、このAPIを使用して、Webアプリケーションのプロトタイプを作ってみようと思います。