こんにちは、Sansan Engineering Unitの部長を務める、笹川 裕人です。今回で4回目となる「Sansan Tech Talk」はSansanのテックリードたちが直面している技術的な課題や取り組みについて深掘りする連載企画です。今回は営業DXサービス「Sansan」の「データ連携ソリューション」オプションの一機能であるSansan Data Hubの開発に携わっている藤原 雄介にインタビューしました。
▼連載記事はこちら
buildersbox.corp-sansan.com
笹川:今回のゲストは、Sansan Engineering Unit Data Hubグループの藤原 雄介さんです。 藤原さん、まずは自己紹介をお願いします。
藤原:Data Hubグループの藤原です。よろしくお願いします。 私自身は、ソフトウェアエンジニアを始めて20年くらいになります。最初は、Webアプリではなく、.NETによる自社フレームワークやミドルウェアの開発をし、大規模なシステムのアーキテクトやIoTの連携基盤などの仕事をしていました。また、オフではシリアライザーのOSSを書いたり、ライブラリやランタイム関連の洋書の翻訳をしたりもしました。そんな中、お客様の直接の課題をその都度解決していくのではなく、 プロダクトという形で価値を提供する仕事に関わりたいと思った時に、 Sansan Data Hubに出会いました。
笹川:ありがとうございます。藤原さんは、当初SIerにいて、長く勤めた後に、初めての転職でSansanに転職してきて、ちょうど1年ぐらいですよね。
藤原:そうなります。カジュアル面談や面接で話を聞いていると、リソースの制御や分散処理といった分野に課題感があることがわかりました。その領域であれば、自分のスキルを生かしてSansanのビジネスに貢献できそうだと確信していたので、初めてにしてはスムーズな転職ができたのではないかと。
笹川:Sansanには中途入社で藤原さんのように早々に活躍している人が大勢いますよね。まず始めに、藤原さんが担当しているSansan Data Hubについて紹介してもらえますか?
プロダクトについて
藤原:私が担当しているSansan Data Hubは、企業にあるさまざまなマーケティングデータ、具体的にはSalesforceや企業独自のシステム内にあるデータを集め、整理し、情報を追加して書き戻すプロダクトです。これ以降の話の前提となるアーキテクチャの構造を説明しますと、Sansan Data Hubはデータ処理のパイプラインと、一部の設定を管理する画面という構成になっています。パイプラインはMicrosoft AzureのFaaSやPaaSを組み合わせ、非同期のメッセージベースのマイクロサービスアーキテクチャで実装されています。
パイプラインの品質保証
笹川:ありがとうございます。この連載では、プロダクトが直近抱えている課題などについて聞いています。ということで早速ですが、藤原さんが所属しているData Hubのプロダクトについて、今後取り組んでみたいチャレンジや、解決したい課題はありますか?
藤原:課題はいろいろありますが、せっかくなのでデータ処理のパイプラインという観点で2つお話しします。
まずは品質保証の話。Sansan Data Hubはデータパイプラインのプロダクトです。新しい機能を加える場合、ユーザーに見えるのはパイプラインの出口から出てくるデータであり、そのデータを作る処理は上流に存在します。このとき、上流の変更を下流に伝えるパイプライン全体に影響がないこと、下流が想定通りに動作することを確認していく必要があります。ここをいかに効果的、効率的に行っていくかの話です。
もうひとつは、システム全体でのリソース制御についてです。上流と下流を連携して制御して行く必要があり、単に特定のポイントだけ制御していくだけではうまくいかないことが多くあります。
IaCの分割によるテストの効率化
笹川:データバイプラインの品質保証の観点で、その品質保証を効率的、効果的に行うというと、意味のある単位で行うという視点もあると思います。この二軸で改善したいのだと思うのですが、 逆に言うと今までのテストだとどのような点が不十分なのでしょうか?
藤原:はい。上流の変更が下流に不都合を起こしていないかの確認ですぐに思い浮かぶのは結合テストだと思います。結合テストの課題について深掘りすると、結合テストを行うために複数のマイクロサービスをデプロイする必要があります。パイプラインが長くなると、どうしてもその準備にも実行にも時間がかかってしまいます。
笹川:時間がかかるというのは感覚的な部分があるので、具体的にどのくらいなのかを知りたいですね。単体テスト全体であれば数秒で終わってほしいし、E2Eテスト全体なら数十分になっててほしいとか。
藤原:現状のE2Eテストは手動で実施していることもあり、環境のセットアップから初めて、最低でも3日はかかります。これをまずは1日、ゆくゆくは1~2時間程度にしたいです。現在は、パイプラインを流すE2Eのリグレッションとして、CSVを取り込んで、パイプラインが最後まで流れるかの確認で1ケースあたり数十分かかります。そして、何よりパイプライン全体を準備する必要があります。これはリソースのプロビジョニングやアプリのデプロイに加え、関連するデータベースのレコードの投入なども含みます。
笹川:なるほど、それだと、テスト項目の数が少なかったとしても時間がかかってしまいますね。ちなみに、E2Eの完全自動化は考えていませんか? テスト項目が決まっていればテストは自動化できるかもしれないと思いました。本体の変更への追随に追われてしまっては本末転倒なので、自動化は慎重に考える必要があるとは思いますが。
藤原:1~2時間の世界にするにはE2Eの完全自動化が必要になります。理想論を言えば、自動E2Eテストですべての条件を網羅できれば、速く安全なサービスを提供し続けられます。とはいえ、おっしゃるように本体の変更への追随のコストもかかりますし、そもそもパイプラインの入力に対して関連するデータのパターンを加えると、どうしても組み合わせが膨大になります。これでは、自動化の着手すらままなりませんし、そもそも手動でもとても実施できない量になります。そのため、現在は2点間の結合テストを中心に手動で行っています。自動化についても、最初からE2Eを自動化するのではなく、この2点間結合テストの自動化を進めていきたいと思っています。
笹川:なるほど。そのようにして小さな依存間のテストに限定して実装するということと、さらにテスト実行のためのプロビジョニングを速くできるようになると、どのくらい短縮されますか?
藤原:そうですね。 小さな依存間、具体的にはあるマイクロサービスによる変更の影響が隣接マイクロサービスに影響がないかのテストであれば、その日のうちにテストの準備をして、テストケースを一通りこなして…、というのを半日、早ければ1時間で一通り終わらせるループを目指したいです。プロビジョニングにはどうしても時間がかかるので。
笹川:プロビジョニングは結構難しい構成になっているんですか? たとえば、テストしたい2点のみピンポイントにプロビジョニングするならその時間を達成できるように思えます。
藤原:今のIaCの構成は全体としての整合性を重視しており、ピンポイントなミニ環境をプロビジョニングできるようにはなっていません。もちろん、毎回プロビジョニングしていては大変なので、あらかじめセットアップされたテスト環境があって、それを一部更新して利用しています。そして、その環境の更新やデプロイするアプリは他のチームと重ならないようにする必要があります。
笹川:環境が1個しかないから、ぶつからないようにしないといけないってことですね。
藤原:はい。とはいえマイクロサービスアーキテクチャであり、個々のサービスのコードは独立してデプロイできる状態です。そのため、多くの場合は、勝手にアプリをデプロイして、 勝手にIaC上の設定を変えても成り立つんですけど、 そうでない場合は調整が大変になります。最近はAzureプラットフォームの世代交代の時期でもあり、そのテストでは実際に調整に苦労しています。また、個々のサービスがキューを介して通信しているとはいえ、パイプラインの上流の変更は下流に影響を与えることはあります。その場合もテスト環境の調整が必要になります。
笹川:教科書的には、マイクロサービスアーキテクチャのフィーチャーの開発では、 独立に変更やテストが実行できる状況になるはずですが、パイプラインになっているので上流から下流への影響があるので、 テストに支障をきたすみたいなことが起きるということですね。
藤原:はい。理想的にはそのあたりもきれいに独立しているべきなのですが、現実にはうっかり依存関係が混ざりこんでいたりします。なので、きちんと下流のリグレッションテストもしないといけない。もちろん、これらの問題をそのまま放っておくつもりはなく、まず部分的なプロビジョニングを実施できるように、IaCを分解していく取り組みを始めています。その一方で、うっかり下流のサービスの基盤更新のプロビジョニングが漏れたとなると大変なので、変更のまとまりを一度にプロビジョニングできるようにもしておきたいです。
笹川:なるほど、なるほど。面白いですね。
藤原:ここで、どういった単位で基盤を分解するかという議論もあります。たとえば、変更される単位のまとまりとして、たとえば担当チームの単位でわけるというのはひとつのパターンです。ただし、Sansan Data Hubではあえてチームで担当範囲を分けていません。なので、担当チームで分けるのではなく、マイクロサービス群をある程度のまとまり、ドメインの境界で分けていくことを考えています。あとは、単純に複数環境を作るとなるとコストはかかりますし、小まめに削除するとなると再構築の時間がかかります。クラウドリソースごとに課金体系やプロビジョニングにかかる時間は異なるので、きちんと計測して、一歩一歩進めていこうと思っています。
笹川:そうですね。ちなみに、分解であれば規模も考慮すると1、2カ月くらいかなと思いますが、どのぐらいのスパンで考えていますか? たとえば、今の改修って、インフラ間で複数テスト環境ができればとりあえず独立したテストが実行できるようになると思うから、 価値は大きそうな気がしていて。
藤原:現在のData HubのIaCは再利用性を重視するあまりかなりの複雑度になっているので、 再設計を含めて3カ月くらいかかってしまいます。早く成果につながるよう、まずはIaC自体をレイヤー化して分離しようとしています。基盤の中のさらに共通の基盤部分と個別部分を分割して、プロビジョニングしたい部分を分ける。そのうえで、よくテストで使うところから順次整理していこうとしています。リファクタリングですね。
笹川:なるほど。IaCのリファクタリングは大変ですが、今回目指す変更は価値が高そうなので頑張って進めたいですね。
大量データ投入時のリソース制御
笹川:少し話を変えて、Data Hubは大規模なデータを扱うと聞いていますが、その観点でも話を聞きたいです。ある特定のジョブがリソースを占有してしまい、ユーザーに影響してしまうといったことが考えられそうですが、そのような課題はないのでしょうか?
藤原:あります。なので、リソースの制御を強化していきたいです。 データ連携システムなので、さまざまな要因により、平常時をはるかに超えた量のデータが連携されてくることがあります。そういったときに、単に「余剰リソースを確保しておきます」ではなく、うまくリソース使用量の制御や、普段とは違う状態になっていることをユーザーにフィードバックをできないかと考えています。場合によっては、大量のデータ投入がユーザーが意図していない問題により引き起こされる場合もあるためです。また、パイプラインは単純な一直線ではなく、複数の入力を結合したり、複数の出力に結びついたりします。そのため、単に自動的なスケーリングを実施するだけでは、思わぬところにしわ寄せが行く可能性がありますし、単独のリソースの負荷を見るだけでは適切な制御にならない場合があります。そのため、自分の状態だけを見るのではなく、下流の状態を見て上流をコントロールしていくような仕組みを徐々に取り入れているところです。
笹川:なるほど。いわゆるフィードバック制御ですね。
藤原:はい。そしてそのためのオブザーバビリティも強化しています。
笹川:現状の計測は十分ではないという感じですか?
藤原:十分とは言い難いです。 いわゆる普通の計測、 CPUの使用率、 キューのメッセージ数とか、 滞留時間などは見ています。 ただし、マイクロサービスのサービス数が多くなってくると、個々のメトリクスを俯瞰するのは難しく、より抽象的な単位で見ていきたい状況です。そのため、より意味のあるタイミングや粒度でのメトリクスを取れるようにする改善を行っています。また、先ほど話に出たフィードバック制御の派生として、 人間が見るのが無理なら、 機械にやらせるしかないということで。
笹川:監視やアラートのロジックも、 流量制御ロジックとして自律実行させるみたいな。
藤原:そうですね。
笹川:それは結構面白そうですね。
藤原:こういった、実際に運用して出てきた課題に対して、優先度をつけて対応していくというフィードバックループを回せるのがDevOpsの醍醐味ですね。
笹川:この流量制御、発想を逆にして自動スケーリングをするのもありではないでしょうか?
藤原:それ自体はやっています。
笹川:あとコストとのバランスって感じですかね。
藤原:はい。コストとのバランスはあります。また、パイプライン構造の場合、どこかを緩めると、 ボトルネックが移動する場合があります。なので、安全なところは自動で、そうとは言い切れないところは運用担当者が見極めながら調整しています。ここでもフィードバック制御の考え方を導入できないかと考えています。
笹川:なるほど。 今は一旦そこを維持したまま、 時間方向に伸ばすことで、 対応しようとしていると。
藤原:はい。あとはパターンによって取るべき対応は異なります。先ほど言った、 うっかり大量のデータが来てしまう事象を考えると、流量制御の方が最適な解決策になります。
笹川:データパイプラインに流れてくるデータの種類に応じて、 時間方向に伸ばしていいものだったら伸ばして、 システムを維持しているという状況が理想的だし、 そこのスループットにとても価値があるのであれば、 瞬間的にお金をかけても流す方向に動かすだろうし。また、 意図しない大量データなのであれば、 ユーザーにお知らせしなくてはならない、 みたいなところをうまく制御する。
藤原:その通りです。
笹川:リソース制御の話は結構面白いですね。リソースのスケーラビリティという観点だと、一般にボトルネックになりがちなデータストアの構成をどうしているのかは気になります。
藤原:Sansan Data Hubではさまざまなデータストアを用途に応じて使い分けています。たとえば、SQL Database ElasticPoolというAzureの機能があり、これは計算リソースをプールという単位で管理し、同じプールに割り当てた複数のDBで共有するというもので、DB単位での水平分割と、計算リソースの集約によるコスト節約を両立するものです。ただし、たとえばテナントごとの水平分割をしたときに、同じプールを使用する他のテナントが計算リソースを占有する可能性があります。メッセージはキューに入ってくるので愚直にFIFOで処理すると空いているプールへのディスパッチが非効率になります。テナントを見て負荷をうまくコントロールするようなミドルウェア的な機能を開発したりしています。
笹川:なるほど。 他の、同じプールを使っているネイバーに邪魔されないような仕組みを実装すると。今の話を聞いていると、 大量のデータと大量のクライアントというかユーザーに対して、 最大限サービスを提供しきるみたいなところのために、 いろいろ細かい改善を繰り返しながら、 改善をどんどん続けているみたいなところが結構ありますね。
藤原:まさにそうですね。10年くらい前に、クラウドは1個のでっかいOSだみたいな話がありましたよね。
笹川:ありましたね。
藤原:少しはその気持ちがわかってきた気がします。 やっぱりリソース制御をして全体として破綻しないようにしつつ、 ビジネスとして成り立つようにする。反応が悪いOSはイライラする。まさにクラウドOSに片足を踏み入れた気分です。
笹川:そこはうまいこと、ユーザー体験を考慮して、 動いているような状態は維持するとかみたいなところですね。このあたりの改善はビジネスの価値にも直結する部分なので頑張っていきたいですね!
藤原:やりましょう! 本日はありがとうございました。
笹川:ありがとうございました!