Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python用のマイクロサービスフレームワークを探す旅 / A journey to find a microservices framework for Python

79a92313bba008d66f30b226ee618fa7?s=47 yukinagae
September 29, 2019

Python用のマイクロサービスフレームワークを探す旅 / A journey to find a microservices framework for Python

golangのGoa (https://goa.design/) のようなマイクロフレームワークに似たようなのをPythonでもほしいので、Nameko (https://www.nameko.io/) の拡張を作ってみました(`・ω・´)
repository: https://github.com/yukinagae/nameko-design

79a92313bba008d66f30b226ee618fa7?s=128

yukinagae

September 29, 2019
Tweet

Transcript

  1. Python用のマイクロサービスフレームワーク を探す旅 @yukinagae

  2. 目的 golangの Goa のようなマイクロフレームワークに似たようなのを Pythonでもほしい 2

  3. 背景 webアプリではないのでマイクロなフレームワークを使っていき 言語はGo/Pythonで絞りたい 学習コストを減らす 検証やハマることを減らしたい キャッチアップしやすい 機械学習システムは似たような構成になりやすい バッチで学習しDBにデータをストア: Python DBからAPIでデータをサービングする:

    Go or Python 3
  4. Goaとは? Goa is a Go framework for writing microservices that

    promotesbest practice by providing a single source of truth from which server code, client code, and documentation is derived. マイクロサービス用のフレームワーク コードからサーバサイドのスケルトンやドキュメント(swagger) を生成できる 4
  5. こんな感じのAPIデザインをgoで記述する var _ = Service("calc", func() { Method("add", func() {

    Payload(func() { Field(1, "a", Int, "Left operand") Field(2, "b", Int, "Right operand") Required("a", "b") }) Result(Int) HTTP(func() { GET("/add/{a}/{b}") }) GRPC(func() { }) }) }) 5
  6. ポチッとな(`・ω・´) goa gen calc/design 6

  7. 省略しているがいろいろ生成してくれる gen ├── calc │ └── *.go ├── grpc │

    ├── calc │ │ ├── client │ │ │ └── *.go │ │ ├── pb │ │ │ ├── calc.pb.go │ │ │ └── calc.proto # <- protobuffer │ │ └── server │ │ └── *.go │ └── cli │ └── calc │ └── cli.go └── http ├── calc ├── cli ├── openapi.json # <- swagger ファイル └── openapi.yaml # <- swagger ファイル 7
  8. ロジックを実装 あとは生成されたうちの2~3ファイルにロジックを実装するだけ。 生成された空メソッド 実装する func (s *calcsrvc) Add(ctx context.Context, p

    *calc.AddPayload) return 0, nil } func (s *calcsrvc) Add(ctx context.Context, p *calc.AddPayload) return p.A + p.B, nil } 8
  9. Goaのいいところ スキーマファースト スキーマ作成 → 開発というワークフローができる http + gRPCの両方使える 9

  10. Pythonでも似たようなのほしいのでは (`・ω・´) 10

  11. 11

  12. Nameko(なめこ) A microservice framework for Python. マイクロサービス用のpythonフレームワーク ビジネスロジックの実装に集中できる 拡張いろいろできる(どのプロトコルやDBにもサービス拡張でき る)

    名前がよい 12
  13. Nameko(なめこ)の由来 Nameko takes its name from the Japanese mushroom, which

    grows in clusters. クラスタ(?)に成長する日本のキノコである "なめこ" が由来 13
  14. HTTPの場合 アノテーションで @http を指定 import json from nameko.web.handlers import http

    class HttpService: name = "http_service" @http('GET', '/get/<int:value>') def get_method(self, request, value): return json.dumps({'value': value}) 14
  15. gRPCの場合 アノテーションで @grpc を指定 grpc = Grpc.implementing(exampleStub) class GrpcService: name

    = "grpc_service" @grpc def stream_unary(self, request, context): messages = [] for req in request: message = req.value * (req.multiplier or 1) messages.append(message) return ExampleReply(message=",".join(messages)) ※ namekoのコアにはgRPCが入っていないが nameko‑grpc という拡張を 使用可能 15
  16. 使い方 HTTPサービスを起動 nameko run http_service curlで叩いてみる(`・ω・´) $ curl localhost:8000/get/123 {'value':

    123} ためしにサンプルプロジェクト作成した。 ただDBからselectするだけ(/・ω・)/ yukinagae/nameko‑api‑template 16
  17. 軽く触ってみての感想 ざっと調べた中では一番イメージに近いPythonライブラリ コーディング量も少なくて済みそう exampleレポジトリあるので結構参考になりそう DB周りのやり方はまだよくわかってない sqlalchemyは対応してるのを軽くサンプルで動作確認した swaggerのコード生成はないので作る必要あり 17

  18. namekoの足りないところ スキーマファーストではない ふつうにエントリーポイントを作成する感じ http or gRPCはそれぞれ別に作らないといけない swaggerのコード生成 18

  19. 結論 Flaskでよくない? 19

  20. Flaskから置き換えるほどか?? 実績 + ノウハウ + ドキュメントが多い namekoを新しく使うメリットがどこまであるか? 正直今後の新サービスは9割方go(Goa)でいけるのでは? 20

  21. ただやはり諦めきれない...... namekoにもいいところある(`・ω・´) Flaskよりミニマム API部分はselectしたいだけならばこれくらいで十分 gRPCのエントリーポイントをアノテーションで記述できる 可読性高いのでは 21

  22. これを改善すればよいのでは? スキーマからコード生成 swagger生成 22

  23. スキーマからコード生成だけやってみる 方法案 × yamlから生成 × swaggerから生成 ◦ PythonでDSLっぽくやる ← 今回はこの方法(`・ω・´)

    ※ テンプレートエンジンは Jinja2 を使用 23
  24. 作ってみた(`・ω・´) yukinagae/nameko‑design 24

  25. 端的に地獄......( ˘ω˘)スヤァ service = Service('http_service') \ .Title('This is a http

    service') \ .Method('liveness') \ .Description('liveness probe') \ .Result(str) \ .HTTP(GET, '/liveness') service.generate() # コード生成 25
  26. Pythonicに書けるようにしたつもり このPythonファイルをスキーマとする with Service('http_service'): Title('This is a http service') with

    Method('liveness'): Description('liveness probe') Result(str) HTTP(GET, '/liveness') with Method('readiness'): Description('readiness probe') Result(str) HTTP(GET, '/readiness') 26
  27. これを叩くだけ cd nameko-design poetry run python cli/main.py 27

  28. これを生成(`・ω・´) from nameko.web.handlers import http class HttpService: name = 'http

    service' @http('GET', '/liveness') def liveness(self, request) -> str: pass @http('GET', '/readiness') def readiness(self, request) -> str: pass 28
  29. まだTODOたくさんあるけれど Configure http url and port Add URL parameter and

    type Add payload (name, type, description, position etc) Add validation Add gRPC server Generate proto files Generate swagger json 29
  30. こんな感じでできたらよさそう(´∀` ) with Service('example_service'): Title('This is an example service') with

    Method('liveness'): Description('liveness probe') Result(str) HTTP(GET, '/liveness') with Method('add'): Description('a + b') with Payload(): Field(1, "a", int, "left operand") Field(2, "b", int, "right operand") Required("a", "b") Result(int) HTTP(GET, '/add/{a}/{b}') GRPC() 30
  31. おわり 31