ブログ、世界一継続するのが難しい趣味。僕の周りも三日坊主しかいないし、僕自身記事を書いても読み直して幻滅して消します。はい。
<追記 2019.2.22> 完結に知りたいならこっちの記事がおすすめやで~
なんやねんこれ
今回は変わったインターンに参加してきました。
架空のサービスのアーキテクチャを考えるというものです。仕様書が与えられて、その仕様を満たしつつ、冗長性だとか拡張性だとか変更容易性とかが高まるようにアーキテクチャを考えます。手が動かないという致命的な欠点を持つ僕にとってはこれほど素晴らしいインターンはありません(手が動かないことは無いんですが、趣味でやると中途半端にいろんなものに手を出しすぎてしまいがちです)。 概要はこんな感じ。
サービスの仕様と特徴
とりあえず仕様はこんな感じです。
割と普通の仕様だとは思いますが、いろんなデータの依存関係がありますね。ライブ単位で切り出せるところがあったり、データのアクセス頻度なども考える必要があります。また、細かい部分の仕様はよくわからないので、ある程度質問したり想像で補ったり、ライブ配信サービス全体ではなくあくまでその一部のチャット部分のアーキテクチャだけを考えなければいけないというハマりどころがあります。
後で知ったんですが、OPENRECのアーキテクチャを参考解答として考えていたようです。それはまぁそうだろうなぁという見当がついたんですが、まさかネット上に落ちているとは……
TeaBreak インターン合格まで
このインターン、短期(二日間)なのに書類審査だけでなく面接まであるので最初はビックリしました。なのでその内容についてざっくり書いて置いた方が参考になるかと思います。
地方の人には交通費やホテルの手当てがあって、渋谷の一等地で実際にサーバーエージェント社で働いているエンジニアからいろいろとアドバイスを貰ったりするので、それなりに手間がかかっています。なので当然審査も丁寧にやります。そういう意味では会社のエンジニアと交流もできる良いインターンです。応募を考えている方は是非お勧めします。
で、書類審査はともかく面接の内容についてですね。質問内容について具体的に書くとアレ()なんですが、印象としては「採用面接か?」といった感じでした。面接を担当をするのは「技術担当人事」なので、「バブルソートの計算量オーダーは?」とか「OSI参照モデルとは?」みたいな質問は来ません。ただ、将来のキャリアについてどのように考えているかであったりの部分で深く突っ込まれたので、「二日間タダでディズニーいけるぞ~↑↑↑↑」くらいに思っていた僕は完全に面食らってしまいました(笑)
Day1 設計の方針
というわけで一日目です。3~4人のチームで行うのですが、生活力0の僕は徹夜で本番を迎えてしまいました。そしてもう一人が体調不良で離脱してしまいました。片方が死んでる二人三脚でこのインターンを乗り越えなければいけません。絶望的です。
一日目は仕様をある程度切り分けてザックリとしたアーキテクチャを考えました。ちなみにAWSを採用しました。仕様に対する解釈は以下の通りです。
- ライブの状態情報や会員の情報などはライブに問い合わせてすぐに返答が返ってくるものとする。
- 連投制限やBAN(最初の仕様書にはあった)は、ライブ毎に依存せず、高々10分間分のデータを確認するだけで良いので、一括で処理をしてからデータベースに格納すればよい。
- 管理者的な立場が行うオペレーションは頻度が低くリクエスト数が安定しないため、lambdaを使う。
- ライブ中のコメント配信はWebSocketを使う(当たり前)
- とにかくコメントが投稿されて表示されるまでのパフォーマンスをいかに高く保つかを考える。
- フロントエンドでできることはフロントエンドで行う(新規登録者の非表示)
後はずっと情報収集の時間が多かったですね。コメント周りはDyanamoDBを使ったり、連投制限用にMemchachedを使うという風に少しずつ詰めていきました。コメントの基本的な処理はこの時はEC2をフル活用と言ったところです。また、ブロックリストやNGワードはDynamoDBを使用していました。
Day2 改良
この後はひたすらボトルネックを探したり、仕様上の問題を探したりします。
Q コメントされる度DynamoDBからブロックリストとか取り出して処理すんの?
A ある程度キューにしてまとめて処理しても良いけど、ブロックリストとかNGワードってチャンネル依存の情報が多いからk8s使ってまとめて持っちゃった方が良いな? でこの後ライブ毎のPodにして、そこからさらにキャッシュ用Podに切り分けたりしました。
Q てかこれ、前のコメント参照するときどうすんの?
A NGワードとかの加工をしたあと別テーブルでDynamoDBに保存しよう。後、過去のデータ参照するためにコントローラー用のPodが必要な気がする。コントローラー用Podはメモリにキャッシュしながらまとめてコメントを流す実装が必要。
Q リアルタイムでNGワードとかブロックリストの反映できるの?
A コントローラー用PodがmemcachedPodとライブの対応付けをしてるから大丈夫
Q コントローラー用Podが単一障害点になってない?
A なのでRedis搭載してレプリケーションする必要がある
Q コントローラー用PodにRedisとアプリケーション二つコンテナ載せてるけどそんな構成大丈夫なの?
A あぁーmemcachedが落ちたとき一旦いろんなリストを一時的にキャッシュしたり、ブロックリスト一気に更新したりとか、アプリケーションのデプロイ時にいろんな処理が必要だなぁとか考えるとバッチ処理用Podを常駐させた方がいいなぁ
といった感じであーだこーだ言いつついろいろ修正しました。その細かい経緯はメモを取っていなかったので覚えていません。
議事録って大事ですね!
ザックリアーキテクチャ
描きなおしたら逆にわかりにくくなったわ草。調子乗ってGIMPとか使ったけどペイントで良かったわ!。ちなみに、VPCとかその他細かいものは除いています。
見てほしいのは赤い線で、赤い線にはRDBなど遅いDBにアクセスする経路がありません。また、存在するLiveであるかどうかであったりはRedisで適度にキャッシュするか、配信本体で高速に応答できれば大丈夫でしょう。この時に24時間以内のユーザーかどうか判断することができます。ブロックリストやNGワードの変更はlambdaからコントローラーPodに行って、キャッシュPodを書き換えることで比較的リアルタイムに反映されます。Day1の時はこの辺りの情報をDBに格納していたのでこの辺りのパフォーマンスは非常に良くなったと思います。
Live配信は10分以上3時間以内くらいの生存時間なので、ある程度作って消す想定で使うk8sとはかなり相性が良いと思います。そのためにどのようにキャッシュデータを切り出すか、またどのようにそれをコントロールするのかは考えるのに時間がかかりました。というかこの辺り説明すればするほどややこしくなるので止めます。
つまり、
インターンシップを終えて
一日目の後も二日目の後も懇親会がありました。サーバーエージェント社がかなりエンジニアを大切にしている会社なんだなということが良く伝わりました。
あとあれですね、このインターンには最優秀賞なるものがありまして、幸いにも受賞することができました!やったね!
考えてたことの1割くらいしか体感書けてないのに、目がチカチカするようなボリュームになってしまいました。よくある「いかがでしたか?」のサイトの改行連打を馬鹿にしてましたが、文盲にはアレぐらいがちょうどいいですね!(アレ?文盲って差別用語にあたるんかな?って思ってググったらいろんな見解が出てきてチカチカしてきました。おやすみなさい。)
サイバーエージェントが気になる人はインターンお勧めですよ!
<追記> そういえば今回のインターンフロントエンドエンジニアが意外と多かったですね。フロントとバックの境界がもうかなり曖昧になってきているなぁというのを感じます。フロントエンドやりたくねぇ・・・・・・