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-requirements
とserverless-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
ファイルを作って、スキーマを定義していきます。
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で実現できるようにしてみました。
ありがとうございました。