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

gRPC in Cookpad

Yuta Iwama
November 28, 2018

gRPC in Cookpad

Cookpad Tech Kitchen #20 クックパッドのマイクロサービスプラットフォーム現状 https://cookpad.connpass.com/event/106913/

Yuta Iwama

November 28, 2018
Tweet

More Decks by Yuta Iwama

Other Decks in Technology

Transcript

  1. gRPC in Cookpad
    Cookpad Tech Kitchen #20

    View Slide

  2. 自己紹介
    ● 岩間雄太
    ● @ganmacs
    ● 技術部開発基盤グループ
    ○ 2017年度新卒入社

    View Slide

  3. 目次
    ● これまでの Cookpad のサービス間通信
    ● Cookpad での gRPC 運用
    ● Ruby で gRPC

    View Slide

  4. gRPC 導入経緯

    View Slide

  5. これまでの Cookpad
    ● Cookpad ではマイクロサービスを推進してきた
    ● 社内では Garage, GarageClient で API 共通化
    ● Autodoc でドキュメンテーション
    ● 参考
    ○ https://speakerdeck.com/eagletmt/web-application-development-in-cookpad-2017
    ○ https://speakerdeck.com/adorechic/how-cookpad-shifts-to-microservices

    View Slide

  6. gRPC 導入理由
    ● IDL とスキーマがほしい
    ○ 各フィールドの型を定義、参照したい
    ● REST なエンドポイントへのマッピングが困難
    ○ サービス間通信は REST よりも RPC のほうが適している事が多い
    ● 多言語化
    ○ Ruby 以外の言語の使用実績の増加

    View Slide

  7. gRPC
    ● オープンソースの RPC フレームワーク
    ● IDL として Protocol Buffers が使える
    ● Protocol Buffers で定義を書くとクライアント、サーバのコードを生成
    ● 様々な言語で実装が存在する
    ● https://grpc.io

    View Slide

  8. gRPC(2)
    ● HTTP2 上で動作
    ○ https://github.com/grpc/grpc/blob/v1.17.0-pre2/doc/PROTOCOL-HTTP2.md
    ● 4種類の RPC
    ○ Unary RPC
    ○ Server streaming RPC
    ○ Client streaming RPC
    ○ Bidirectional streaming RPC
    ● Interceptor でログ、認証、エラー処理など

    View Slide

  9. 定義(Protocol Buffers)の例
    https://grpc.io/docs/guides/concepts.html#service-definition

    View Slide

  10. gRPC の運用

    View Slide

  11. Cookpad の gRPC アプリケーション動作環境
    ● 基本的に hako 上で動作
    ● cookpad.com でも使用
    ● cookpad/sds + Envoy を使用して Client side Loadbalancing
    ○ https://blog.envoyproxy.io/service-mesh-and-cookpad-ba4d5d915dbd
    ○ Envoy の load_balancing_weight を使って Slow Start をサポート
    ● Envoy 経由でリクエストをうける
    ● 開発環境から staging 環境へのアクセスも許可

    View Slide

  12. Cookpad の gRPC 動作環境(サービスイン)
    cookpad/sds
    registrator コンテナが service 起動時に
    front-envoy のエンドポイントを登録 (e.g. 10.0.0.1:77777)
    app
    Service A
    envoy
    front-envoy
    サービス名 エンドポイント weight
    Service B 10.0.0.1:6789 100
    Service C 10.0.0.1:7896 100
    Service A 10.0.0.1:7777 100
    registrator

    View Slide

  13. Cookpad の gRPC 動作環境(Slow Start)
    cookpad/sds
    app
    Service A
    envoy
    front-envoy
    サービス名 エンドポイント weight
    Service B 10.0.0.1:6789 100
    Service C 10.0.0.1:7896 100
    Service A 10.0.0.1:7777 2
    registrator コンテナが weight を徐々に大きくしていく
    registrator

    View Slide

  14. Cookpad の gRPC 動作環境(Running)
    cookpad/sds
    1. 定期的に registrator コンテナが app に health check
    2. health check がとおったら sds に再登録
    app
    Service A
    envoy
    front-envoy
    registrator
    サービス名 エンドポイント weight
    Service B 10.0.0.1:6789 100
    Service C 10.0.0.1:7896 100
    Service A 10.0.0.1:7777 100

    View Slide

  15. app
    Service A
    envoy
    front-envoy
    Cookpad の gRPC 動作環境(通信)
    envoy が定期的に sds を見に
    行って リクエスト先を見つける
    app
    Service B
    envoy
    front-envoy
    cookpad/sds

    View Slide

  16. Cookpad の gRPC 動作環境(サービスアウト)
    cookpad/sds
    registrator コンテナが service 終了時に
    front-envoy のエンドポイントを削除
    app
    Service A
    envoy
    front-envoy
    サービス名 エンドポイント weight
    Service B 10.0.0.1:6789 100
    Service C 10.0.0.1:7896 100
    registrator

    View Slide

  17. サービス定義(Protocol Buffers) の管理
    ● 一つのリポジトリで管理
    ● サービスごとにディレクトリを切る運用
    ○ service A のサービス定義だったら service_a/ 以下に定義を記述
    ● 使用したいアプリケーションは git submodule で使用
    ● ckaznocha/protoc-gen-lint による Lint
    ● pseudomuto/protoc-gen-doc を使って自動でドキュメント生成
    ○ hako-console にドキュメントへのリンクを配置
    Web アプリケーションを把握するためのコンソール
    , https://techlife.cookpad.com/entry/2018/04/02/140846

    View Slide

  18. メトリクス
    ● 前述の2つの Envoy コンテナでメトリクスをとっている
    ○ Envoy Stats https://blog.envoyproxy.io/envoy-stats-b65c7f363342
    ○ アクセスログ
    ● メトリクス、ログ情報を Prometheus に入れており grafana でみれる
    ● アクセスログに対して google/mtail を使用して Prometheus から読めるように
    している
    ● hako-console に grafana へのリンクを配置

    View Slide

  19. Prometheus w/ envoy アクセスログ
    ● サービス開発者が(ほぼ)何もしなくても動作
    ● front-envoy コンテナが mtail コンテナをマウント
    ○ mtail が envoy のアクセスログ Prometheus 用に出力
    ○ https://github.com/ganmacs/prom-mtail-test
    ● ECS 上のサービスディスカバリーサービス(sds)を作成
    ○ Prometheus が sds をもとに mtail コンテナを見つける
    app
    Service A
    envoy
    front-envoy
    mtail

    View Slide

  20. Image
    Area

    View Slide

  21. Image
    Area

    View Slide

  22. Ruby (on Rails) で gRPC

    View Slide

  23. grpc gem
    ● C と C++ で作られたものを Ruby の拡張ライブラリとして使用
    ○ grpc/grpc は C++, Python, Ruby, Objective-C, PHP, C# をサポートしている
    ● grpc gem はマルチスレッド (シングルプロセス)
    ○ Ruby には GIL があるので並列に動かない
    ○ マルチプロセス化は直近のロードマップになさそう
    ■ https://github.com/grpc/grpc/issues/15334
    ● https://rubygems.org/gems/grpc/

    View Slide

  24. grpc gem(2)
    ● grpc-tool gem でサーバ、クライアントのコードを生成
    ● ユーザはサーバを実装するだけ
    https://grpc.io/docs/quickstart/ruby.html

    View Slide

  25. Ruby で gRPC in Cookpad
    ● 公式の gRPC 実装を使用
    ○ bigcommerce/gruf みたいなフレームワークは使ってない
    ● アプリケーションレイヤーでアクセスログが取れないので Interceptor を自作
    ● シグナルを受けると死んでしまうので起動/停止を行うライブラリを自作
    ○ https://github.com/grpc/grpc/issues/14043
    ● その他様々な Interceptor を自作
    ○ 例外処理
    ○ New Relic などのツールもサポートされてないので interceptor として自作
    ○ Go の grpc-ecosystem/go-grpc-middleware みたいなもの

    View Slide

  26. Ruby on Rails で gRPC in Cookpad
    ● app/ 以下にサービス定義を配置
    ● lib/ 以下に自動生成コードを配置
    ● config/initializers に gRPC の設定を配置
    ○ Listen ポート、Interceptor の設定など
    ● 起動には rails runner を使用している
    ○ e.g. $ bundle exec rails runner run_grpc_server.rb
    ○ 最初は rake task を作成していたが eager_load 周りでハマりどころが多い
    ○ https://github.com/rails/rails/blob/v5.2.1/railties/lib/rails/application.rb#L518
    ● ActiveRecord の connection pool との相性

    View Slide

  27. grpc gem と ActiveRecord
    ● grpc gem はマルチスレッド(シングルプロセス)
    ● interceptor で AR の connection pool から pickup して終わったら返す
    ○ 並行数の上限が connection pool 数になる

    View Slide

  28. grpc gem の問題
    ● CPU を使い切れない
    ○ オートスケールが他のアプリに比べてうまくいかない
    ○ スケールアウトするより先に gRPC の ResourceExhausted エラーが発生する
    ● Graceful Shutdown がない
    ○ 急にサーバが死ぬので Envoy を使ってサービスアウトしてからサービスを止めている
    ○ 当然ストリーム系の Graceful shutdown もない
    ● その他いろいろ

    View Slide

  29. griffin
    ● 自作の gRPC ライブラリ
    ● https://github.com/ganmacs/griffin
    ○ nghttp2 を使用して作成
    ● grpc gem との互換性を気にした
    ○ Protocol Buffers から生成されるコードをそのまま使用できる
    ○ grpc gem が改善されたら戻れるように
    ● 社内のアプリで動き出している
    ○ 現在移行中
    ● unary RPC のベンチマークでは griffin のほうが早い
    ○ https://gist.github.com/ganmacs/5c7857b03ee80cf78e638f2a2a74fe01

    View Slide

  30. まとめ
    ● Cookpad ではサービス間通信に gRPC を使うようになってきた
    ● Envoy を活用して gRPC サービスの基盤を構成している
    ● Rails と gRPC を組み合わせて使用している
    ● 新しい gRPC gem (griffin) を作って検証中

    View Slide

  31. 今後
    ● Envoy の機能を使ったカナリアリリース
    ● griffin のプロダクション導入
    ● grpc-gateway の導入

    View Slide