CTOが聞く Vol.8 fluct 大山「広告配信プラットフォームの内部をごりごりと改善しているfluctのエンジニアに話を聞いてみた」

CARTA HOLDINGSで働くエンジニアたちにCTOが「最近なにやってるの?」をざっくばらんに聞いていくシリーズです。今回はCARTA HOLDINGS CTOのすずけん(@suzu_v)が、fluctのエンジニアへ話を聞きました。

インタビュアー:鈴木健太 Twitter ID @suzu_v(写真左)

株式会社CARTA HOLDINGS 執行役員CTO / 株式会社fluct取締役CTO。社内では「すずけん」と呼ばれる。「みんなのGo言語」「データ分析基盤入門」共著者。ウェブ技術全般に明るい。ポッドキャスト「ajitofm」をやっています。

インタビュイー:大山陽耕(写真右)

fluctの広告配信システム、おもに配信に直接関連するシステムで、プログラマティック取引のRTB(Real Time Bidding)に関連を担当。配信チームに所属。文中ではyowcow。

fluctの配信チームでの仕事

すずけん: 今日はよろしくお願いします。fluctにきて5年くらいですか?

yowcow: そうですね、今は6年目になりました。

すずけん: これまで担当してきた開発は、動画・音声広告のRTB 1、RTB での PMP 2 配信基盤、あとは広告枠のマルチフォーマット対応ですかね。

yowcow: そうですね。最近では、RTB仕様のIAB OpenRTB 2.6 3 の対応もやっています。 ほかには、例えばMemcacheDB 4 を別の仕組みで置き換えていったりとか、アプリケーション間通信のシリアライゼーションをMessagePack 5 からProtocol Buffers 6 に変えていったりとか・・・ 外からわかりづらいことをやっていますね(笑)

どのように仕事の優先順位を決めているか

すずけん: ありがとうございます。 自己紹介を兼ねて普段の仕事を教えてもらったわけですが、いわゆるテクニカルなリプレースの話もあれば、機能開発の話もありますよね。 そのなかから何に取り組むかの優先順位は、どういう風に決めているんですか?

yowcow: 週に1回、BizDev (fluct内のビジネスデベロップメント本部) とミーティングをして、ビジネスサイド (エンジニア以外の主にコンサルタント職や営業職側) の声を聞いています。 機能の要望や不具合の共有を聞き、その背景にある技術的な課題や複雑さを整理しながら、fluctが今やるべきことや期待されていることについて効果的な開発や改善を選びながらやっているかんじです。

すずけん: ふむふむ。例えば「ビジネス的に大事なものはやる(優先順位が高い)」ということであればイメージしやすいと思うのですが、そういうことではなくて、システム内部の課題も同様に優先順をつけている。 yowcowさんの脳内タスクリスト的には、そういうさじ加減で順番にまわしているんですね。

yowcow: そうですね。ビジネス的にやったほうがいいことと、技術的にやったほうがいいことって同じテーブルで議論できないことが多いと思いますが、そうならないよう課題の背景について共有し、ミーティングに参加するメンバーでやるべきことややり方を議論するようにしています。

すずけん: ありがとうございます。それを続けているとBizDevのメンバー側からの信頼も高くなっていきますよね。

yowcow: ひとつの議論のなかにも、違う見方があるべきかなと思っていて。アイディアや意見が “直交” しているというか。 例えば、不具合が起こりやすい仕組みがあるときに、都度直し続けることもできますが、その背景が共有されていれば壊れにくいもので置き換えれば良いという見方もできるし、 汎用性の低い仕組みを横に増やして新たなことを実現しする方法もありますが、既存の仕組みを汎用的なものに作り変えることで、仕組みを増やさずにできることを増やす方法もある。 極力ひとつの見方だけではなく、意見が交わるところで議論ができるように意識しています。

すずけん: なるほど。問題の表面だけで議論するのではなくて、裏でなにが起きているかをみんなに伝えて理解してもらって、違う視点を与えるということをやっているんですね。

どのようにビジネスと仕組みを「直交」させるか

すずけん: さきほど、仕組みの汎用性を上げることでできることを増やす話がありました。 実際の課題として、どういうものがあって、どうやって解いてきたかお話をきかせてもらえますか?

yowcow: fluctは十数年続いていて、関わってきた人も多く、その時々によって様々な文脈で手を入れられてきた歴史があります。 さきほど「違う見方があるべき」というところでも話しましたが、仕組みの話も同様で、ビジネス的にやりたいことに対してそれを解決するために動く仕組みが単純で直交していることが大切だと思っています。 そうすることで、仕組みの組み合わせ方によってビジネス的にもできることを増やしていけますが、そうでないと、特定の用途を実現するだけの仕組みがどんどん作られていってしまう。

すずけん: ふむふむ。

yowcow: fluctの仕組みはバナー広告 7 から歴史が始まりましたが、その後ネイティブ広告 8 の取り扱いもはじめました。 私がジョインした当初、バナー広告とネイティブ広告はそれぞれ専用の仕組みで作られていたのですが、そのシステムに動画広告 9、音声広告 10 の扱いを実装していく際、どのように対応するかが挑戦になりました。

すずけん: なるほど、なるほど。

yowcow: このまま動画広告用の仕組みを横に増やしてしまうと、システム全体的をうまく噛み合わせ続ける難しくなってしまうと思い、一度「広告種別」という新たな軸を作って仕組みを組み立て直すことにしました。 ひとつの側面からしか見ていないと見落とされがちなものを、別軸から見るようにして、もう一度再定義した、ということだと思います。

すずけん: ありがとうございます。直交していない機能、つまり専用機能を別々に立てていくと、管理画面も専用になるし、データベースも専用になるし、あるいはAPIというかサーバー側の実装も専用になる。 見方によっては独立して切り離しやすいとも捉えられるけれども、実際には業務のうえでも、仕組みのうえでも、複雑さを生みましたよね。 直交させるか独立させるかというのは、どういう判断軸があるんですか?

yowcow: おそらく、最初にネイティブ広告の対応をしようという話がでたとき、「バナーとネイティブ広告は共存しない」という見方があったと思うんですよね。 ひとつの広告枠にバナー広告とネイティブ広告は一緒に出ない、ゆえに仕組みとしては混ざることはない、と。 けれども、その見方は広告枠それぞれをどのチームが扱っているかというだけじゃないか?とも思ったんです。

すずけん: そうですね。当時はネイティブ広告のチームは分かれていて、最初は本当にビジネス的にも混ざっていなかった。 だから仕組みも独立して作られたんですよね。

yowcow: はい。 しかし、広告枠で本来何がしたいのかという視点で見ると、広告枠にはバナー広告、ネイティブ広告、動画広告など、何が入れられてもいいのではないか?と考えられました。 そうなると、別々の仕組みでは難しかった。 「広告枠に対して複数の種別広告を流せるようにする」と見方を変えていったら、やるべきことがはっきりしたっていうのがありますね。

すずけん: ありがとうございます。今回のケースは「広告枠」というものを捉え直したという話だったのですが、元からあるものを捉え直してリプレースするという点では、いちから作るより大変なはずですよね。 仕組みを変えるときってどういうことを意識して置き換えていっているんですか? 新しい仕組みにどんどん載せ替えていけばいいのかもしれないですが、既存の、専用でつくられているほうが動いていて、そこから移す難しさがあると思っていて。

yowcow: そうですね、けっこう大変ですが、ゆっくりでも徐々に移行していける流れを作るように選んでいるというのはあります。 やっていくなかで僕もけっこう考え方が甘いなと反省させられることは多いですが、オペレーションのチームや多賀さん 11 が業務上の問題やエッジケースを指摘してくれるので、自分の足りていない部分で助けてもらっています。

すずけん: めちゃくちゃわかります。オペレーションエクセレンスというか、オペレーションのチームって本当に「このケースでこの設定すると、こういう挙動になって壊れると思うんですけど・・・」って、設定する前に聞いてきてくれて、テストもしてくれるじゃないですか。 テスターチームとかではないんですけど、やっぱりオペレーションに通じているので「なにを触ったらどうなるか」ということを経験的にわかっている。あのオペレーションチームの気づく力って僕たちエンジニアから見てもすごいものがありますよね。

心臓部をリプレースし、信頼性と開発のスケーラビリティをあげる

すずけん: MemcacheDBの置き換えについても聞かせてください。そもそもMemcacheDBにどんな問題があって、どうして置き換えようとしたんでしょうか。

yowcow: fluctの配信システムの中心で長らく使われてきたのですが、2009年ごろを最後に開発は止まっていて、独自にパッチを当てて使っていました。 そこでMessagePackでシリアライズしたデータを扱っていたのですが、型がしっかりとしていないため、動的型付けの言語で扱うのには常に不安がありました。

すずけん: うんうん。

yowcow: そんな頃に、MemcacheDBがおこなっていることを3つのコンポーネントに分解してGoで実装したところ、いいかんじに作れた。 12

  1. 与えられた任意のファイルを発見してロードするインターフェイス
  2. 任意の形式のファイルを読み取るインターフェイス
  3. 任意のプロトコルで通信するインターフェイス

ただ、MemcacheDBに課題はありましたが、そのままを置き換える理由は無かったので導入はしていませんでした。

すずけん: つまり始めは、(Goでの実装を)個人的に実験していたかんじですよね?

yowcow: そうです。その後、ajiyoshiさん 13「型がちゃんとしたデータをストレージとして使えるようにしよう」という開発を始めたとき、この仕組みに乗っかることになった。 その際、バックエンドで扱うデータベースは BoltDB 14、通信方法は gRPC 15 が選択されました。

MemcacheDBとromdbの対比。romdbではstorageを任意の仕組みに入れ替え可能。

すずけん: (世の中でいう)Memcacheってキーバリューストアだけど、僕らがほしいものはキーバリューストアから単純に値をとってくるというよりも、当時ちょっとしたロジックもDBのフロント側でできたほうが、配信側でひくときに便利だねって話をしたような気もします。 たしかromdbにのせるということをしたんじゃなかったかな?

yowcow: はい。単純にデータをひくだけじゃなく、ロジックを持ったAPIにできるとより便利でした。 それなりに速く動き、データストアを扱い、ロジックを持ったAPIをもち、複数のアプリケーションから参照できるサービスを作るにはちょうどよかったです。

サービス間のプロトコルを置き換え、段階的に堅牢にする

yowcow: 最初gRPCで会話するのでいいよねということで作ったんですけど、gRPCをうまくクライアント実装できる言語がまだ少なかったため、その後HTTP上でProtocol Buffersをやりとりするインターフェイスが追加されました。 さらに、パフォーマンス最適化のため独自TCPプロトコルを作って移行しました。 データストアの方も、BoltDBからajiyoshiさんのTRIE木のデータストア 16 に変更され、BoltDBインデックス作成のボトルネックが解消されました。 単純なコンポーネントの集合なので、こういった変更は容易でしたね。

そんなことをしていたら、データストアとしてスタートしたromdbが、今はロジックを自分たちで実装できるアプリケーションサーバになってきました。 このまま必要な機能をromdb側のエンドポイントで実装し続ければ、現在romdbを参照して動いているPerlのアプリケーションを最終的には引退させられると思います。

すずけん: これはromdbを作った当初、まったく予期していなかったシナリオでしたよね。「型があって、簡単に書けて、デリバリーも簡単で、テストもしやすい」というromdbのレイヤーが、ただのデータベースサーバーから、データベースをラップしたAPIサーバーというか、ストレージレイヤーになったことで、そっち側に機能を寄せられるという、このリアーキテクティングは、本人たちも予想していなかったですが、思いの外うまくいっていますよね。

読んでいる人向けに補足すると、Perlのアプリケーションっていうのは、fluctの配信サーバーのほぼすべてのロジックといっても過言ではない、心臓部なんですよね。 10年以上積み重なったロジックたちがたくさん載っていて。 それを書き換えるということは、配信系を書き換えるにほぼ等しく、なかなかできなかったんですけど。でもromdbを入れてから、どんどん元のアドサーバー、Perlが持っていた機能が薄くなって、今も減っていってますよね。

yowcow: Perlのアプリケーションは今後退役する流れなのですが、確実に進められるように今積極的に手を入れていて、最近はRTBシステムとの通信部分のシリアライゼーションをProtocol Buffersで置き換えました。 先にインターフェイスを整えることで、移行を進めやすくしていますね。

従来のサービス構成とプロトコル

置き換え後のサービス構成とプロトコル

すずけん: ありがとうございます。今日のインタビューは、やっている仕事の全体像からすると一部だし、エピソードを拾っているだけなんですけども。 仕事の内容としては、ドリルダウンした先にそこのアーキテクチャを変えるみたいな話が多いので、インタビューでどれくらい伝わるかわからないですけど・・・。 でも、やっていることってこういうかんじですよね。

yowcow: そうですね。うん。たしかに、広告種別の話と、古くなっていくアプリケーションの話って、全然違う話なんですよね。

すずけん: そう。全然違う話なんだけど、事業とかプロダクトを作るうえでは、全然関係していないわけではなくて、実は両方つながっているんですよね。

yowcow: 普通の会社だったら別々のチームがやっているかもしれないですね。

すずけん: でもまあ、なんとなく伝わるといいなと思って載せておきます(笑)

「何が重要か」をチームで理解する

すずけん: ここまで聞いてきた、yowcowさんの仕事内容って、一般的にはいわゆるビジネス側で取りまとめていたり、マネージャーがやっていたりしそうなものもありますよね。

yowcow: 僕はエクストリーム・プログラミング (XP) が好きなんですけど、XPでは技術的な部分も含めてビジネスとしているので、チームの関心事であるのがいいと思うんですよね。 なので、ひとつの議論にいろんな専門性を持った人が参加していて、そのチームとして重要だったり大切だと思うものの順番や方法を選んでいければいいのかなと思います。

すずけん: めちゃくちゃわかります。 XPでもありますけど、それこそ他のメンバーの尊重みたいな話でもあると思っていて。 チームに対して「こういうデメリットがあるよ、複雑なままだと次はこうなるよ」と共有するのもそうだし、yowcowさんは自分でもリリースしてみてどうだったかというのを見られているわけで、そのうえで次どうしようかと考えていますよね。 なので「それはビジネスの人たちで決めてくれ」ではなく、自分たちが決めて作って、結果を受けてまた作るものを変えていく。 それを地(じ)で行っている。感覚的にはそういうかんじですよね。

yowcow: そうですね。技術的にやったほうがいいことだけをやっているわけではなく、何がいま事業的に重要なのかを元にやることを決めています。 そのなかには、やったほうがいいけれども、今はまだ踏み込まないほうがいい部分もあって、そういう途中までしか整えていないものもいっぱいあるんですよね、アプリケーションのなかに。 なにかきっかけがあったらその先も整えようというのをあちこちに散りばめておき、いろんなタイミングで回収しているかんじはありますね。

すずけん: めちゃくちゃわかりますねー。踏み込んで完全に100まで解決すると、残り80くらい時間を積まなきゃいけないけれども、わりときれいにするところまでなら20の時間でいけるみたいな。 なので僕もちょこちょこ、ここまではきれいにしておくか、というのはやっていましたね。

yowcow: すずけんさん、よくコメントに書いていますよね。 ここまではやるけど、ここから先はまだわからないから置いておく、みたいな。

すずけん: そうそう。ありますね。 さてここまでの話は、だいぶまとまりましたかね?(笑) マネージャーではなくて、いわゆるいちソフトウェアエンジニアとしてシニアポジションにいるメンバーが、普段なにをしているのかというのは謎なんじゃないかという仮説がありますが、その点はすごく伝わったんじゃないかなと思います。

こういう人にきてほしい

すずけん: 最後に、yowcowさんとしてはどんな人にチームにきて欲しいですか? こんな人がチームにいたらいいなというイメージがあれば教えてください。

yowcow: 課題を発見して、解決を進めてくれる人がいると嬉しいですよね・・・・・・当たり前のことを言ってますね(笑)

すずけん: いえいえ(笑) 「小さい・大きい・早い」でいうと、課題をスピーディにこなしてくれるということですか?

yowcow: うーん。イメージ的には、エンジニアのアウトプットって、依頼されたとおりに作って完成、だとおもしろくないじゃないですか。 何かをアウトプットするときって、すでに存在している課題とか周辺にある問題を、その時々のタイミングで刈り取りながら何かを実現していく、というふうにやるのがおもしろいと思うんですよね。 なので、そういう発見をしてくれたり、そのうえで解決方法を決めたり作っていったり、そういう道を切り開いていく人がいるとすごく楽しいと思います。

すずけん: めちゃめちゃイメージがわきますね。 「このプロダクトには今こういう状況で、ここに課題があって、こっちにもあっちにも直したほうがいいところはある」というときに、新たな課題がぽーんと飛んできて、じゃあどうするか。 そのときに、その人の判断力が問われると思っています。 状況把握能力が高くて、実装に移していける力もあるんだけど、全部の課題を一気にきれいにすることはできないから、次に対してより良くなる方法でまわして実現していく。 そんな力がある人という解釈をしました。

yowcow: そうですね、そうですね。

すずけん: すごくイメージできました。ということで、判断力のある人をお待ちしています。今日はありがとうございました!

PR

fluctではエンジニアを積極大募集中です。 hrmos.co hrmos.co hrmos.co

まずはカジュアルにお話してみませんか? hrmos.co


  1. バイナリ形式のオブジェクト・シリアライズ フォーマットの1つ。 https://msgpack.org/ja.html
  2. Private Market Place https://markezine.jp/word/detail/PMP
  3. Protocol Buffers。構造化データのシリアライズフォーマットの1つ。定義言語をもち、各種言語向けにシリアライザ・でシリアライザを生成できる。
  4. fluct開発チームのメンバー。
  5. バイナリ形式のオブジェクト・シリアライズ フォーマットの1つ。 https://msgpack.org/ja.html
  6. Protocol Buffers。構造化データのシリアライズフォーマットの1つ。定義言語をもち、各種言語向けにシリアライザ・でシリアライザを生成できる。 https://developers.google.com/protocol-buffers
  7. https://markezine.jp/word/detail/%E3%83%90%E3%83%8A%E3%83%BC%E5%BA%83%E5%91%8A
  8. https://markezine.jp/word/detail/%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E5%BA%83%E5%91%8A
  9. https://markezine.jp/word/detail/%E5%8B%95%E7%94%BB%E5%BA%83%E5%91%8A
  10. https://markezine.jp/word/detail/%E3%82%AA%E3%83%BC%E3%83%87%E3%82%A3%E3%82%AA%E5%BA%83%E5%91%8A
  11. fluct開発チームのメンバー
  12. https://github.com/yowcow/goromdb
  13. fluct配信チームのエンジニア。 通称あじよしさん
  14. Go で実装された key-value データベース。 https://github.com/boltdb/bolt
  15. Protocol Buffers を使う RPC 技術。 https://grpc.io/
  16. https://github.com/ajiyoshi-vg/hairetsu