Stailerを支えるアーキテクチャ

by

@wapa5pow

Stailer」は株式会社 10Xが提供する「開発不要でネットスーパーアプリを立ち上げられるシステム」です。バックエンドとそれにつなげるアプリ(iOSAndroid)を提供しています。

screen

10Xではよりよいチームを目指しエンジニアも含めメンバーを募っています。エンジニアが気になるどのような技術を使っているかに関して今回このブログで紹介しようと思います。少しでもチームに興味を持ってもらえたら採用ページがあるのでぜひぜひこちらからご応募ください。

tl;dr

  • インフラはGCP
  • クライアントはFlutter(Dart)でサーバもDart
  • サービス間通信はgRPC
  • 分析環境はBigQuery/Redash/Digdagの組み合わせ
  • 監視はCloud Monitoring

アーキテクチャ

overview

Stailerは主なサービスはGCP上に構築されています。認証やログなどでFirebaseを使っています。商品検索などではElasticsearchを使っているのでElasticsearchのマネージドなサービスであるElastic Cloudを使っています。

タベリーのときと同じように、サービスをデプロイする先としてGoogle Kubernetes Engine(GKE)を使っています。タベリーのときに学んだ資産を活かし各種改善したアーキテクチャになっています。

クライアントアプリはFlutter(Dart)で書かれており、クライアントと通信するサーバもDartで書かれています。クライアントもサーバも同じコードでかけます。クライアントとサーバはgRPCで通信しています。

Cloud Runもマイクロサービスのような形で走っておりこちらはスクレイピングのようにブラウザを操作するコードが動いているのでTypeScriptで動いています。サーバからアクセスされますがこちらもgRPCで通信しています。

データベースにはCloud Firestore、Cloud Firestoreに書き込んだデータをElasticsearchに同期させるためにCloud FunctionsのDatabase Triggersを利用します。同期する必要のあるデータだけFirestoreからElasticsearchに書き込むようになっています。

Firebaseはユーザ認証・プッシュ通知・行動ログなど幅広くつかっており、ログをBigQueryにエクスポートして分析しやすくしてあります。

監視はCloud Monitoring/Cloud Logging/Cloud Traceを使っています。Cloud MonitoringはGKE内にあるPrometheusを通してメトリックスを取得しサービスの状態をグラフィカルに表示します。以前、GKEをCloud MonitoringとPrometheusでちゃんと監視するで詳細を書きました。
Cloud Loggingにはありとあらゆるログが入っています。GKEでは標準出力・エラー出力にログを出せばそのままCloud Loggingにログが送られるので便利です。フィルタしてBigQueryにエクスポートすることもできるので見つけにくいエラーがあったときはログをBigQueryに送り統計的にあたりをつけてデバッグしたりしています。Cloud TraceもGKEとCloud Runで走っているサービスをともにTraceできるのでデバッグに役立っています。

サービスアーキテクチャ

service

クライアント(iOS/Android)に関わる部分のサービスのアーキテクチャはシンプルに表すとこのようになっています。今回は複数のサービスが連携しているのでIstioを入れました。がっつりIstioを使うというよりかは薄く必要なものだけ使っています。Istioは結構複雑で管理するのが大変なので軽めにしてあります。Istioはレスポンスヘッダの値を変えたり監視メトリックスも設定すれば自動でとれるので結構便利です。

クライアントとサーバはgRPCで通信します。両者ともDartで書かれているのでProtocol Bufferを変換したコードが同じなのですんなりクライアント・サーバのコードがかけて楽ちんです。ただDartのgRPCライブラリであるgrpc-dartがいまいちコミットされていないのでインターセプターの機能が弱くて辛いところもあります。他にも辛いところとしてGCPのサービスのSDKがない場合が多いです。その場合はAPIが定義されたProtocol Bufferをコンパイルしてそれをパッケージとして取り込みサービスを呼び出します。Firestoreを始め多くのものがそのように呼び出しているのでなかなか面倒ですがそこが楽しくもあります。

サーバからマイクロサービス的な動きをするCloud Runにリクエストを投げることもあります。Cloud Runは最近gRPCが使えるようになったので、インタフェースをProtocol Bufferで定義できて楽です。Cloud RunはECサイトにつなぎにいき各種情報を取得してサーバに返します。数秒以上にわたってリクエストが投げれることもあるのでタイムアウトの値に気をつける必要があります。gRPCの場合はESP v2を使っているのですがCloud Runのタイムアウト設定だけでは足りずCloud Endpointsの設定で以下のように記載する必要があります。役立ちそうなひとはいない気がしますがひとまず共有まで。

title=endpoints.yaml
...
backend:
  rules:
    - selector: "*"
      address: example.com
      deadline: 60

CronJobsはさまざまなcronがあるのですが主なものとして、ECサイトの商品のスクレイピングをしています。KubernetesではCronJobsのメトリックスも取りやすいので楽に管理できます。

WorkerはCloud PubSubを購読して処理をします。

分析系は以下のサービスをKubernetes上で動かしています。

  • Redash
  • Digdag

インフラ系のサービスも各種いれています

  • Prometheus: Cloud Monitoringへのメトリックス転送のため使っています。
  • Grafana: Cloud Monitoringで基本監視はするのですがメトリックス転送のお値段が結構するのでCloud Monitoringに送っていないやつはGrafanaで確認できるようにしています。
  • cert-manager: HTTPSにするための証明書を取得するために使っています。Cloud DNSを使っておりDNS-01 challengeでできるので楽です。
  • Config Connector: GCPのリソースをk8s上で管理できます。たとえばk8sのリソースを定義するとGCSのバケットを作れたりします。なるべくコードで管理したい場合はConfig Connectorが便利です。これによりステージング環境では作ったけど本番では作るの忘れていたみたいなことがなくなります。
  • Kubernetes External Secrets: GCPのSecret Managerと連携してその値をk8s上のSecretとして扱うことができます。他にもSecretを生成するサービスはいろいろありましたがこれが一番シンプルで使いやすかったです。

その他、固定IPを利用できるようにkubeIPを入れています。これはノードのIPをGCPの予約されたExternal IPで固定するためのものです。ノードが数台しかないときはこれが便利です。ECサイトの業者と連携しており固定IPでフィルタされているときに使えます。

まとめ

リリースしたばかりのStailerのアーキテクチャを紹介しました。

まだまだ紹介したいところとしてソースコードはどのように書かれているかなどありますが、もし知りたい場合は採用ページがあるのでぜひぜひこちらからご応募ください。実際に入社を検討するまえに一緒に働く機会もつくれるのでそこでソースコードについて実際に見たり議論したりできます。お待ちしております!