LoginSignup
2
1

More than 3 years have passed since last update.

Serverless FrameworkでAPIに対してProtocol Bufferを適用して作ってみる。

Posted at

TL;DR

Serverless Frameworkでもう少しAPI周りをなんとか扱いたい気持ちがあり、Protocol Bufferでお試ししたことがあったのでそれを共有します。

Protocol Bufferとは

そんなに新しい技術ではないんですが、インタフェース記述言語(IDL)です。Googleにて開発され、元はXMLよりも高速になるようデザインされたようです。
よくProtobufと略して記載されていたりします。
Protocol Bufferに関してはこちらの記事でよくわかりやすくサマらているのでご参考までに。
https://qiita.com/yugui/items/160737021d25d761b353

なぜServerless FrameworkにProtocol Bufferを使う?

もともとServerless Frameworkを主体にサービスを構築して管理していたため、クライアント側がマルチに存在する場合に使用を共有できるようにしたいのが最初のモチベーションで、同じAPIをWeb,Native Appからアクセスすることが予想されるサービスや、センサーデータをまとめて送るにしても、通信量が大きいのでなんとかデータを圧縮できないかと考えていたので、検討しました。

サンプル

やること

LambdaのコードをPythonを前提としてAPI Gateway + Lambdaだけのサービスをやってみました。
(Serverless Frameworkの基礎的な内容は割愛して、Protocol Bufferにまつわるところに絞った話を記載します。)

pluginの追加

pluginにserverless-python-requirementsserverless-apigw-binaryを追加します。

sls plugin install --name serverless-python-requirements
sls plugin install --name serverless-apigw-binary

serverless.ymlにも記載しておきます。

plugins:
  - serverless-python-requirements
  - serverless-apigw-binary
custom:
.
.
.
  apigwBinary:
    types:
      - 'application/x-protobuf'

requierement.txt

Lambda上でProtoBufを扱うので、protobufをimportする必要があります。
というわけで、requirement.txtを作ります。

protobuf==3.5.1
six==1.11.0

スキーマ作成

事前にprotobufをインストールしておきます。

git clone git://github.com/openx/python3-protobuf.git
cd python3-protobuf
./autogen.sh
./configure --prefix=$PREFIX # protobuf インストール先を指定
make
make check
sudo make install

cd python # Python バインディング
python setup.py build
python setup.py test
sudo python setup.py install

.protoファイルを作って、スキーマを定義していきます。

sample.proto
syntax = "proto3";

message Test {
  string test_id = 1;
  string hoge = 2;
}

スキーマを作成したら、ビルドです。


protoc -I=. --python_out=. sample.proto

コマンド実行後、sample_pb2.pyが生成されます。

Lambda Functionの実装

serverless.ymlに関数を記載します。

functions:
  Get:
    handler: handler.get
    package:
      include:
        sample_pb2.py
      exclude:
        - serverless.yml
    events:
      - http:
          path: get
          method: post
          cors: true
          private: true

handler.pyを用意して実際にProtoBufを組み込んでいきます。bodyにProtocolBufferでSerializeされたデータを与えて、LambdaにてParseすれば扱えるようになります。
Responseで返す場合はSerializeしてstringで扱ってあげればレスポンスできます。

mport json
import sample_pb2
import base64

def get(event, context):
    obj = sample_pb2.Test()
    obj.ParseFromString(base64.b64decode(event['body']))
    obj.test_id = 'bbb'
    response = {
        'statusCode': 200,
        'headers': { 
            "Access-Control-Allow-Origin": "*",
            'Content-Type': 'application/x-protobuf' 
        },
        'body': obj.SerializeToString().decode('utf-8'),
        'isBase64Encoded': True
    }

    return response

あれ?簡単?

Protocol Bufferの扱いに慣れるのには苦労しましたが、組み込み自体はさほど時間がかかりませんでした。どちらかというとスキーマ定義した後にPython上で扱う際Lambdaでデバッグする作業がなかなか苦痛でした。

まとめ・展望

  • ProtoBufをServerless Frameworkで実現できるようにしてみました。

ありがとうございました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1