IoTと業務システムをつなぐ
gRPC/RESTサービス
の開発と運用
藤田泰介 吉江智弘
1
登壇者紹介 藤田泰介
2017年11月
● MOVの前身のタクベルの開発に参画
● サーバエンジニアとしてAPI開発に従事
2019年4月
● MOV Centralサービスの立ち上げ
● サーバエンジニアチームのリーダー
MOVに参画する前はiOSアプリエンジニア
2
登壇者紹介 吉江智弘
• 2019年3月にDeNA入社
• サーバエンジニアとしてCentralサービス開発に参加
3
セッションで伝えたいこと
少人数チームにおいていかに
開発スピードを落とさず
新技術を取り入れて行くか
4
目次(前半)
●タクシー配車サービスMOVの紹介
●MOV Centralサービスの紹介
●Centralサービスの特徴
●Centralサービスが扱うデータ
●Centralサービスのアーキテクチャ
5
6
タクシー配車サービスMOVの紹介
MOVは日々進化しています
7
サービスインしてから
間もなく2年
8
MOVとは
9
• 乗りたいときに、スマホひとつで簡単にタク
シーが呼べるサービス
• ITのチカラでタクシー利用を進化させる
• 提供エリア
• 神奈川 東京 大阪 京都 兵庫など
• 車両台数
• 数万台規模に拡大中
MOVはアプリ配車だけじゃない
10
• 後部座席タブレット
• MOV CALL
• 決済機
MOVの全体像
11
MOVのリアルタイム車両情報を
電話配車に活かして
事業者様のタクシー配車を最大化したい
12
そんな中、生まれたMOVの新サービスが
Centralサービス
13
14
MOV Centralサービスの紹介
MOVアプリ配車と電話配車システムの連携
MOVの新サービス、Centralサービス
15
• タクシー事業者様の無線配車システムとMOV
アプリ配車サービスを連携させる
• 事業者様は既設無線配車システムと同等の機
能をMOV乗務員タブレットで利用可能にする
• MOVの車両ステータス情報を事業者様配車シ
ステムから利用できるようにする
Centralサービスのイメージ
16
従来の無線配車システムはMOVと連携することにより電話配車に専念する
Centralサービスの導入メリット
17
• MOV・無線配車システムそれぞれで管理して
いた車両ステータス情報を一元化できる
• 無線が廃止され車内の操作機器が1つにまと
まるので乗務員様の車内業務がシンプルにな
る
• 1つの端末で配車室からの配車受付、アプリ
からの配車受付が可能になる
• システム導入コストの削減とアプリ配車によ
る売上アップを見込める
Centralサービスの位置づけ
18
アプリ配車と電話配車を連携して
タクシー事業者様の
配車効率を最大化する
19
Centralサービスの目指すもの
Centralサービスの開発
20
• 2019年4月から開発開始
• 2019年11月に試験稼働(2020/2から本稼働)
• チーム構成
• PdM、デザイナ
• アプリエンジニア
• サーバエンジニア
• サーバエンジニアは4名
• Kubernetes未経験者のみ
• gRPCを使ったAPI開発も全員未経験
• うち2名は1,2年前までアプリエンジニア
21
Centralサービスの特徴
最少人数で最大の効果を生み出す戦略
Centralサービスの特徴1
• タクシー事業者様の電話配車システムは事業
者ごとに仕様が違う
• 開発しているシステムベンダーもバラバラ
• 我々が全事業者様の配車システムの仕様を把
握することは不可能に近い
• いかに汎用的な仕様に落とすかが重要
• 独自仕様に影響を受けないサービスを作る
22
Centralサービスの特徴2
• 独自機能を作り込まない汎用的な仕様に倒す
• APIが仕様を決めるのではなくAPIに渡ってく
るデータが仕様を決める
• データによって乗務員端末と配車システムが
仕様に沿った動きをする
23
少人数チームで開発スピードを
落とさないための戦略
Centralサービスは
データが主役
24
25
Centralサービスが扱うデータ
実際にどのようなデータがあるのか
Centralサービスが扱うデータ
大きく分けて3種類
• マスタデータ
• メッセージ
• 車両ステータス
26
27
データの流れ
マスタデータとは
MOVと電話配車システムで共通に使うデータ
• 営業所マスタ
• 車両マスタ
• 乗務員マスタ
Centralサービス独自のデータ
• 車両状態
• 定型メッセージ
• 地区/待機場所
28
マスタデータの特性
• MOVと共通のデータはMOVのマスタ管理シ
ステム(通称タクモニ)から連携される
• 乗務員ログイン中のデータ更新はできない
• データ更新頻度は少ないが連携漏れに注意が
必要
29
メッセージとは1
• 配車室からの指示や端末の状態変更依頼をや
りとりするデータ
• 配車室から乗務員に対する指示
• 配車指示
• 通話依頼
• 業務メッセージ
• 乗務員から配車室への指示応答や依頼
• 配車指示への応答
• 状態変更依頼(休憩など)
• 待機の申請
30
メッセージとは2
• APIを個別に開発するのではなくメッセージ
という汎用的なデータをつかってやりとりす
る
31
メッセージの特性
• リアルタイム性が重要
• 取りこぼしのないデータ配信はさらに重要
32
車両ステータスとは
車両状態を示す情報
• 位置情報
• タクシーメーターの状態
• メーター以外の状態(休憩、開局、閉局 etc)
MOVにおける車両ステータス
• 数秒に1回のペースでサーバに送信する
• アプリ配車の抽選などに使用する
33
車両ステータスの特性
車両ステータスはMOVの根幹を支える重要な情
報
• データのリアルタイム性が重要
• 位置情報は個人情報になり得る場合があるの
で取り扱いに注意が必要
34
35
Centralサービスのアーキテクチャ
データとサービスの関係
技術要素
36
● gRPC
●Google Cloud Endpoints for gRPC
●Google Kubernetes Engine(GKE)
●Redis Streams
●Firestore
●開発言語はGo 1.14
データ特性ごとにサービスを分割する
37
●マスタデータ
○ マスタ管理サービス
●メッセージ
○ メッセージングサービス
●車両ステータス
○ 車両モニタリングサービス
マスタ管理サービスアーキテクチャ
38
●マスタデータはFirestoreに保存する
●データのCRUD操作用にREST APIを提供する
●MOVタクモニがデータを追加更新、乗務員端
末と配車システムがデータを参照する
●Extensible Server Proxy(ESP)がREST API
をgRPC APIに変換する
マスタ管理サービスアーキテクチャ
39
メッセージングサービスアーキテクチャ
40
●電話配車システムと乗務員端末間のメッセー
ジのやりとりを仲介する
●データのリアルタイム性が重要なためRedis
Streamsを使ってメッセージの配信をする
メッセージングサービスアーキテクチャ
41
車両モニタリングサービスアーキテクチャ
42
●リアルタイム配信用データと近傍検索データ
を管理する
●Redis Streamsを使って車両ステータスをリ
アルタイムに電話配車システムに配信する
●迎車地に近い車両を検索する(近傍検索)ため
のデータはMemorystoreに保存する
車両モニタリングサービスアーキテクチャ
43
リアルタイム
配信用データ
検索用データ
Centralサービスを支える技術と展望
後半
44
後半の目次
• 前半のおさらい
• Centralサービスを支える技術
• Centralサービスのこれまでとこれから
• まとめ
45
前半のおさらい
46
前半のおさらい
Centralサービスに求められる特性
• 遅延や取りこぼしのないデータ配信
• 様々なクライアントに対応できる柔軟性
• 少人数での開発を効率的に進める工夫
47
Centralサービスを支える技術
48
Centralサービスを支える技術
49
Centralサービスを支える技術
50
Centralサービスを支える技術
遅延や取りこぼしのないデータ配信
51
遅延の少ないデータ配信
52
遅延の少ないデータ配信
車両ステータスは数秒に1回のペースでAWS IoTを通して配信される
53
遅延の少ないデータ配信
サービス間の効率的な通信とは?
• 一般的なJson/HTTPなどのプロトコルではオーバヘッドが無視できない
• オーバヘッドを最小化するには、常時接続型のサービスが望ましい
• gRPC/WebSocket/MQTT/TCPなどを検討
54
遅延の少ないデータ配信
CentralサービスではgRPCをメインプロトコルとして採用
gRPCのメリット
• HTTP/2によるパフォーマンス面のメリット
• 複数のプログラミング言語のサポート
• IDLによるスキーマ共有やコード生成のエコシステム
55
取りこぼしのないデータ配信
56
取りこぼしのないデータ配信
車両ステータスとメッセージではデータの特性が異なる
• 車両ステータスはデータの鮮度が重要
• メッセージはデータをロストしないことが重要
57
取りこぼしのないデータ配信
サービス間のメッセージ管理
• スケーリングやサービスの拡張性は確保したい
• サービス間のメッセージングは非同期が望ましい
• メッセージの管理にはメッセージブローカーを採用する
58
取りこぼしのないデータ配信
メッセージブローカーの選択肢
Dissecting Message Queues (https://bravenewgeek.com/dissecting-message-queues)
Persistency one-to-many SaaS
RabbitMQ persistent / transient 1:1 / 1:n CloudAMQP
Apache Kafka persistent 1:n AWS, Azure, Confluent
Redis BlockedList transient 1:1 AWS, GCP, Azure ...
Redis Pub/Sub transient 1:1 / 1:n AWS, GCP, Azure ...
Redis Streams transient 1:1 / 1:n AWS, RedisLab
59
取りこぼしのないデータ配信
Redis Streams
Redis 5.0で追加されたデータ型
Apache Kafkaによく似たメッセージ処理のための機能を提供
特徴
• データを時系列でもつ追記型のデータ構造
• データを取得しても過去のデータを再取得可能
• コンシューマグループの概念により読み出しの分散が可能
• XACKコマンドでメッセージの購読をマークできる
60
取りこぼしのないデータ配信
CentralサービスではRedis Streamsをメッセージブローカーとして採用
61
まとめ
遅延や取りこぼしのないデータ配信の実現
• gRPCを利用して遅延の少ないデータ配信を実現している
• Redis Streamsを採用しメッセージの取りこぼしを防いでいる
62
Centralサービスを支える技術
様々なクライアントへの対応
63
Protocol Buffersの活用
64
Protocol Buffersの活用
Protocol Buffers
Protocol Buffers (protobuf)
• Google製の構造化データのシリアライズフォーマット
• IDLで記述したプロトコル定義ファイルからシリアライズ/デシリアライズ コードを生成
• 様々なプラットフォーム / 言語で利用できる
• C++, C#, Dart, Go, Java, Python ...
protocol buffer compiler (protoc)
• .protoファイルを読み込みコード生成を行うコンパイラ
• 各言語向けソースコードをprotocコマンドを利用して生成する
65
Protocol Buffersの活用
Protocol Buffersを活用し様々なクライアントに対応する
• IDLによるスキーマ共有
• 様々なプラットフォーム/言語に対応したコード生成
66
Cloud Endpointsの活用
67
Cloud Endpointsの活用
gRPCサービスならではの課題
• 認証はどのように提供する?
• クライアントとのドキュメント共有方法
• 常時接続が必要のないクライアント
• マスタデータのみを扱うクライアントがgRPCコードを追加実装するのはコスト
68
Cloud Endpointsの活用
Cloud Endpointsでできること
gRPCに対応したAPI管理サービス
• HTTP/JSONリクエストをgRPCに変換
• 認証機能の提供
• ドキュメントの生成/共有 (後述)
69
Cloud Endpointsの活用
Cloud Endpointsを利用した認証
Cloud EndpointsはJWTを用いたいくつかの認証方法をサポートしている
トークンの検証はExtensibleServiceProxy(ESP)が行う
endpointsの構成yamlファイルに認証条件を記載するだけで利用できる
70
Cloud Endpointsの活用
JSON/HTTP <-> gRPCの変換
Cloud Endpointsはプロトコルのコード変換をサポートしている
コード変換はExtensibleServiceProxy(ESP)が行う
利用方法もシンプル
• .protoファイルにアノテーションを追加する
• endpointsの構成yamlにマッピングを記載する
71
認証, 権限管理
72
認証, 権限管理
Centralサービスの認証認可
認証
• 配車システムや乗務員端末、連携するMOVシステム向けの認証
• 乗務員端末は紛失や盗難に備えたリスク管理が必要
• クライアント毎に異なる認証方法を提供する
認可
• 配車センター同士やドライバー同士で動態情報やメッセージが共有されてはいけない
• 適切な権限管理が必要
73
認証, 権限管理
配車システムや社内システム向けの認証
認証
• Cloud Endpointsの認証機能を利用
• Google ID Tokenとサービスアカウントを利用してユーザーアカウントを認証
認可
• 認可部分は個別に実装する必要がある
• JWTからアカウント情報を参照して権限をチェックするInterceptorを実装
• トークンの発行者によってチェック内容が切り替える
74
認証, 権限管理
乗務員端末の認証
配車システムやMOVシステム向けと同様の仕組みは利用できない
• MOVで管理する乗務員端末の数は数千台
• 端末1台毎に紛失 / 盗難のリスク管理が必要
• 独自認証局を構築し権限管理を行う
75
認証, 権限管理
独自認証局を利用した認証
独自認証局を利用した認証
• 端末のキッティング時に認証局がクライアント証明書を発行
• 端末はクライアント証明書を利用して各サービス向けのアクセストークン発行が行える
• Centralサービスはアクセストークンの内容から車両を識別し権限チェックを行う
リスク管理
• 認証局はクライアント証明書の発行や管理を行う
• 端末と認証局とのコネクションは1本となるよう制限
• 問題が発生した場合は証明書を無効にすることでリスク管理が行える
76
認証, 権限管理
クライアント証明書の発行フロー
1. MOVの車両登録APIを実行し車両トークンを受け取る
2. 認証局に証明書発行依頼
3. 認証局はトークンを検証し証明書を発行する
77
認証, 権限管理
アクセストークンの発行フロー
1. 認証局にトークン発行依頼
2. 認証局はクライアント証明書を検証
3. 発行されたトークンを利用してCentralサービスにアクセス
78
まとめ
様々なクライアントへの対応
• ProtocolBuffersで様々なクライアント実装に対応している
• CloudEndpointsでJSON/HTTPとgRPCの選択肢を用意している
• クライアントに応じた認証方法を提供している
• CloudEndpointsによる認証
• 独自認証局による認証
79
Centralサービスを支える技術
少人数での開発を効率的に進める
80
Infrastructure as Code
81
Infrastructure as Code
インフラ管理のコストは最小化したい
• インフラ構成をチーム全員が把握している
• 誰でも環境を立ち上げられる
• いつでも素早く環境を用意できる
82
Infrastructure as Code
Deployment Manager
GCPが提供するInfrastructure as Code(IaC)ツール
特徴
• AWSでいうCloudFormation的なサービス
• PythonやJinja2でテンプレートの仕組み
• 状態ファイルを管理しなくてOK
83
Infrastructure as Code
Deployment Manager
Deployment Managerを利用したインフラ設定の自動化
• base : ネットワークやファイアウォールの設定を管理
• service : GKEクラスタやNodePoolなどのサービス設定を管理
• iam : IAMやユーザーアカウント周りの設定を管理
84
Infrastructure as Code
Deployment Manager
Deployment Managerを利用したインフラ設定の自動化
• コンテキスト毎のコンフィグをマージして最終的な構成情報を生成する
Context 役割
Master チームや組織のコンフィグ
Project プロジェクト単位のコンフィグ
Env 構築環境によるコンフィグ(dev, stg, qa, prod)
Module 構築対象によるコンフィグ(base, service, iam)
Env Module 環境 + 対象によるコンフィグ
85
Infrastructure as Code
Deployment Manager
86
クライアントとの情報共有
87
クライアントとの情報共有
クライアントとの情報共有は時間をとられやすい部分
• APIドキュメントの作成や共有のコスト
• protoスキーマの共有や生成物の管理
88
クライアントとの情報共有
APIドキュメントの共有
Cloud Endpoints Portalを利用したドキュメントの生成
• protoファイル情報からドキュメントを生成できる
• Json/HTTPに対応するAPIはOpenAPI形式でも出力可能
89
クライアントとの情報共有
protoスキーマの共有や生成物の管理
Protocol Buffersを運用する際の課題
• protoファイルのバージョン管理の問題
• コンパイル場所やコンパイラバージョンの統一
• コンパイル後のソースコードの配布
90
クライアントとの情報共有
protoスキーマの共有や生成物の管理
.protoファイルの管理やバージョニングはCIで自動化する
• .protoファイルを管理するリポジトリ
• .protoファイル自体のバージョン管理
• 更新があると各言語向けのビルドジョブを実施
• コンパイル後の生成物を管理するリポジトリ
• protoファイルのビルド + 配布方法を管理
91
protocプラグインの活用
92
protocプラグインの活用
protocプラグインを利用したコード生成で開発を効率化する
• protocは各言語向けコードを生成するだけのツールではない
• プラグインによる拡張が可能な設計
93
protocプラグインの活用
protocプラグインを利用したコード生成で開発を効率化する
• 既存のprotocプラグインを利用して使いやすいコードを生成する
• 自分たちのプロジェクトにあったprotocプラグインを自作して利用する
94
まとめ
少人数での開発を効率的に進める工夫
• 少人数だからこそ積極的に自動化していく
• 属人化を防ぎたい部分
• 繰り返しコミュニケーションが必要な部分
• 既存の便利な仕組みを積極的に取り入れる
• protobufのコード生成周辺は便利な仕組みが揃っている
• 小さな部分でも積み重ねて効率化していく
95
Centralサービスのこれまでとこれから
96
Centralサービスのこれまでとこれから
これまでの振り返り
97
Centralサービスのこれまでとこれから
これまでの振り返り
98
Centralサービスのこれまでとこれから
抜粋
99
• gRPCのタイムアウトやスケールの問題を解決できた
• インフラ構築やデプロイ自動化が進んでよかった
• 新しい技術を使う機会が多くて開発が楽しい
• 検証のフローやログの整備が後回しになってしまった
これまで解決できたこと
100
Centralサービスのこれまでとこれから
gRPCのロードバランシング
101
gRPCのロードバランシングの問題
Centralサービスのこれまでとこれから
gRPCのロードバランシング
102
gRPCのロードバランシングの問題
• スケールアウトしても負荷分散しない
Centralサービスのこれまでとこれから
gRPCのロードバランシング
103
gRPCのロードバランシング
• Proxy Model
• HTTP/2対応のリバースプロキシを配置して負荷分散をする
• L4 ProxyではgRPCのリクエスト分散が行えないので注意する
• Balancing-aware Clinet
• クライアントサイドで接続先サーバの一覧を把握しリクエスト時に負荷分散する
• 高パフォーマンスだが, バランシングポリシーの分散など考慮事項は多くなる
• External LoadBalancing Service
• 上記のハイブリットパターン
• 外部LBサーバに接続先サーバを問い合わせてからリクエストして負荷分散
Centralサービスのこれまでとこれから
gRPCのロードバランシング
104
GKE + gRPC構成のProxy Modelロードバランシング
• HTTP(S) ロードバランサ
• GKE IngressControlerが作成するL7LB(HTTP/2対応)
• GCPサービスとの連携が可能 : ManagedSSL / CloudArmor / CloudCDN
• Centralサービスでは主にこちらを採用
• ロードバランサのヘルスチェックに少し工夫が必要なので注意
• `/`へのGETリクエストもしくはreadnessProbeをhttpGetで作成する必要がある
• gRPCサービスの場合はバックエンドをHTTP/HTTP2両受けできるようにすることで対応可能
Centralサービスのこれまでとこれから
gRPCのロードバランシング
105
GKE + gRPC構成のProxy Modelロードバランシング
• TCP/UDPロードバランサ
• type: LoadBalancer のServiceが作成するL4LB
• バランシングするには別途EnvoyやIngressControler等のL7プロキシが必要
• コネクションを1本に絞りたいなど、特定のユースケースではこちらを採用
Centralサービスのこれまでとこれから
gRPCのロードバランシング
106
gRPCのロードバランシングの問題
• Podがスケールアウトしても負荷分散しない場合があるので注意する
• ロードバランシングは自分たちの目的にあったものを選択する
• 常時接続型サービスとはいえ、切断を許容できるようにするのも重要
• 定期的にサーバ側でコネクションをリセットしてリバランスを行う
• クライアント側は突然の切断や定期的なリセットに対応できるようにしておく
Centralサービスのこれまでとこれから
gRPCのコネクション管理
107
gRPCサービスのコネクションの維持の問題
• grpc-goではKeepaliveはデフォルトで無効なので注意する
• Client-side Keepaliveの設定が必要
• サーバーはgraceful shutdownできるようにしておくことも重要
Centralサービスのこれまでとこれから
gRPCのコネクション管理
108
実際は間に入っているLBやプロキシの設定にも影響を受ける
• 設定の際は実際にやり取りされるフレームを確認しながら設定を行うとよい◎
• Goの場合は GODEBUG=‘http2debug=2’; を有効にするとframe dumpを出力できる
• パケットキャプチャツールを使うことも有効
今後の取り組み
109
Centralサービスのこれまでとこれから
今後の取り組み
110
自動化の取り組みは今後も取り組んでいく
• デプロイの選択肢を増やす(Blue/Green, Canary)
• k8sと親和性の高いCDツールの導入
運用を効率化するための仕組みの導入
• 緊急度は低いが重要度は高いタスク
• 本番の動態データの再現
• 運用の実態に合わせたログ, 監視ツールの整備
まとめ
111
まとめ
• 配車アプリ以外のサービスもいろいろ作っています!
• 新しい技術も積極的に採用しながらアップデートしています!
• サービスやデータの特性を考えながら技術選定をおこなっています
• 開発を効率化するための取り組みも大事にしています
統合後もDeNAと連携しながら更にスピードアップしていきます!
112
ありがとうございました
113
114

IoTと業務システムをつなぐgRPC/RESTサービスの開発と運用