Falcon Web Frameworkを使ったPythonでのREST APIの開発とデプロイメント


今回の記事では、PyPy上でFalconのウェブフレームワークを使ってPythonでREST APIを開発・デプロイしていきます。

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

はじめに:Falconとは何か?

Falconは、スピーディーなWeb APIやアプリのバックエンドを構築するための最小限のWSGIライブラリです。HTTP APIの構築に関しては、他のフレームワークは膨大な量の依存関係や不要な抽象化に悩まされています。Falconは、HTTPとRESTアーキテクチャスタイルを採用したすっきりとしたデザインです。

あなたの頭に浮かぶ最初のことは、おそらく「なぜFalconを使うべきなのか?」ということでしょう。さて、Falconはflask、Django、Bottle、web.pyのような他のpythonのフレームワークと同じくらいパワフルで、高速で、拡張性があり、信頼性が高く、RESTfulなスタイルを奨励しています。ベンチマークによると、FalconはflaskやDjangoよりもpypy上で21倍も高速です。LinkedIn、Leadpages、Wargaming、およびRackspaceのような組織は、すでにアプリケーションにFalconを使用しています。

Alibaba Cloud ECSへのFalconのインストール

Alibaba Elastic Compute Service (ECS)へのFalconのインストールは、PCへのインストールと同じくらい簡単です。

Alibaba ECS上でUbuntu 16.04をプロビジョニングする

このチュートリアルを参考にして、Alibaba_Cloud上のUbuntu Serverをセットアップしてサーバーをプロビジョニングする手順を参考にしてください。

Ubuntu 16.04にpypy3と依存関係をインストールする

コードを速く動かしたいなら、PyPy を使うべきです。

1、スピード:PythonのプログラムはPyPyの方が高速に動作することが多いです。(JITコンパイラとは何ですか?)
2、メモリ使用量: メモリを大量に消費するPythonプログラム(数百MB以上)はCPythonよりも少ないスペースで動作します。
3、互換性:PyPyは既存のPythonコードと非常に互換性があります。cffiをサポートしており、twistedやDjangoのような一般的なPythonライブラリを動かすことができます。
5、スタックレス: PyPyはデフォルトでスタックレスモードをサポートしています。

$ sudo apt-get install python3-dev
$ wget https://bitbucket.org/pypy/pypy/downloads/pypy3-v6.0.0-linux64.tar.bz2
$ tar -xvf pypy3-v6.0.0-linux64.tar.bz2  -C /opt
$ sudo ln -s /opt/pypy3-v6.0.0-linux64/bin/pypy3 /usr/local/bin/pypy3
$ sudo chown -R <youruser>:<yourgroup> pypy3-v6.0.0-linux64/
$ pypy3
Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:10:04)
[PyPy 6.0.0 with GCC 6.2.0 20160901] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>> import this

pypy3をインストールしたら、pypy3のpipと互換性のあるpythonの依存関係をインストールしなければなりません。

$ wget https://bootstrap.pypa.io/get-pip.py
$ pypy3 get-pip.py   # pypy3 -m ensurepip   
$ sudo apt-get install python3-pip
$ pip3 install virtualenvwrapper

virtualenvwrapper をインストールします。

.bashrc または .profile に以下の行を追加します。

export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/Devel
source /usr/local/bin/virtualenvwrapper.sh

pythonの依存関係はvirtualenvでインストールした方が良いです。

$ mkvirtualenv -p /usr/local/bin/pypy3 falconenv
(falconenv):~$ pypy3 -m pip install falcon mongoengine

Ubuntu 16.04にMongodbをインストールする

MongoDBはオープンソースのドキュメントデータベースで、高性能、高可用性、自動スケーリングを実現しています。

$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
$ echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
$ sudo apt-get update
$ sudo apt-get install -y mongodb-org 
$ sudo systemctl start mongod  
$ sudo systemctl status mongod
# This command will start mongod. Other options are stop | restart | status. 
? mongodb.service - High-performance, schema-free document-oriented database
   Loaded: loaded (/etc/systemd/system/mongodb.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2016-04-25 14:57:20 EDT; 1min 30s ago
 Main PID: 4093 (mongod)
    Tasks: 16 (limit: 512)
   Memory: 47.1M
      CPU: 1.224s
   CGroup: /system.slice/mongodb.service
           ??4093 /usr/bin/mongod --quiet --config /etc/mongod.conf

REST APIの構築

ユーザーがbookを作成したり、bookを更新したり、MongoDBからidでbookを取得したりするbookプロジェクトを作成します。

Falconアプリのディレクトリ構造

book_project/book/には以下のpythonファイルがあります。

models : modelsではmongoengineのORMを使用しています。mongoengineのDocumentクラスを継承したクラスは、MongoDBデータベースに相当するコレクションを記述しています。ここでは、フィールド名、ISBN、著者名を持つリソースBookを作成しました。リソースのオブジェクトごとにユニークなIDを自動生成してくれます。

from mongoengine import StringField, IntField, Document

class Book(Document):
    name = StringField()
    isbn = IntField()
    author= StringField()

api : bookリソースには、on_get, on_post という enpoint メソッドがあります。各メソッドの使い方は以下のコードコメントに記載されています。

api.pyのソースコードは以下の通りです。

import falcon, json
from .models import Book

class BookResource(object):
    def on_get(self,req,resp,book_id):
        '''
        :param req: A request object
        :param resp: A response object
        :param book_id: book_id received in http path to query book object
        :return:
        '''
        book_obj= Book.objects.get(id=book_id)
        #Query book collection to get a record with id = book_id
        resp.body = json.dumps({'author':book_obj.author,'name':book_obj.name,'isbn':book_obj.isbn})
        #It will set response body as a json object of book fields.
        resp.status = falcon.HTTP_200
        #Finally return 200 response on success

    def on_post(self,req,resp):
        '''
         This method will recevie the book data in request body in order to store it in database
        :param req: It contains json of book's author, name and isbn.
        :param resp:
        :return:
        '''
        book_data = req.media
        #req.media will deserialize json object
        book_obj=Book.objects.create(**book_data)
        #passing book_data to create method. It will create a database document in book collection.
        resp.body = json.dumps({'book_id':str(book_obj.id),'message':'book succesfully created'})
        resp.status=falcon.HTTP_200

指定されたIDの本を取得するためのGETリクエストのエンドポイント:http://<host>:<port>/<book_id>

データを持つ本を作成するためのPOSTリクエストのエンドポイント:http://<host>:<port>/<book_id>

{"author":<author_name>,"name":<book_name>, "isbn":<isbn>}

app:これは HTTP リクエストのエントリーポイントで、HTTP パスやその他の設定に基づいたリソースへのルーティングが含まれています。

import falcon
from mongoengine import connect
from .api import BookResource

connect('bookdb', host='127.0.0.1', port=27017)
app = application = falcon.API()
books = BookResource()
app.add_route('/book/{book_id}', books)
app.add_route('/books/', books)

connect(, host=, port=), この行は、与えられた資格情報を使って自動的にmongodbデータベースへの接続を作成します。この接続は、アプリのスコープ全体でグローバルに使用されます。

app = application = falcon.API(), この行は、gunicorn (ウェブアプリケーションサーバ)が自動検索してwsgiアプリとして動作するアプリケーションインスタンスを作成します。

books = BookResource(), この行は、リソースのインスタンスを作成します。

app.add_route('/book/{book_id}', books)とapp.add_route('/books/', books)は、httpパスとメソッドをリソースのそれぞれのメソッドにルーティングします。

GunicornとNginxでWebアプリをデプロイする

Gunicorn

Gunicorn 'Green Unicorn'は、Python WSGI HTTP Server for UNIXです。プリフォークワーカーモデルです。Gunicornサーバは様々なWebフレームワークと幅広く互換性があり、シンプルに実装されており、サーバリソースが軽く、かなり高速です。

簡単に言えば、gunicornはHTTPリクエストを理解し、HTTPバイトをPythonオブジェクトに変換することで、Pythonアプリケーションでも理解できるようにします。

以下のコマンドを使ってubuntuマシン上でgunicornを実行してください。

(falconenv):~$ pypy3 -m pip install gunicorn
(falconenv):~/book_project$  gunicorn --reload book.app --bind 127.0.0.1:9000

Nginx

NGINXは、ウェブサーバ、リバースプロキシ、キャッシング、ロードバランシング、メディアストリーミングなどのためのオープンソースソフトウェアです。NGINXは、最大のパフォーマンスと安定性を目指して設計されたWebサーバーとしてスタートしました。HTTPサーバー機能に加えて、NGINXは電子メール(IMAP、POP3、SMTP)のプロキシサーバーとして、またHTTP、TCP、UDPサーバーのリバースプロキシとロードバランサーとしても機能します。

簡単に説明すると、nginxはHTTPリクエストバイトを受信し、HTTPレスポンスバイトをクライアントに送信するソフトウェアです。NginxはHTTPリクエストバイトをpythonアプリケーションサーバ(gunicorn)に転送する役割を担っています。

$ sudo apt-get install nginx

sudo vim falcon_nginx.conf

upstream falcon_gunicorn {
    server 127.0.0.1:9000;
}

server {
    listen  80;
    server_name <ALIBABA ECS instance public ip>;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location / {
            proxy_pass         http://falcon_gunicorn;
            proxy_redirect     off;
            proxy_set_header   Host $host;
    }
}
$ sudo cp falcon_nginx.conf /etc/nginx/sites-enabled/nginx.conf
$ sudo service nginx restart

概要

REST APIを開発して迅速にデプロイするためには、Falconが最良の選択肢の一つであることが証明されています。Alibaba CloudのElastic Compute Service (ECS) Ubuntu Serverにpypy3, falcon, MongoDB, gunicorn, Nginxとその他の依存関係をインストールする必要があります。falconのAPI構文は完全にRESTアーキテクチャに基づいており、適切なルーティング、モデル構造、およびビューを使用して非常に簡単に開発することができます。Falconはスケーラブルなソリューションであり、gunicorn, uwsgi, waitressのようなWSGIサーバ上に簡単にデプロイすることができます。gunicornサーバの上にNginxを追加することで、マイクロサービスのスケーラビリティ、分散性、安全性を向上させることができます。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ