Slide 1

Slide 1 text

1 Intro / Logo ウォレットアプリ Kyash の先 Kyash Direct のアーキテクチャ 株式会社 Kyash 岩藤 圭介(keisuke iwado) twitter: @k315k1010

Slide 2

Slide 2 text

2 ● DDD、CleanAcrchitecture等にお ける個々の設計トピックの詳細な掘 り下げ ● 具体的な実装方法、コーディング ウォレットアプリ Kyash の先 Kyash Direct のアーキテクチャ ● KyashやKyash Directに興味を もっていただく ● 実務を通じて感じたMicroservices アーキテクチャのハマりどころ、注意 した方が良いことを抑えていただく この発表のゴール お話ししないこと

Slide 3

Slide 3 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 3

Slide 4

Slide 4 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 4

Slide 5

Slide 5 text

5 ミッション:価値移動のインフラを創る 人びとの価値観や想いが詰まったお金。 お店や人びと、そしてさまざまな対象にお金を自由に届けられたら、世界はもっと明るく楽しくなる。 CEO
 鷹取 真一


Slide 6

Slide 6 text

6 2つの事業をやっています ウォレット事業 Kyash Direct事業 個人ユーザー向けウォレットアプリ「Kyash」と、B向け決済プラットフォーム「 Kyash Direct」

Slide 7

Slide 7 text

7    2015年1月 創業   2017年4月 ウォレットアプリ「Kyash」ローンチ   2018年6月 リアルカード、2%インセンティブプログラム提供開始  2019年4月 決済プラットフォーム「Kyash Direct」発表 Visaカード発行ライセンス取得   2015年7月 シートラウンド 1.7億円調達  2016年後半 シリーズAラウンド 11億円調達  to be continued….  2019年7月 シリーズBラウンド 15億円調達 これまでの歩み Kyash ローンチから2年4ヶ月

Slide 8

Slide 8 text

8    2015年1月 創業   2017年4月 ウォレットアプリ「Kyash」ローンチ   2018年6月 リアルカード、2%インセンティブプログラム提供開始  2019年4月 決済プラットフォーム「Kyash Direct」発表 Visaカード発行ライセンス取得   2015年7月 シートラウンド 1.7億円調達  2016年後半 シリーズAラウンド 11億円調達  to be continued….  2019年7月 シリーズBラウンド 15億円調達 これまでの歩み Kyash ローンチの2年後に Kyash Direct を発表

Slide 9

Slide 9 text

9    2015年1月 創業   2017年4月 ウォレットアプリ「Kyash」ローンチ   2018年6月 リアルカード、2%インセンティブプログラム提供開始  2019年4月 決済プラットフォーム「Kyash Direct」発表 Visaカード発行ライセンス取得   2015年7月 シートラウンド 1.7億円調達  2016年後半 シリーズAラウンド 11億円調達  to be continued….  2019年7月 シリーズBラウンド 15億円調達 これまでの歩み ちなみに私は約1年前のこのあたりで入社

Slide 10

Slide 10 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 10

Slide 11

Slide 11 text

11 誰でもすぐにつくれる どこでもつかえる すぐにわかる ウォレットアプリ Kyash について ● 自分たちで言うのもなんですが良いプロダクトだと思います ● ご存知なかった方、ぜひ使ってみてください!

Slide 12

Slide 12 text

12 カード(クレジット/デビット) コンビニ 銀行 ポイント/ ギフト / リワード チャージ Kyash の特徴 ● いろいろな方法でチャージ(コンビニ・ ATM・カード(手動/自動)・ポイント) ● 一瞬で送金 ● Visa加盟店でお買い物 ● 利用状況をリアルタイムに ● キャッシュバックがあって お得

Slide 13

Slide 13 text

13 プロセシング アプリケーション・プログラム カード発行ライセンス及び当局の資金決済法に 基づいた登録・各種ガイドライン遵守 国内外のVisaカード加盟店からの決済処理を 司るプロセシングシステムの構築・運用 エンドユーザーが利用する アプリケーションの構築・提供 イシュイング 当局許認可 スタートアップ システムベンダー 銀行・ カード会社 Kyash の事業上の特徴 カードの発行・利用に関わるすべてのレイヤーを垂直統合しています

Slide 14

Slide 14 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct とは 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 14

Slide 15

Slide 15 text

15 Kyash Direct とは ● 企業向けのSaaS製品です ● オリジナルデザインの Visaカードを、多様な形態で、安価かつスピーディに発行することができます ● 会員管理、カード発行、残高管理、取引履歴照会、等の機能を WebAPIで提供します ● 法人向けカードの発行も可能です 物理カード モバイルペイメント バーチャルカード

Slide 16

Slide 16 text

16 プロセシング アプリケーション・プログラム カード発行ライセンス及び当局の資金決済法に 基づいた登録・各種ガイドライン遵守 国内外のVisaカード加盟店からの決済処理を 司るプロセシングシステムの構築・運用 エンドユーザーが利用する アプリケーションの構築・提供 イシュイング 当局許認可 スタートアップ システムベンダー 銀行・ カード会社 Kyash Direct の特徴 その1 ● パートナー企業はエンドユーザー向けアプリケーションの構築に注力 できます ● カード会員向けに必要な機能の実装には Kyash Direct API を利用できます ● 既存のアプリケーションに組み込むことも容易です

Slide 17

Slide 17 text

17 パートナー企業が管理する ファンディングソース チャージ カード発行 決済 国内外5,390万の VISA加盟店 Kyash Direct の特徴 その2 ● 売上金、銀行預金、与信、ポイント、仮想通貨といった、 パートナー企業の管理下にあるユーザーの金融資 産やバリューを資金源(ファンディングソース)とすることができます ● ユーザー資産をダイレクトに Visa決済に利用できるようになり、 流動性を高める効果が期待できます カード決済に関わる実務・システムを垂直統合しているからこそ実現可能

Slide 18

Slide 18 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 18

Slide 19

Slide 19 text

19 Kyash と Kyash Direct は似ている プロセシング アプリケーション・プログラム カード発行ライセンス及び当局の資金決済法に 基づいた登録・各種ガイドライン遵守 国内外のVisaカード加盟店からの決済処理を 司るプロセシングシステムの構築・運用 エンドユーザーが利用する アプリケーションの構築・提供 イシュイング 当局許認可 8割方は同じであるかに見えると思います

Slide 20

Slide 20 text

20 Kyash - α + β => Kyash Direct ? そう考えていた時期が僕たちにもありました(今年のはじめ頃) CTO
 椎野 孝弘
 (入社間もない頃)
 エンジニア チーム
 まずは現状のウォレットとの Fit&Gap を洗い出しましょう。 既存の資産で使えるものは使うとして、追加しなきゃならな い機能開発がどれくらいあるか、、、 、、、ハイ! ※わかりやすさのため、一部演出を加えてお伝えしております。

Slide 21

Slide 21 text

21 Kyash と Kyash Direct で違うところ ※ごく大雑把に Kyash Kyash Direct 顧客 エンドユーザー(to C) パートナー企業(to B) マルチテナント対応 不要 必要 エンドユーザー向けアプリ 必要 パートナー企業が提供 エンドユーザー認証 必要 パートナー企業が提供 法人ユーザー対応 不要 必要 ファンディングソースの拡張性 追加開発できれば良い 相当な柔軟性がないと厳しい 経理・財務上必要な集計 自社分のみ パートナー企業ごと 管理系機能 社内向け 社内+パートナー企業向け … Kyashに機能を追加して対応する場合、影響範囲がとても大きいことが予想されるもの

Slide 22

Slide 22 text

22 これは…かなり無理ゲー厳しいかもしれない… ● どこをどうイジる必要があるか、洗い出すのが大変 ○ ドキュメント類の不在/陳腐化 ○ メンバーの入れ替わり ○ 安定しているがゆえに誰も触ったことがない部分も ● ウォレット単体で見ても設計的に無理が出てきている ○ 無理やり機能追加したら近い将来、収集がつかなくなりそう ○ 負債を積み増してる感があって精神的にキツイ ● 流用できた部分についても、要件の違いから乖離が発生していく可能性が高 い(ダブルメンテは避けられない) ● 新規に作る部分についても既存の設計の制約を受ける Kyashの拡張 厳しそう Points

Slide 23

Slide 23 text

23 ● 今までKyashで遭遇してきた課題を根本的なアーキテクチャレベルから解決でき るチャンス ● 運用を通じて、組織全体としてのドメイン知識はローンチ当初より今の方が圧倒 的にあるのでより良い設計ができそう ● 既存の実装を参考にできる ● 既存の設計の制約を受けない ● 面白そうなので開発者(私)のモチベーションが圧倒的に上がる スクラッチ開発 Pros. いっそのこと、ゼロから作るとしたら …?

Slide 24

Slide 24 text

24 ● 作らなければならないモノが圧倒的に増える ● アーキテクチャの刷新を試みる場合、失敗のリスクが相応にある ● 新しいことを試みるので、必要な時間の見積もりが困難 ● 社内に完全に別系統のシステムを2つ抱えることになる スクラッチ開発 Cons. いっそのこと、ゼロから作るとしたら …?

Slide 25

Slide 25 text

25 ● 作らなければならないモノが圧倒的に増える ● アーキテクチャの刷新を試みる場合、失敗のリスクが相応にある ● 新しいことを試みるので、必要な時間の見積もりが困難 ● 社内に完全に別系統のシステムを2つ抱えることになる スクラッチ開発 Cons. スタートアップが新しいチャレンジをするとき、 ある程度は避けて通れない いっそのこと、ゼロから作るとしたら …?

Slide 26

Slide 26 text

26 いっそのこと、ゼロから作るとしたら …? ● 作らなければならないモノが圧倒的に増える ● アーキテクチャの刷新を試みる場合、失敗のリスクが相応にある ● 新しいことを試みるので、必要な時間の見積もりが困難 ● 社内に完全に別系統のシステムを2つ抱えることになる スクラッチ開発 Cons. リソースが限られているスタートアップとして、 かなり受け入れがたい

Slide 27

Slide 27 text

27 どうしたものか…

Slide 28

Slide 28 text

28 ❗❗

Slide 29

Slide 29 text

29 (再掲)Kyash と Kyash Direct は似ている プロセシング アプリケーション・プログラム カード発行ライセンス及び当局の資金決済法に 基づいた登録・各種ガイドライン遵守 国内外のVisaカード加盟店からの決済処理を 司るプロセシングシステムの構築・運用 エンドユーザーが利用する アプリケーションの構築・提供 イシュイング 当局許認可 8割方は同じであるかに見えると思います

Slide 30

Slide 30 text

30 プロセシング アプリケーション・プログラム カード発行ライセンス及び当局の資金決済法に 基づいた登録・各種ガイドライン遵守 国内外のVisaカード加盟店からの決済処理を 司るプロセシングシステムの構築・運用 エンドユーザーが利用する アプリケーションの構築・提供 イシュイング 当局許認可 スタートアップ システムベンダー 銀行・ カード会社 こうすれば・・・? ウォレットアプリ Kyash as a Partner

Slide 31

Slide 31 text

31 CTOに報告・相談 、、、というわけで、一見遠回りのようでも、 ゼロから開発した方が却って早いし、今後いろいろ な問題にも対処しやすくなるのではないか?と考 えているのですが… このとき、CTOの胸にどのような想いが去来していたのか。 Kyash Direct が軌道に乗り、ウォレットの統合を成し遂げた暁には、 お酒を酌み交わしつつ聞いてみたいと思います。 ・・・

Slide 32

Slide 32 text

32 CTOに報告・相談 なるほど。わかりました。 では、その線で行きましょう! ❗❗❗ どうでしょう。イケてる経営陣だと思いませんか。 Kyashではエンジニアを絶賛募集しています!!

Slide 33

Slide 33 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計の試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 33

Slide 34

Slide 34 text

ウォレットアプリ Kyash を振り返ってみる 34

Slide 35

Slide 35 text

35 ウォレットアプリ Kyash で利用している技術

Slide 36

Slide 36 text

36 ウォレットアプリ Kyash のシステム構成 Microservices 的に複数のサービスに分かれています(※簡略化しています) API Internet カード発行 入金 家計簿連携 通知 ユーザー検索 Processing CardNetwork DB ユーザー認証 管理系機能 Internet 決済 外部サービス 外部サービス Internet Internet 社内管理 バッチ処理 Kyash

Slide 37

Slide 37 text

37 なぜ Microservices …? 以下、個人的な推察です ● Monolith にするには巨大で複雑すぎる ● 部分的な変更が全体に影響を及ぼすのを避けたい ○ 例:アプリで障害が起きてもカードは使える、等 ○ 障害発生時のインパクトが部分ごとに大きく異なる(例:決済>通知) ○ 部分ごとに変更の頻度が大きく異なる(例:API>決済) ● 部分ごとに負荷が大きく異なる ○ 部分的にスケールさせたい(の問題も) ● 外部サービスとの接続部分を切り離しておきたい ○ 提携先に影響が及ぶのは避けたい ● 機能追加のスピードは極力落としたくない Kyash が Microservices を選択した理由

Slide 38

Slide 38 text

サービスの数に対して、エンジニアの人数がまっ たく足りていない… 38 なぜ Microservices …? 一方で、つらみも抱えています ● 『コンウェイの法則』を是とするなら、 Kyash では Microservices は採用できないこと になります ● Amazonの『ピザ2枚ルール』も…

Slide 39

Slide 39 text

そもそも Micerservices を選択すべき? 39 Kyash Direct 設計時に考えたこと その1 ● もともと人数が足りていなかったところに Kyash Direct を開発するためにエンジニア チームを分割 ● ウォレットチームのギリギリ感をヒシヒシと感じる日々… ● 直近の増員は。。。

Slide 40

Slide 40 text

40 ● 巨大かつ複雑すぎる一枚岩 ● 部分的な変更が全体に影響 ○ 外部サービスとの接続部分(=提携先)にも影響 ● 部分的なスケールは不可能 ● 機能追加の難易度は。。。 向き合うことになるであろうモノたち じゃあ Monolith でやるとしたら…? どっちにしても地獄。。。なのか?

Slide 41

Slide 41 text

41 冷静になって Microservices v.s. Monolith 目下の課題で比較 ● 変更がどんどん難しくなる ● スケールが難しい ● デプロイが超ハイリスク ● エンジニアの人数が足りていない ● 運用管理がつらい(実体験として) ● 障害調査がつらい(実体験として) Microservices Monolith

Slide 42

Slide 42 text

42 冷静になって Microservices v.s. Monolith 目下の課題で比較 ● 変更がどんどん難しくなる ● スケールが難しい ● デプロイが超ハイリスク ● エンジニアの人数が足りていない ● 運用管理がつらい(実体験として) ● 障害調査がつらい(実体験として) Microservices Monolith 後で変えるのは相当困難 ● 変更難 → ゼロから作る意味がない ● スケール → ● デプロイ → 祈る 後で変えるのが比較的容易? ● エンジニア → 採用がんばる ● 運用管理 → ツール ● 障害調査 → 仕込み

Slide 43

Slide 43 text

43 こちらを選択 ● 変更がどんどん難しくなる ● スケールが難しい ● デプロイが超ハイリスク ● エンジニアの人数が足りていない ● 運用管理がつらい(実体験として) ● 障害調査がつらい(実体験として) Microservices Monolith 後で変えるのは相当困難 ● 変更難 → ゼロから作る意味がない ● スケール → ● デプロイ → 祈る 後で変えるのが比較的容易? ● エンジニア → 採用がんばる❗ ● 運用管理 → ツール ● 障害調査 → 仕込み つらみは身に沁みているけれど、 それでもやはり利点の方が大きいと判断

Slide 44

Slide 44 text

44 ● 設計・実装が難しい ● 必要な最低リソース(コンピュータ・人) は多くなる ● 運用管理がつらい ● 障害調査がつらい ● 各サービス単体では小さくてシンプル ● 変更の影響を局所化できる ● スケールしやすい ● デプロイしやすい ● リソース(コンピューター・人)配分を最適化し やすい Pros. Cons. あえて Microservices を選択するからには メリットは余すところなく享受し、デメリットはできるだけなくしたい❗❗

Slide 45

Slide 45 text

45 あえて Microservices を選択するからには メリットは余すところなく享受し、デメリットはできるだけなくしたい❗❗ ● 設計・実装が難しい ● 必要な最低リソース(コンピュータ・人) は多くなる ● 運用管理がつらい ● 障害調査がつらい ● 各サービス単体では小さくてシンプル ● 変更の影響を局所化できる ● スケールしやすい ● デプロイしやすい ● リソース(コンピューター・人)配分を最適化し やすい Pros. Cons. ある意味エンジニアの腕の見せどころ

Slide 46

Slide 46 text

46 あえて Microservices を選択するからには メリットは余すところなく享受し、デメリットはできるだけなくしたい❗❗ ● 設計・実装が難しい ● 必要な最低リソース(コンピュータ・人) は多くなる ● 運用管理がつらい ● 障害調査がつらい ● 各サービス単体では小さくてシンプル ● 変更の影響を局所化できる ● スケールしやすい ● デプロイしやすい ● リソース(コンピューター・人)配分を最適化し やすい Pros. Cons. Microservices のメリットを最大限引き出すためには 各サービスの独立性を高度に保つことが必須

Slide 47

Slide 47 text

いかにして Microservices の独立性を保つか? 47 Kyash Direct 設計時に考えたこと その2 今こそウォレットアプリ Kyash の開発・運用を通じて感じてきたつらみ 培ってきたノウハウを活かすとき…!

Slide 48

Slide 48 text

48 ポイントは大きく2つ 1. サービスをどう分けるか? 2. サービスをどう統合するか(連携させるか)?

Slide 49

Slide 49 text

49 ふたたび、ウォレットアプリ Kyash を振り返る ※簡略化しています API Internet カード発行 入金 家計簿連携 通知 ユーザー検索 Processing CardNetwork DB ユーザー認証 管理系機能 Internet 決済 外部サービス 外部サービス Internet Internet 社内管理 バッチ処理 Kyash

Slide 50

Slide 50 text

50 今だから見える課題1:サービス境界がユースケース寄り API Internet カード発行 入金 家計簿連携 通知 ユーザー検索 Processing CardNetwork DB ユーザー認証 管理系機能 Internet 決済 外部サービス 外部サービス Internet Internet 社内管理 バッチ処理 Kyash ※簡略化しています

Slide 51

Slide 51 text

51 今だから見える課題1:サービス境界がユースケース寄り ● 複数のサービス間で共有したい概念(ユーザー、カード、残高、取引履歴、等) が出てくる(低凝集) ● これらの共有したい概念は、基本的にシステム全体にとって重要なもの ● 重要な概念ほど、所属先が自明でなくなり、実装が方々に散らばる 主な問題点

Slide 52

Slide 52 text

52 今だから見える課題2:共有データの存在 API Internet カード発行 入金 家計簿連携 通知 ユーザー検索 CardNetwork DB Processing ユーザー認証 管理系機能 Internet 決済 外部サービス 外部サービス Internet Internet 社内管理 バッチ処理 Kyash ※簡略化しています

Slide 53

Slide 53 text

53 今だから見える課題2:共有データの存在 ● 各サービスに個別のDBユーザーが割当てられ、論理的に分けられてはいるもの の、物理的には1台のDBを共有しており、課題1で指摘した「共有したい概念」に 相当する一部のデータは、DBテーブルを介して実際に共有されている ● これら共有データは、事実上公開インターフェースとなっている ● 定義されたAPIとは異なり、SQLによる自由なRead/Writeが可能であり、すべて を把握しなければ安全に変更ができない(密結合) 主な問題点

Slide 54

Slide 54 text

54 今だから見える課題3:Orchestrator(指揮者)の肥大 API Internet カード発行 入金 家計簿連携 通知 ユーザー検索 CardNetwork DB Processing ユーザー認証 管理系機能 Internet 決済 外部サービス 外部サービス Internet Internet 社内管理 バッチ処理 Kyash ※簡略化しています

Slide 55

Slide 55 text

55 今だから見える課題3:Orchestrator(指揮者)の肥大 ● 各サービス間の連携を同期的なRequest/Reply方式で行っている。そのため 複数サービスをまたがる処理の起点となるサービスが、以下のことを把握して 全体をコントロールする必要がある ○ 処理全体の流れ ○ 各処理をどのサービスが持っているか ○ 各処理の呼び出しに必要なパラメータ ○ 各処理の戻り値の扱い方 ○ 正しい処理の呼び出し順序 ● 本来なら各サービスに隠蔽すべき詳細情報が呼び出し元に流出しやすい(低 凝集/密結合) 主な問題点

Slide 56

Slide 56 text

56 Microservicesの独立性を保つために 直面してきた課題と先人の知恵から学んできた、今だったらこうしたい 1. 分割単位がユースケース 2. 共有データ 3. Orchestration的に連携 1. 分割単位は境界づけられたコンテキスト(DDD) 2. DBはサービスごとに物理的に分割 3. Choreography的に連携

Slide 57

Slide 57 text

境界づけられたコンテキスト、どう切る? 57 Kyash Direct 設計時に考えたこと その3

Slide 58

Slide 58 text

境界づけられたコンテキスト Kyash の開発・運用を通じて散々考えてきたので、意外とシュッと決まる ● ノウハウがないところからスタートしていたら、とても難しかったと思います ● だいたい1コンテキスト内に集約ルートとなる Entityが数個くらいの感覚です( VOはたくさん) Partner User Account Card Processing Clearing Funding 58 ※簡略化しています

Slide 59

Slide 59 text

サービス同士、どう連携させる? 59 Kyash Direct 設計時に考えたこと その4

Slide 60

Slide 60 text

60 Message Pub/Sub で非同期的に情報を伝達します Message Bus Partner User Account Card Processing Clearing Funding

Slide 61

Slide 61 text

Message Bus Partner User Account Card Processing Clearing Funding 61 サービスは、自身の内部で何か起きたら Message Bus に所定の Message を送ります (ここでは Message Bus ≒ Pub/Sub 型の何かであると考えてください) Userで何かが起きた

Slide 62

Slide 62 text

Message Bus Partner User Account Card Processing Clearing Funding 62 Message Busに届いた Message は、各サービスに Publish されます 全体に伝わる

Slide 63

Slide 63 text

Message Bus Partner User Account Card Processing Clearing Funding 63 各サービスは、自身が処理すべき Message が届いたら必要な処理を実行します ❗ Accountが反応

Slide 64

Slide 64 text

Message Bus Partner User Account Card Processing Clearing Funding 64 処理する必要のない Message が届いた場合は無視します Partnerは無視 ⚙ Accountは何かしら処理

Slide 65

Slide 65 text

Message Bus Partner User Account Card Processing Clearing Funding 65 処理を実行した結果、何か起きたら(大抵は何か起きる)、また所定の Message を送りま す。これが繰り返されます

Slide 66

Slide 66 text

Message Bus Partner User Account Card Processing Clearing Funding 66 原則としてサービス間で直接の通信は行いません。必ずMessage Busを経由します ❌

Slide 67

Slide 67 text

67 Message Pub/Sub による非同期的な連携 ● サービス間の依存が Message および Message Bus に一元化される(サービ ス間の相互依存は Message のみとなる) ● 起こった結果(Event)のみを気にすれば良く、処理の過程を考慮する必要が ない ● 各処理は特定の Event に対する反応として記述するため、比較的小さく収ま る(Event Driven) Pros. サービスを圧倒的に疎結合・高凝集にしやすい

Slide 68

Slide 68 text

68 Message Pub/Sub による非同期的な連携 ● Message変更の影響が大きい ○ Messageは公開インターフェースに相当 ○ 項目の追加程度なら問題はありません ○ 項目の削除や大幅な構造変更には、Version管理、あるいは別Message として新たに定義して対応することになると思います ○ できるだけコンパイラでチェックできるようにしたいところです ● 提供したいのは同期的な WebAPI(HTTP Request/Response)だけど、非同 期メッセージングでどうやる? ○ 後述します ● どこかで障害が発生した場合、データの一貫性をどうやって補償する? ○ 後述します ● 複数サービスにまたがる処理がどう動いているか追跡が困難 ○ 後述します Cons.

Slide 69

Slide 69 text

サービスを分割するとして、DBはどうする? 69 Kyash Direct 設計時に考えたこと その5

Slide 70

Slide 70 text

70 DBどうする問題 案1:Event Sourcing Event Store ① Busに流れるすべてのEventを記録 ② 必要となる都度、過去の Eventをすべて再生し て現在の状態を取得 ① ② Message Bus Partner User Account Card Processing Clearing Funding

Slide 71

Slide 71 text

71 DBどうする問題 案1:Event Sourcing ● 記録が追記のみで作成されるため、データ競合が発生しにくい ○ 排他制御の問題をある程度クリア ● Eventを再生しさえすればどのサービスも結果的に同じ状態を入手できる ○ データの一貫性の問題をある程度クリア ● 過去のある時点の状態に戻せる ● 監査証跡として有効 ● インターフェースはEventなので(SQLではないので)、永続化機構をサービス ごとに分けたりしなくても問題なさそう Pros.

Slide 72

Slide 72 text

72 DBどうする問題 案1:Event Sourcing ● 過去のEventをすべて再生するため、Eventの数が積み上がるといずれパ フォーマンス問題に行き当たりそう ● これをクリアするためには一定期間ごとにスナップショットを作成しておいて、そ れ以後のEventから再生する、等の対策が必要になる ● 現時点の状態を見るには、Eventを再生しなければならない ● Eventのバージョン競合は起こりうるのでその制御は必要 Cons.

Slide 73

Slide 73 text

Message Bus Partner User Account Card Processing Clearing Funding 73 DBどうする問題 案2:各サービスごとにDBを持つ(State Sourcing) DB DB DB DB DB DB DB

Slide 74

Slide 74 text

74 DBどうする問題 案2:各サービスごとにDBを持つ(State Sourcing) ● サービスの独立性を高く保つことができる ● 扱いやすい(慣れの問題?) ● 現時点の状態(最新のデータ)を簡単に見ることができる Pros.

Slide 75

Slide 75 text

75 DBどうする問題 案2:各サービスごとにDBを持つ(State Sourcing) ● データの上書きが発生するため、普通に排他制御が必要 ● 複数サービスにまたがる処理=複数DBにまたがる処理 となるため、データの 一貫性を担保するために補償トランザクションの仕組みが必要 ● サービスの数だけDBが必要() Cons.

Slide 76

Slide 76 text

76 DBどうする問題 結論:各サービスごとにDBを持つ+Event Store Event Store ① 各サービスのDBでRead/Write ② Busに流れるすべてのEventを記録 ③ いざというときピンポイントで 復旧に必要な過 去のEventを再生 ② ③ Message Bus Partner User Account Card Processing Clearing Funding DB DB DB DB DB DB DB

Slide 77

Slide 77 text

77 DBどうする問題 ● Writeについてはスナップショットを毎回作成しているのと同じ ● ReadについてはEventの再生ではなく、常に最新の状態が保持されているDB から取得 ● 必要に応じて、Event StoreからEventを取得・再生 特徴 結論:各サービスごとにDB+Event Store

Slide 78

Slide 78 text

78 DBどうする問題 ● サービスの独立性を高く保つことができる ● 扱いやすい(慣れている) ● 現時点の状態を簡単に見ることができる ● 過去のある時点の状態に戻すことができる ● 監査証跡も ● 障害発生時のリカバリ Pros. 結論:各サービスごとにDBを持つ+Event Store

Slide 79

Slide 79 text

79 DBどうする問題 ● 各サービスごとのDBに対しては排他制御が必要 ○ 排他制御を行います ● 補償トランザクションの仕組みが必要 ○ 後述します ● サービスの数だけのDBに加えEvent Store用のストレージが必要() ○ べらぼうな金額ではないはず…! ● 通常ReadはDBから行うが、Eventの再生もありうることを前提とした設計・実 装が必要 ○ Event Sourcing寄りの設計・実装を行います ○ 具体的にはAggregateの変更はEvent生成→Event適用の手順を踏むよ うに統一します 結論:各サービスごとにDBを持つ+Event Store Cons.

Slide 80

Slide 80 text

● WebAPIをどうやって提供する? ● データの一貫性をどうやって担保する?(補償トランザクション) ● トレーサビリティをどうやって確保する? 80 ここまでのおさらい ● Microservices でいく ● Microservices の利点を最大限引き出すために ○ サービスは境界づけられたコンテキストで切る ○ サービス同士の連携はMessage Pub/Subを利用したEvent Drivenな Choreography方式 ○ 永続化は各サービスごとのDB+Event Store 決まったこと ✅ 未解決の問題

Slide 81

Slide 81 text

WebAPIをどうやって提供する? 81 Kyash Direct 設計時に考えたこと その6

Slide 82

Slide 82 text

82 ここで、さきほどからチラホラと出てきている Message と Event について ● Message:送受信を目的として所定のフォーマットで記述されたデータ ● Event:過去のいずれかの時点で発生した事実(結果)がデータとして記載され た Messageの1種 Message Event

Slide 83

Slide 83 text

83 Event: 過去に発生した事実(結果) ● 一方、WebAPIの関心時は今からやってほしいこと&その結果 ● WebAPIが実行された結果としてEventが生まれることはあっても、Eventだけ でWebAPIを記述することはできない ● Eventだけ定義されていても永久に何も起こらない Message Event なにかしら必要

Slide 84

Slide 84 text

84 WebAPI に対応する Message ● Command ○ 今からやってほしいこと( Requestに対応) ○ 実行するサービス側でインターフェースとして定義 ○ 実行するサービスのみが受け取る Messageの1種 ● Document ○ Commandの結果(Responseに対応) ○ Commandを定義するサービス側でインターフェースとして定義 ○ Command送信時に指定された返信先のみが受け取る Messageの1種 Message Event Command Document

Slide 85

Slide 85 text

85 WebAPI に対応する Message の例 Command:RegisterUser ● Name:Tokichiro Kinoshita ● Gender:Male ● DateOfBirth:YYYY-MM-DD ● ReplyTo:api ● Command名 ● Commandパラメータ ● Documentの返信先 ● Event名 ● 起こった事実の内容 ● Document名 ● Commandの実行結果 ※Commandパラメータに含まれる情報は持たなくて良い Event:UserRegistered ● ID:blii3osllhcp2qsl0ao0 ● Name:”Tokichiro Kinoshita” ● Gender:Male ● DateOfBirth:YYYY-MM-DD ● CreatedAt: YYYY-MM-DD Document:RegisterUserResult ● ID:blii3osllhcp2qsl0ao0 ● CreatedAt: YYYY-MM-DD

Slide 86

Slide 86 text

86 API Facade の導入 これでHTTPの世界とMessagingの世界を繋ぎます パートナー企業 サーバー Message Bus Service 1 Service 5 Service 2 Service 4 HTTP Req. HTTP Res. Command Document Service 3 ● API Facade が、WebAPI を公開します ● HTTP Request を、API に対応する Command に変換し、Message Bus に送ります ● Message Bus から Document が返されたら、HTTP Response に変換し、クライアントに返します API Facade

Slide 87

Slide 87 text

87 パートナー企業 サーバー Message Bus Service 1 Service 5 Service 2 Service 4 HTTP Req. HTTP Res. Service 3 ● API Facade は、Requestを受けたセッション内で同期的に 応答を返す必要があります ● Commandの送信後、Documentを受信するか、タイムアウトするまで 待機(Block)します ● API Facade が複数ノードで構成される場合、 Commandを送信したプロセスと、 Document を受け 取るプロセスを一致させるための仕組み が必要になります API Facade ⏳ Service 1 Command Service 1 Document API Facade の特殊事情

Slide 88

Slide 88 text

88 Event と Command / Document の違い パートナー企業 サーバー Message Bus Service 1 Service 5 Service 2 Service 4 HTTP Req. HTTP Res. Service 1 Command Service 1 Document Service 3 ● Event は、すべてのサービスに対して Publish されます ● Command は、Command を提供するサービスに対して Send されます ● Document は、Command で指定された返信先( ReplyTo)に対して Send されます API Facade

Slide 89

Slide 89 text

89 先に挙げた RegisterUser の例で見てみます パートナー企業 サーバー Message Bus User Service 5 Service 2 Service 4 POST api/user Response RegisterUser RegisterUserResult Service 3 ● Command:RegisterUser → Userサービスに Send ● Event:UserRegistered → 全サービスに Publish ● Document:RegisterUserResult → API Facade に Send API Facade UserRegistered

Slide 90

Slide 90 text

Query(HTTP GET)はどうなる? 90 ところで…

Slide 91

Slide 91 text

91 先ほどの例で登録したUserの情報を取得する場合 パートナー企業 サーバー Message Bus User Service 5 Service 2 Service 4 GET api/user/xxx Response GetUser GetUserResult Service 3 API Facade 、、、こうなる・・・? 不可能ではなさそうだけど、つらそう

Slide 92

Slide 92 text

92 境界づけられたコンテキストに対応する各サービスが Queryに応答する責務を担う場合 ● 複数のサービスにまたがるクエリに答えるのが難しい ○ 例:法人ユーザー配下の全ユーザーの今月のカード利用明細 ● API Facade への知識の流出が起こる(例のOrchestrator肥大化) ○ 各サービスにクエリし、結果を合成する必要がある ○ どのサービスがどの情報を持っているか、どのキーで結合するか、等の情 報を API Facade が知っておく必要がある ● クエリの要件が増えるたびに、関連する各サービスのメンテが発生 ○ 常にクエリの要件を考慮した設計・実装が必要 ● パフォーマンス的にしんどい Cons. Pros.

Slide 93

Slide 93 text

もはや CQRS 一択 (Command Query Responsibility Segregation) 93 Queryへの対応

Slide 94

Slide 94 text

94 QueryMaterializer / QueryProcessor の導入 パートナー企業 サーバー Message Bus Service 1 Query Material izer Service 2 Service 4 HTTP GET Response Service 3 ● QueryMaterializer は、他のサービスと同様に Eventを受け取り、必要に応じて QueryDB を更新 します ● API Facade は参照系のAPI呼び出しに対して、QueryProcessor の該当処理を呼び出します ● QueryProcessor は、QueryDB を参照し、必要な情報を取得して呼び出し元に返します API Facade Query DB Query Process or REST / RPC

Slide 95

Slide 95 text

95 ● 各サービスは、何らかの変化に対して Event さえ律儀に発行していれば良く、 Queryを意識する必要がない ● Queryの要件に特化したデータ構造を採用できる ● Queryの応答性能的に有利 ● Queryの要件変更に対して QueryMaterializer/QueryProcessor だけで対応 できる ● QueryProcessor については、Messageの世界に囚われることなくQueryに特化 したプロトコルやフレームワークを採用できる ● Queryだけスケールできる Pros. CQRSの採用

Slide 96

Slide 96 text

96 CQRSの採用 Cons. ● 最新のデータが反映されるまでタイムラグがある ○ 数秒あるいはそれ以上の遅延が発生したとしても実用上は問題ない ● Eventを取りこぼすとQueryの結果にデータ更新が反映されない ○ Event Store からリカバリ ● サービスが増える/プロダクト全体として複雑性が増す ○ やむを得ない…

Slide 97

Slide 97 text

データの一貫性をどうやって担保する? (補償トランザクション) 97 Kyash Direct 設計時に考えたこと その7

Slide 98

Slide 98 text

Sagaパターンを適用します 98 補償トランザクション

Slide 99

Slide 99 text

99 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 1. Processingサービスから「オーソリ要求を受けたよ」 EventがPublishされます

Slide 100

Slide 100 text

100 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 2. 各サービスはMessageBusを経由して「オーソリ要求受けたよ」 Eventを受信します

Slide 101

Slide 101 text

101 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 3. 「オーソリ要求受けたよ」 Eventに対して、何かしらの責務を負っているサービスは、これに反応してそ れぞれに処理を行います。ここでは User、Card、Account とします ❗ ❗ ❗

Slide 102

Slide 102 text

102 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 4. このとき、各サービスで生成されるトランザクションデータは、 「Trying」状態となります ⚙ ⚙ ⚙ Trying Trying Trying

Slide 103

Slide 103 text

103 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 5. 各サービスは、処理が完了したら、それぞれに結果を EventとしてPublishします 6. その間、Processingは各サービスの結果 Eventを待ちます※ ※つまりProcessingは、自身が結論を下すためにどのサービスのどの Eventが必要かを知ってい なければなりません

Slide 104

Slide 104 text

104 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 7. Processingは、必要な結果Eventが出揃ったら最終的な判断を行い、

Slide 105

Slide 105 text

105 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 8. 一連のEventの結論として、「オーソリ承認したよ」 EventをPublishし、 9. 同時にクライアントにも 「オーソリOKっす」的なレスポンスを返します

Slide 106

Slide 106 text

106 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 10. 各サービスはMessageBusを経由して「オーソリ承認したよ」 Eventを受信し、

Slide 107

Slide 107 text

107 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 11. 該当するトランザクションデータの 「Trying」の状態を「Confirmed」に書き換え、確定させます。これが Commitに相当します 12. この後に「トランザクションをConfirmedにしたよ」EventをPublishします ❗ ❗ ❗ Confirmed Confirmed Confirmed ⚙ ⚙ ⚙

Slide 108

Slide 108 text

108 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card いずれかのサービスで結果が NGとなったり、エラー等により処理が Failした場合は、その旨を Eventとして Publishします NG/Failの場合

Slide 109

Slide 109 text

109 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card Processingは、どれか1つでもNG/Failureと返ってきたら最終的な判断を NGとします NG/Failの場合

Slide 110

Slide 110 text

110 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card つまり一連のEventの結論として、「オーソリ拒否したよ」 EventをPublishし、同時にクライアントに 「オーソリ 無理っす」的なレスポンスを返します NG/Failの場合

Slide 111

Slide 111 text

111 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 各サービスは、MessageBusを経由して「オーソリ拒否したよ」 Eventを受信し、 NG/Failの場合

Slide 112

Slide 112 text

112 Sagaパターンの例:決済(オーソリ) Message Bus Processi ng User Account Card 該当するトランザクションデータの 「Trying」の状態を「Canceled」に書き換え、確定させます。 これがRollbackに相当します。 もちろん「トランザクションがCanceledになったよ」Eventを投げます。 ❗ ❗ ❗ Canceled Canceled Canceled NG/Failの場合 こういう一連の流れをSagaと呼ぶらしい ⚙ ⚙ ⚙

Slide 113

Slide 113 text

113 Sagaパターンのポイント ● 補償トランザクションをEvent Drivenに実装できる ● 各サービスで作成されるトランザクションデータは、Commit/Rollbackに対応する ためにStateを持つ必要がある ● Sagaに関わるEventについてはそれぞれ以下3パターンが必要 ○ Success ■ OK ■ NG ○ Failure ● Saga単位で一意となるID(SagaID、相関ID)を付与しておくと、いたずらに他 サービスのIDを持つ必要がなくなる上に、Saga単位のCommit/Rollbackの処理 をある程度共通化できる可能性がある

Slide 114

Slide 114 text

● Sagaに関わるEventについてはそれぞれ以下3パターンが必 要 ○ Success ■ OK ■ NG ○ Failure(Error) 114 ここで、気になった方はいらっしゃるでしょうか Eventって状態の変化を表すものなんじゃないの? (NGとかFailureでは状態は変わらないのでは?)

Slide 115

Slide 115 text

1. Cardサービスにそれ用のCommandを用意する 2. サービスAが「このカードのチェックたのんだ」的なEventを投げ、Cardサービスがそ れを拾い、チェック結果をEventとして返す 3. サービスAがCardサービスから発行されるカードの状態変化Eventをすべて拾い、 サービスAのDBに記録してカードの状態をトレースする 4. Queryに問い合わせて結果を取得する 115 これ悩みました 例1:あるサービスAの処理の中で、あるカードが現在利用可能か否かを確認したい これを実現するにはどうするのが良いでしょう? みなさんなら、どれを選びますか?

Slide 116

Slide 116 text

3. サービスAがCardサービスから発行されるカードの状態変化Eventをすべて拾い、 サービスAのDBに記録してカードの状態をトレースする 4. Queryに問い合わせて結果を取得する 116 まず、 この2つが以下の理由で最初に消えました。 ● カードが現在利用可能か否かのチェックは、単なるQueryではなく、Cardドメインのビ ジネスロジック ○ Cardサービス内で行われるチェックの内容は、単なるQueryとは異なる可能性 がある。いずれにしても依頼者は関知すべきではない ○ チェックを他のサービスで行うことは、ドメインのビジネスロジックが流出してい ることを意味する(低凝集/密結合) ● カードの現在の状態を正確に知っているのはCardサービスだけ(タイムラグが存在 する)

Slide 117

Slide 117 text

117 このとき引っかかっていたこと 1. Cardサービスにそれ用のCommandを用意する 2. サービスAが「このカードのチェックたのんだ」的なEventを投げ、Cardサービスがそ れを拾い、チェック結果をEventとして返す 残る二者択一で、かなり迷いました ● Eventって状態の変化を表すものなんじゃないの? ● OK/NGを返すだけならEventじゃないのでは? ● そもそもどの集約ルートのEventになるの?

Slide 118

Slide 118 text

118 考えるヒント Eventを「状態の変化を表すもの」と限定すると、 SagaパターンではCommandとEventが入り乱れるな…?

Slide 119

Slide 119 text

119 SagaパターンでCommandとEventが入り乱れる Message Bus Processi ng Account Card User あれ、なんかEvent Drivenっぽくないぞ・・・ Orchestrationっぽくなってきたぞ・・・ ① ① ② ② ③ ❓

Slide 120

Slide 120 text

120 思い込みに気づく Event Sourcing の Event と Event Driven の Event は違う ● Event Sourcing ○ 起きた出来事(変更)をすべて記録する ○ 現在の状態は過去の出来事をすべて再生することで得られる ● Event Driven ○ 起きた出来事をトリガーとして処理を起動する ■ Pub/Sub(Producer/Consumer)型 ■ Stream型 ごちゃ混ぜに考えていました だって同じ言葉だったので…

Slide 121

Slide 121 text

121 Event と一口に言っても種類がある ● Command:今からやってほしいこと ● Document:Commandの結果 ● Event:起きた出来事 ○ SourceEvent:起きた出来事+それによる変化の内容 Message Event Command Document Source Event

Slide 122

Slide 122 text

122 私たちの選択 これを選択しました もうおわかりかもしれませんが 2. サービスAが「このカードのチェックたのんだ」的なEventを投げ、Cardサービスがそれ を拾い、チェック結果をEventとして返す ● 現在は、原則としてCommand/DocumentのパターンはAPI Facadeからのみ利用 可としています(≒ 原則 WebAPIと1:1 => Applicationの関心事) ● Commandを他のCommandやEventと組合わせて使用すると、あっという間に Orchastrator化するため、注意が必要と感じています(Commandは単体で Applicationの要求を満たすよう設計すべき) 例1:あるサービスの処理の中で、あるカードが現在利用可能か否かを確認したい このケースでは

Slide 123

Slide 123 text

1. Userサービスにそれ用のCommandを用意する 2. サービスAが「このユーザーIDの存在確認たのんだ」的なEventを投げ、Userサービ スがそれを拾って結果をEventとして返す 3. サービスAがUserサービスから発行されるUser生成Eventを拾い、サービスAのDB に記録してユーザーIDの有無をトレースする 4. Queryに問い合わせて結果を取得する 123 ではこういう場合は? 例2:あるサービスAの処理の中で、あるユーザーIDが存在するか確認したい これを実現するにはどうするのが良いでしょう? みなさんなら、どれを選びますか?

Slide 124

Slide 124 text

124 私たちの選択 を選択しました。理由は以下です。 3. サービスAがUserサービスから発行されるUser生成Eventを拾い、サービスAのDBに 記録してユーザーIDの有無をトレースする この場合は ● 単なるIDの存在確認は、Userドメインのビジネスロジックとは言えない ○ 他のサービスでやってもビジネスロジックの流出は起きない ● ユーザーIDの存在確認のために都度Eventのやりとりでやるとすると、そういうニー ズが生まれるたびにUserサービスに各Eventに対応するための修正を入れなけれ ばならず、煩雑すぎる

Slide 125

Slide 125 text

125 ● ドメイン固有のビジネスロジックと見るべきか ● アプリケーションの関心事と見るべきか ● どっちの方が(中長期的に)楽そうか 例1:あるサービスの処理の中で、あるカードが現在利用可能か否かを確認したい 例2:あるサービスの処理の中で、あるユーザーIDが存在するか確認したい この2つのケースの違いは微妙なもので、どれが絶対的に正しいというのはない気がし ています。私たちの場合、 といったことを基準に、その都度議論して判断しています。 難しいですが、だからこそ議論する価値のある内容だと思います。

Slide 126

Slide 126 text

トレーサビリティをどうやって確保する? 126 Kyash Direct 設計時に考えたこと その8

Slide 127

Slide 127 text

分散トレーシングを仕込みます 127 Microservices のトレーサビリティ

Slide 128

Slide 128 text

128 Datadogを選択した理由 ● 分散トレーシングの結果をAPM(Application Process Monitoring)でグラフィカルに 確認できる ● APMとLogを関連付けて一緒に見ることができる ● AWS用のプラグインが充実 ● 分散トレーシング基盤を自前で用意する余裕はない ● 価格面の妥当間(Datadogも安くはないけど他のはもっと高かった) ● ウォレットでも使っていてとくに不満がない

Slide 129

Slide 129 text

129 Datadogで分散トレーシングするための仕込み ● サービステンプレート(後述)に含まれるライブラリに仕込んでいます ○ Datadogのライブラリを組み込み ○ フレームワーク的な部分でtracerを起動 ○ TraceID、SpanIDを引き回す ○ ログにTraceID、SpanIDを出力 ● サービステンプレートを利用していればある程度勝手にトレースされます ○ サービスをまたぐ場合は勝手にSpanが切られる ○ Spanを切りたいところでStartSpan(...)すれば良い

Slide 130

Slide 130 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計での試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 130

Slide 131

Slide 131 text

131 ※現時点でのもので、変わる可能性があります

Slide 132

Slide 132 text

132 132 Kyash Directで利用している技術(※今のところ)

Slide 133

Slide 133 text

133 Kyash と同様にGoを選択した理由 ● 現メンバーが使い慣れている(学習コスト:低) ● 大きな不満がない ○ 書きやすさと、実行時のリソース効率・性能のバランスが良い ○ 強い静的型付け(ないと生きていけない) ● Kyashの既存実装をコードレベルで参考にできる ● コミュニティが活発 ● 言語人口が多そう(採用活動❗) といったところです

Slide 134

Slide 134 text

134 サービステンプレート - 構造 ● internal ○ adaptor ■ MessageHandler(InputPort実装) ■ MessagePresenter(OutputPort実装) ■ DBアクセス周りの実装 ○ usecase ■ Usecase各種 ○ domain ■ Model(Entity、VO) ■ Factory(Model、Event) ■ Repository ■ Service Clean Architecture にもとづくレイヤー化と依存性の管理をしています DIにはWireを利用しています 最初はいろいろと迷いましたが、今は各サービスでコードの構造が揃い、見通しが良く なって、修正やレビューがはかどると実感しています ● pkg ○ usecase ■ Command ■ Document ○ domain ■ Event ■ VO ● cmd ○ main

Slide 135

Slide 135 text

135 サービステンプレート - ライブラリ ● log ○ 基本的にlogrusのwrapper ○ DatadogAPMのためのプラグイン等 ● errors ○ twirpのエラーを参考にエラーの分類を規定 ○ stack情報を持たせやすく ● persistence ○ DB接続とトランザクション管理 ● messaging ○ Message Pub/Subまわりのインターフェース ○ 各種Message(Event、Command、Document)のインターフェース ○ AWS SQS/SNS用の実装 ○ Messageの重複排除、排他制御、リトライなど ○ DatadogAPMのための仕込み 以下のライブラリを自作して、基本的にすべてのサービスで利用しています

Slide 136

Slide 136 text

136 サービスのインフラ構成 SQS Server Process Server Process Server Process Agent Aurora SNS 1サービスの基本的な構成です

Slide 137

Slide 137 text

137 サービスのインフラ これが複数存在し、各々が PublicなEvent用のSNSをSubscribeしています Event SNS ● SQSはFIFOにしていない(At Least Once)ため、重複排除を行います ● 複数のServerProcessが同一のMessageを受信しても問題ないよう排他制御も行います ● 現在はこのためにDynamoDBを利用しています Service 1 Service 2 Service 3

Slide 138

Slide 138 text

138 全体像 Command系とQuery系に別れています API Facade Event SNS Query ● Commandは、対象サービス専用の SNS Topicに送られ、そのサービスでのみ Subscribeされます ○ API FacadeはEventには関与しません ● Queryは、MaterializeのためにEventをSubscribeするためにSQSだけ持っています ● API FacadeとQueryのやりとりは、MessagingではなくRPC(PBベース)となっています Query Command

Slide 139

Slide 139 text

139 大量のAWSリソースを複雑に組み合わせて使っているので、 ふつうにconfigとかでやっていたら なので、 Event SNS Query ● 明確なリソース命名規約 ○ 環境とサービスが決まればすべてのリソース名が推移的に決定 ○ 規約に基づくオーケストレーションとAppからのリソースアクセス ● 個人的に「SREチーム神」と思ったポイントです Query Command API Facade

Slide 140

Slide 140 text

140 ここから先、実際のコードが気になるアナタ! とりあえず、Kyash に来てください❗

Slide 141

Slide 141 text

目次 01. 株式会社 Kyash について 02. ウォレットアプリ Kyash について 03. Kyash Direct について 04. Kyash Direct のスクラッチ開発を決意するまで 05. 設計での試行錯誤 06. どう実現しているか 07. まとめ 08. 質疑応答(?) 141

Slide 142

Slide 142 text

142 まとめ(という名の感想) ● Microservices のメリットを本気で引き出そうとすると、考えなければならない ことが本当に多いです ● 設計に関する書籍は「読む↔実践する」を何往復かすると得るところが大きい です(消化に時間がかかる・反芻が必要) ● Event DrivenとEvent Sourcingは両立できるけれども、設計を考える際は文 脈が異なることを意識した方がはかどります ● Request/Reply型の同期処理に慣れきった状態から非同期メッセージング によるEvent Drivenなアプリケーションを書くのは、最初はかなり難しいです (脳の切り替えが必要) ● Eventチェーンがバシッと決まるとピタゴラスイッチ的なカタルシスを感じること ができます ● 通常レベルの流量なら(IoTとかでなければ)、AWSのSQS+SNS+αは、非同 期メッセージングによるEvent Drivenなアーキテクチャの基盤として十分実用 的なパフォーマンスを発揮できそうです ● 運用はこれからなので、まだまだ試行錯誤は続きそう。。。

Slide 143

Slide 143 text

143 最後に大事なことなのでもう一度 Kyashではエンジニアを積極採用中です❗❗ meetup等もやっています。気軽に遊びに来てください!

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

Special Thanks !! ● builderscon tokyo 2019 ● All Kyash Members & Users ○ especially: Kyash Direct Engineers ● @mtoyoshi

Slide 146

Slide 146 text

ご意見、ご質問、ご感想など、下記 twitterアカウントにお寄せいただけたらうれしいです 146 twitter: @k315k1010 Kyashでの投げ銭を体験してみたい方はコチラへ … Kyash ID: iwado

Slide 147

Slide 147 text

No content