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

スペースマーケットにおけるマイクロサービスの取り組み

194f4e605d797dda7a64fd08734eff82?s=47 chato
March 26, 2021

 スペースマーケットにおけるマイクロサービスの取り組み

【GraphQL/Fargate...】シェアリングエコノミーを支えるアーキテクチャ
SPACEMARKET x Lancers Engineer Meetup #1
にて発表した資料です。

194f4e605d797dda7a64fd08734eff82?s=128

chato

March 26, 2021
Tweet

Transcript

  1. スペースマーケットにおけるマイクロサービス の取り組み SPACEMARKET x Lancers Engineer Meetup #1 スペースマーケット 技術部

    バックエンドチーム EM 西尾 綾祐
  2. 2 自己紹介 西尾 綾祐(ニシオ リョウスケ) 2017年3月にスペースマーケットに JOIN 予約・決済周りを担当することが多い 現在はバックエンドチームの EMとしてチームマネジメント、プ

    ロジェクト管理、採用、及びプロダクト開発を担当。
  3. 3 マイクロサービス化以前の構成(2018年11月以前) スペースマーケットでは長らくAPI側は単一のアプリケーションで構成されてました

  4. 4 2021年3月時点のAPI側構成 現在ではAPI側は主に3サービスに分割しています

  5. 5 スペースマーケットにおけるサービス分割粒度について

  6. 6 スペースマーケットにおけるAPIサービス分割粒度について ビジネス的に意味のある大きな粒度での分割

  7. 7 スペースマーケットにおけるAPIサービス分割粒度について ビジネス的に意味のある大きな粒度での分割(現在は 3サービスに分割)

  8. 8 スペースマーケットにおけるAPIサービス分割粒度について DBトランザクションが発生するところは分割しない

  9. 9 スペースマーケットにおけるAPIサービス分割粒度について 改修頻度があまり高くない部分は切り出さない

  10. 10 スペースマーケットにおけるAPIサービス分割粒度について API分割粒度まとめ • ビジネス的に意味のある大きな粒度での分割 • DBトランザクションが入る部分は分割しない • 変更が入りやすい部分を切り出す 現在は

    MAIN / 検索 / 予約・決済 の3つに分割されている
  11. 11 ちなみに API以外の話(バッチ部分)については結構サービスが別れている • マーケティング系バッチ(3システム) : Rails • 検索系バッチ(5システム) :

    Go / Rails • 検索アルゴリズム: <secret> • 予約系バッチ(2システム) : Go • その他バッチ(2システム) : Rails
  12. 12 マイクロサービス 対応の歴史(第1段検索編) 最初は検索部分を別システムに切り出した

  13. 13 マイクロサービス 対応の歴史(第1段検索編) 叩くGraphQL毎にエンドポイントが違うのは辛いので Gatewayを設置 ・Schema Stitching で 複数のリモートスキーマ を1つのスキーマとして扱う

    ・実験段階ではRubyで作ってみたがいろいろ頑 張ってみたが性能がうまく出ず ・Node.jsで作ったところあっさり解決 Ruby: Blocking-IO Node: Non-Blocking IO Gatewayの特性上Node.jsの方が適性 ・RESTはGateway経由せず
  14. 14 マイクロサービス 対応の歴史(第1段検索編) 検索で必要な情報はバッチ処理で同期 ・検索を高速化するために検索に特化したテー ブル構造(非正規化)に ・いわゆるキャッシュ的な感じのものを MainDB->検索DB等にバッチ処理で同期して 検索APIはそれを使う

  15. 15 マイクロサービス 対応の歴史(第2段予約・決済編) 次に予約部分を切り出した(現時点の構成)

  16. 16 マイクロサービス 対応の歴史(第2段予約・決済編) Mainサービスから予約部分を切り出すためには 2つのAPI結果をマージする必要があった 欲しい予約のレスポンス
 {
 id : 1


    status: 予約完了
 price: 20000円
 room_id : 100
 room: {
   部屋の名前: 普通の部屋
   部屋の説明: 素敵な部屋です。
  }
 }
 
    Room情報
 予約情報
 mainが返せる部屋レスポンス 
 room: {
  部屋の名前: 普通の部屋 
  部屋の説明: 素敵な部屋です。 
 }
 
    mainは予約情報は 持っていない
 予約が返せる部屋レスポンス 
 {
 id : 1
 status: 予約完了
 price: 20000円
 room_id : 100
 }
    予約サービスは 
 部屋の情報を持っ ていない

  17. 17 マイクロサービス 対応の歴史(第2段予約・決済編) 対応: GraphQL側については2つ(もしくは複数)にサービスを分けた場合であってもクライアン トからはまるで1つのシステムから情報が返ってきているかのように見せるためにスペース マーケットでは 「Schema Stitching」 ->

    「Apollo Federation」 を用いた方法に変更することで対応 課題: Mainサービスから予約部分を切り出すためには 2つのAPI結果をマージする必要が あった
  18. 18 マイクロサービス 対応の歴史(第2段予約・決済編) 「Schema Stitching」 • 第1段(検索マイクロサービス )の際に取り入れたSchema Stitchingだが、単純に複数システムの スキーマをまとめるだけの機能として使っていた

    • なので1つのリクエストの中に複数のサービスの内容を含めることはできなかった • 複数のシステムが持った情報について例えば予約情報欲しい、スペース情報が欲しい を2リクエ ストとして返却はできるが、1つとして返却することはできなかった • もちろん各システムの前段にある Gatewayにて1つとして扱うようにコードを追加する。具体的には Gatewayにて予約の中にはスペース情報をマージする と言うコードを記載すれば可能であるが、 複数を1つにまとめる と言うことをする時に gatewayを改修する必要がある • さらにはすでにSchema Stichingはduplicatedになっていた
  19. 19 マイクロサービス 対応の歴史(第2段予約・決済編) 「Apollo Federation」 • 複数のシステムが持った情報について例えば予約情報欲しい、予約情報の中にはスペース情報 があるので一緒に欲しい 1つのレスポンスとして返却 することが可能

    • 2つ(もしくは複数)のGraphQL結果をまとめる時に Gatewayを直すのではなく、Gatewayにぶら下 がる各サービスのGraphQL定義を修正する • たとえば、予約のレスポンスに予約とは異なるサービスの room情報を含めたいのであれば予約 のフィールドにはroomがある、そしてroomは別サービスで定義されている。別サービスに Room情 報を問い合わせる時は予約の room_idを用いて引いてきて欲しい。といった記載を予約サービス 側にする。 • 一方でMainサービスでは別サービスからは RoomIDが渡ってくる、そして外部から呼び出した際に 部屋情報を引いてくるというコードを記載する
  20. 20 マイクロサービス 対応の歴史(第2段予約・決済編) 欲しい予約のレスポンス 
 {
 id : 1
 status:

    予約完了
 price: 20000円
 room_id : 100
 room: {
   部屋の名前: 普通の部屋 
   部屋の説明: 素敵な部屋です。 
  }
 }
 
    Room情報
 予約情報
 詳細はGraphQLとマイクロサービスは相性が良さそうな件 〜Apollo Federationを用いたスキーママージについて〜 https://blog.spacemarket.com/code/graphql-apollo-federation/ 合成するものを増やす場合でもGatewayは触らず、 
 個々のサービスに記載を増やす 
 「Apollo Federation」
  21. 21 マイクロサービス 対応の歴史(第2段予約・決済編) REST側はどうしているのか? -> 自前で似たようなことをしている 欲しい予約のレスポンス
 {
 id :

    1
 status: 予約完了
 price: 20000円
 room_id : 100
 room: {
   部屋の名前: 普通の部屋
   部屋の説明: 素敵な部屋です。
  }
 }
 
    Room情報
 予約情報
 mainが返せる部屋レスポンス 
 room: {
  部屋の名前: 普通の部屋 
  部屋の説明: 素敵な部屋です。 
 }
 
    予約が返せる部屋レスポンス 
 {
 id : 1
 status: 予約完了
 price: 20000円
 room_id : 100
  __extend_resource: [{ 
 resource: “Room”, 
 size: “single_default 
 key: 100
 option_params: {}
 merge_params: {}
 }]
 }
    __extend_resourceというレスポンスが含まれている場合 は 該当リソースを別サービスから取得してレスポンス をgatewayでマージする
 ただし、新規エンドポイントやリソースが増えた場合は Gatewayの改修も必要
 (apollo gateway, federation がやっていることを自前で やるので)

  22. 22 スペースマーケットにおけるマイクロサービスの現状とこれから 良かったこと • システムの規模が小さくなったことでバージョンアップがやりやすくなった • 改修する時の領域が明確になった (予約を直したいなら予約・決済システムを直せば良 い) •

    単体テストがとても早くなった (当時は1時間近くかかっていたものが10分未満になった。 分割した時に見直したと言う点も大きい ) • 弊社では今後Rails -> Node.jsに移行しようとしていますが、その時に一部だけ切り出す ことができる土台ができた 課題 • サービス間通信をしたいけどまだできていない • DBを分けていない部分があるので DBスキーマ変更はMAINで行うなどちょっと変な点が ある                       などなど 課題もまだまだある
  23. None