DMM.comの、一番深くておもしろいトコロ。

DMM動画サービスの問題を解決しようとしている話(再生URL生成API編)

DMM動画サービスの問題を解決しようとしている話(再生URL生成API編)

  • このエントリーをはてなブックマークに追加

はじめに

こんちは〜。DMM.com 動画配信事業部の配信基盤チームというところにおります@_tinojiです。

最近お隣のチームの人たちが、動画サービス改善における取り組みについて記事をいくつか書いていてですね。

inside.dmm.com

inside.dmm.com

乗るしかねぇこのビッグウェーブに〜〜。ということで今回は、動画配信基盤における取り組みについてご紹介させていただきたいと思います。



チーム紹介

まず軽くチームの紹介をさせていただきたいと思います。

配信基盤チームが日頃何をしているかというと…、VOD*1やLOD*2の配信システムを作ったり、動画のエンコード基盤を作ったり、コンテンツの認証システムを作ったり、最近では画像の配信もしていたりと、様々なコンテンツをユーザーにお届けするために必要になるシステムの基盤をつくっています。

現在8名で構成されているスクラムチームなのですが、うち6人が東京、2人は石川にいるという、他のチームとは少し違った体制で開発を行っています。石川のメンバーは2人とも長くDMMの動画配信システムに携わっており、本記事で紹介するシステムも石川メンバーの保月さんという方がメインで開発しました。

年齢層もバックグラウンドも様々なごった煮チームですが、和気あいあいとやってます。

再生URL生成ってなんぞや

再生URLとは、文字どおり再生を行うために必要なURLであり、それを叩くことによってコンテンツへのアクセスができます。 弊サービスでのストリーミング再生はHLSとSmooth Streamingの2つの技術を利用しており、PlaylistやManifestと呼ばれるデータを得るためのURLが再生URLに当たります。

「再生URL生成? それってスタイルガイドとかコンポーネント化とかと肩を並べるほど大きな話なの?」

そんなふうに思ったあなた! 再生URLをナメてはいけません。

  • 購入済みかどうかのチェック
  • 最適な通信経路の選択
  • たとえURLが漏れても他者から再生させない仕組み
  • デバイスごとに異なる配信形式
  • 販売形態によって異なる画質 etc.

と、満たすべき仕様はたくさんあり、なおかつそれらの処理を瞬時に行う必要があります。当たり前ですが、再生URLが得られなければ動画は再生できません。 動画を見れない動画プラットフォーム、なんてありえませんよね? ということですごく重要なファクターなのです。


20年間で積もり積もった様々な「課題」

さて今回紹介するのは、そんな再生URL生成APIを モノリシックで複雑なシステムから分離した! という話です。

冒頭で紹介したデザイン・フロントエンド側の記事でも述べられていたように、DMM動画は20年近く続く長寿サービスです。そしてそのサービスは、肥大化に肥大化を重ねたモノリシックなシステムによって支えられています。 皆さんもご存知のとおり設計思想には流行り廃りがあり、エンジニアは常に最適な物を模索しながら設計していると思います。そして当時選択された設計思想こそ、このモノリシックなアーキテクチャだったのでしょう。

サービス規模も組織も急成長するなか、担当するエンジニアは入れ替わり立ち替わりしながらもシステムは同じものを使い続け、拡張に拡張が重ねられてきました。 それは、最速で新しいサービスをユーザーに届けるための選択肢であり、おかげでここまで大きな売上規模を誇るサービスに成長しました。

急速に成長するDMMを支えるために先人たちが全力で開発してきた結果ですので、一概に悪いシステムとは言えないのですが、一つのシステムにどんどん機能が追加されてきたため、「意図がよくわからない条件分岐」「利用されているのかどうかわからないファイル」など、結果として様々な課題を抱えています。そのため、「ここを修正しただけなのに、なぜかあっちの方が動かなくなった!」という現象がしばしば発生していました…。エンジニアはどこも壊れないように、他のサービスに影響を及ぼさないように、慎重なリリース作業を行う必要がありました。

スピーディーな開発を目指して取られた選択肢が、後々サービス成長の足を引っ張るというのは何とも皮肉な話です。

スタイルガイドやコンポーネント化の取り組み同様、私達はこの課題に向き合い、密結合したシステムを疎結合な形に分離していく改善を進めています。


旧システムの問題点

動画配信基盤のエンジニアの間でも、ここが分離できれば楽なのになぁと言われてきたシステムがいくつかあり、そのうちの一つが再生URL生成機能でした。この機能は各動画コンテンツを再生するための必要なURLを発行しているもので、従来はモノリシックなシステム上のライブラリの一つとして提供されていました。

このライブラリに対して、以下のような問題点が指摘されていました。

  • 様々な機能と密結合している
    • 購入関連処理やコンテンツのメタ情報系の処理、ファイルの実体に関する処理等々が複雑に絡み合っており、機能追加の際に他の機能に影響を及ぼさないか入念な調査が必要
  • 複数のサービスでそれぞれソース管理を行っており、更新に手間がかかる
    • ソースを修正したら担当部署へ反映をお願いする必要があった
    • 実は動画以外のサービスでも使われていたりします
  • URLと用途との間にズレがある
    • ○○用のURL生成のつもりで作られたはずが別の使い方がされている

f:id:kikuchi-hiroaki:20180930213412p:plain


新システム(st-api)の概要

構成

今回のプロジェクトにより、上記のシステムが以下のように分離されました。私達はこれを st-api と呼んでいます。 旧システムを深く理解しているベテランのメンバーが主導して開発を行ったことにより、調査を含めて計画から半年程度という比較的短い期間でリリースできました。

f:id:kikuchi-hiroaki:20180930224141p:plain

特徴

本APIは動画の再生・ダウンロード時に必ず呼ばれるものなので、速度と信頼性が求められます。

速度的には、8コアのVMで動作させた場合、HTTPSで1000ユーザー同時接続した場合に1サーバあたり秒間2500リクエスト程度をさばけることが負荷検証からわかっています。 それを5ノード稼働させているので、理論上は秒間12500リクエストをさばけることになりますね。

利用しているDBも含めてConsulによるノードマネージメントと死活監視を行なっています。 グローバルからのアクセスに用いるDNSにAWSのRoute53を使用しており、これをConsulから管理させることによって異常時/復活時のサービスインとサービスアウトが自動的行われます。便利ですね。


st-apiを支えるツール

コードが分離されたことにより、イマ風なDevOpsツールなどの導入も容易になりました。リリースの速度を高めるため、また新たな負債が蓄積しないように、現在以下のようなツールを利用しています。

ノードディスカバリー/ノードマネージメント: Consul

動画配信基盤は扱っているコンテンツ量が膨大なため、古くからオンプレの基盤によって支えられています。

そんなオンプレのノードのノードディスカバリーやノードマネージメントを行い、スケーラビリティとハイアベイラビリティを担保しているのがConsulです。 マスターレスなアーキテクチャでなおかつサービスレベルでの監視も行ったりといろいろと頼もしいミドルウェアです。 これだけで一記事が書けそうな魅力的なものなので、今度、弊チームでのConsul利用方法を投稿したいと思っています。

f:id:kikuchi-hiroaki:20181001114554p:plain


APIドキュメント: Swagger

RESTful APIのドキュメント作成には、YAMLでの記述が可能で、WebUIからAPIを簡単に実行することもできるSwagger*3を使用しています。

f:id:kikuchi-hiroaki:20181001114837p:plain


CI/CD基盤: CircleCI

CircleCI Enterprise*4を利用してユニットテスト・APIテストを実行し、加えて各環境へのデプロイとコードの静的解析(後述)をキックしています。また、本番環境に対して一定時間ごとにテストの実行・結果の通知を行い、障害を早期発見できるようにしています。

f:id:kikuchi-hiroaki:20181001111749p:plain


デプロイ基盤: Ansible + Rundeck

構成管理ツールであるところのAnsible*5ですが、私のチームではデプロイツールとしても使用しており、多くのコードがAnsibleによって各環境にデプロイされています。この際、コマンドをペチペチ叩いてPlaybookを実行するとヒューマンエラーが怖いうえに非効率的なので、Playbookの実行基盤としてRundeck*6を使用しています。RundeckのAnsibleプラグインを使用して、「GitHub EnterpriseからPlaybookをclone=>ansible-galaxyでrequirementsにリストされたRoleを取得=>Playbook実行」という一連の行程を自動で行うことが可能になっています。

masterブランチにマージされた際には、CircleCIからRundeckのAPIが実行されて該当のブランチが各環境に自動デプロイされます。ただ現状ではデプロイするタイミングをコントロールしたいので、CircleCIのManual Approval機能を使用するか、Rundeckから手動でデプロイ用ジョブを実行することにしています。

f:id:kikuchi-hiroaki:20181001115231p:plain


コード静的解析: SonarQube

コードレベルの技術的負債が蓄積していかないように、コードの静的解析と解析結果・メトリクスの可視化を行うことができるSonarQube*7を導入しました。この解析もCircleCI上から自動で実行され、SonarQubeサーバにPushされます。WebUIを開けばCode Smellsの数やコードの重複度などが時間軸に沿って表示され、チームメンバーはいつでもプロダクトの「ヤバさ」を監視できます。

f:id:kikuchi-hiroaki:20180725154230p:plain
SonarQube UIの一部。各項目の判定がAになるようにコーディングしています。


今後の取り組み

今回のプロジェクトにより、DMMの動画システムが抱えていた技術的負債のボスの一匹を打倒することに成功しました。これにより、怯えることなく配信基盤周りの機能を良くしていけるようになりました! やったー!! しかし、我々が使用しているモノリシックなシステムには、まだまだ倒さねばならないボスがうじゃうじゃいます…。

ただ、今回の取り組みによってリプレイスの見通しがつくようになった箇所がいくつもあり、すでに新しい取り組みが始まっています。俺たちの戦いはこれからだ! ということでゴリゴリやっていきたいと思います!!


採用情報

現在、DMM.comでは、エンジニアメンバーを募集しております! 興味のある方はぜひ下記募集ページをご確認下さい! dmm-corp.com