はじめに
はじめまして、2020年4月に株式会社ドワンゴに新卒入社した関森です。 現在は株式会社KADOKAWA ConnectedのKCS部にも所属しています。
KCS部は、KADOKAWAグループ向けプライベートクラウド(以下KCS)を提供しており、その中でも私は、Content Delivery Network(以下CDN)サービスを担当しています。 社内ではこのCDNサービスをDCDN(ドコドン)と呼んでいます。
DCDN では、『niconico』のウェブサイトを構成するJavaScriptやCSS、そしてユーザアイコンや動画サムネイルといった画像ファイルなどの配信を行っています。
今回は、私が入社してから半年間で学んだことを整理しアウトプットするという意味も込めて、DCDNの概要について紹介します。
CDNとは
CDNとは、ウェブコンテンツを効率的かつ高速に配信するためのネットワークのことです。 主に、画像ファイルやCSSなどの静的コンテンツを配信するために利用されています。 オリジナルのコンテンツをキャッシュするキャッシュサーバを複数台配置することによって、オリジナルのコンテンツを保持するオリジンサーバの負荷を低減させ、大規模な配信が可能となります。CDNを提供するクラウドサービスとして、Amazon CloudFront、Akamai、Cloudflare、Google Cloud CDN、Limelightなどが挙げられます。
DCDNの静的コンテンツ配信
DCDNは、自社データセンタに配信システムを構築しつつ1、部分的にパブリッククラウドのCDNサービスを利用するハイブリッドな構成をとっています。
なぜこのようなハイブリッド構成にしているかについて説明します。
『niconico』では動画サービスを提供していることもあり、データセンタには大規模なネットワークキャパシティがあります。 データセンタのネットワーク利用料金は帯域ベースの定額制であるため、従量課金制であるパブリッククラウドのCDNサービスを利用するよりもコストを抑えられます。
しかし、配信元がデータセンタのみの場合、局所的な多重障害でもサービスが停止してしまう可能性があるため、DCDNではパブリッククラウドを併用することにより可用性を担保する構成にしました。 定常時は主に配信コストの低いデータセンタを利用し、有事の際にはパブリッククラウドに自動でフェイルオーバすることによって、コストと可用性のいいとこ取りを実現しています。
DCDNの構成
DCDNのハイブリッドなCDNは、大きく分けて3種類のサーバと1つのアプリケーションから構成されています。 実際にキャッシュデータを持つキャッシュサーバ(以下Edge)、オリジナルデータへのリクエストなどを一元的に行うサーバ(以下Hub)、オリジナルデータを持つオリジンサーバ(以下Origin)およびデータセンタとパブリッククラウドそれぞれへのアクセス流量を管理するアプリケーション(以下Yumori)が存在します。 データセンタの各サーバは、KCS部で提供している社内IaaSであるNicoSphere上のVMで稼働しています。
Edge:キャッシュサーバ
Edgeは、実際にキャッシュを保持する役割を持つサーバです。 Edgeはデータセンタ、およびパブリッククラウドであるAmazon CloudFrontの両方で稼働しており、ハイブリッドな構成になっています。
ユーザからのアクセスは、DNSによってデータセンタとCloudFrontのどちらかのEdgeに振り分けられます(詳しくはYumoriで説明します)。 Edgeにおいてキャッシュヒットした場合、そのキャッシュをユーザに返します。 キャッシュヒットしなかった場合、Hubにオリジナルデータのリクエストを送ります。
Hub:Originへのリクエストを一元的に担うリバースプロキシサーバ
Hubは、Edgeから送られてきたリクエストを受けて、Originにオリジナルデータを取りに行くリバースプロキシとしての役割を持つサーバです。 オリジナルデータ取得後、HubからEdgeにレスポンスを返し、Edgeからユーザにレスポンスを返します。
DCDNでは、各サービスの配信URLごとにOriginを指定できます。KCS部で提供しているオブジェクトストレージであるD3、Amazon S3、または各サービスの開発チームが自前で用意した任意のサーバをOriginとして利用することが可能です。
HubがOriginへのリクエストを一元的に行うことによって、配信URLとOriginとの対応関係の設定をデータセンタおよびCloudFrontのそれぞれのEdgeが持たずに済みます。 設定をHubに集中させることにより、管理コストを抑えることができています。
しかしHubに設定を集中させると、Hubを動かしているWebサーバであるNginxの設定ファイル(nginx.conf)が複雑かつ膨大な行数のコードになってしまいます。 このような設定ファイルを人が直接管理することは運用ミスに繋がります。 そこで、配信設定を各サービスごとに分けてYAML形式で記述し、Goで実装したスクリプトを利用してYAMLファイルからnginx.confを自動生成するようにしています。 これにより、肥大化したnginx.confそのものの管理を行わずに済んでいます。
Yumori:データセンタのEdgeとパブリッククラウドのEdgeへの流量を管理するアプリケーション
ユーザからのアクセスは、定常時は99 : 1の比率でデータセンタのEdgeとCloudFrontのEdgeに振り分けられます。 配信割合はAmazon Route 53の加重ルーティング設定によって管理されます。
Yumori(湯守り)は、データセンタの負荷に応じて配信割合を決定するアプリケーションです。 アクセスの"流量"を管理することから、湯守りという名前で呼んでいます。 Yumoriはデータセンタに対するリクエスト数やトラフィックを監視し、データセンタ内での割当量を超えた場合には、超過分をパブリッククラウドのCDNから配信するように配信割合を変更します。 例えば、人気番組の生放送開始時のスパイクアクセスや、データセンタのEdgeのダウンなどによる処理性能の低下が起きたときに配信割合の変更が行われます。
大規模な障害などによってデータセンタのEdgeでの配信が完全に停止した場合、それを湯守りが自動で検知し、流量の100%をCloudFrontのEdgeに向けることによりフェイルオーバするようになっています。 なぜ定常時にも1%はパブリッククラウドから配信を行うことにしているかというと、CloudFront側に定常的にある程度トラフィックを流しておかないと、フェイルオーバしたときにキャッシュヒットせずすべてのアクセスがOriginへ突き抜けてしまうためです。
画像変換機能
さらにKCSでは、DCDNと連携した画像変換機能を提供しています。 オリジナルの画像に対してURLベースで画像フォーマットと解像度を指定することにより、その形式に動的に変換して配信することができます。 これによるメリットとして、スマートフォンやPCなどの様々なデバイスごとに最適なサイズの画像を表示させたいときに、開発チームがオリジナルの画像を複数種類用意する必要がなくなることや、転送量の節約になることが挙げられます。
Hubがオリジナルデータにアクセスする部分において、Originではなく画像変換サーバにリクエストを送ることにより、変換された画像を取得できます。 詳しくは今後の記事で紹介する予定です。
現在の状況・規模
2020年9月現在、DCDNは提供開始から5年が経過し、サービスとして成熟期に達しています。 サービスとしての規模は以下のようになっています。
- 転送量:約1 PB/月
- 帯域:約20 Gbps(ピーク時)
- リクエスト数:約150000 req/s(ピーク時)
その他の工夫点
キャッシュ
データセンタのEdgeにおける工夫点として、オンメモリキャッシュを利用している点が挙げられます。 ディスクキャッシュと比較すると高価ではありますが、ディスクI/Oの負荷を気にしなくてよいという利点があります。
キャッシュ保持時間(TTL)の値や、HTTPヘッダやクエリパラメータをキャッシュキーに含めるかなどは、配信エンドポイントごとに設定可能です。 キャッシュTTLはデフォルトで1日に設定していますが、さらに一定時間アクセスのなかったキャッシュを削除する設定も加えています。 これによりメモリ領域を節約することができています。 それでもキャッシュヒット率は90%以上をキープできているため、十分キャッシュサーバとして機能しています。
その他の機能として、Originがダウンした場合にキャッシュサーバ上に古いキャッシュが残っていればそれを配信するStaleキャッシュ機能や、ネガティブキャッシュ機能があります。
Nginx
Hubの実装として使用しているNginxは、Luaで記述することによって機能を拡張することができます。 実際にはDCDNではNginxを拡張したOpenRestyを使用しています。
Luaによる実装の例として、Hubから画像変換サーバにリクエストを送る際のリクエストフォーマットの整形などがあります。
また、DCDNではOriginとしてS3を指定した場合、HubからS3に署名付きのリクエストを行います。 しかし、LuaにはAWSのSDKが提供されていないため、AWS Signature V4に対応したリクエストを行う関数を独自に実装しています。
課題や今後について
EdgeのKubernetes化
DCDNでは、オンメモリキャッシュのさらなる効率化を目指しています。 また、今回の記事では触れませんでしたが、Edgeは高スペックな専用のロードバランサを使用しています。
そこでインフラコスト削減のために、キャッシュサーバであるEdgeをKubernetes化するという計画を進めています。
現在、KubernetesのL7ソフトウェアロードバランサであるIngressの利用を検討しています。 それにより、現在のロードバランサが持つ機能をハードウェアロードバランサとソフトウェアロードバランサで分担をしたいと考えています。 また、負荷分散を効率化することによって、キャッシュ保持領域としてのメモリの削減に繋がると考えています。
Kubernetesクラスタとして、KCS部で開発しているDKSを利用予定です。 詳しくはこちらの記事をご覧ください。
HTTP/2対応
DCDNは、プロトコルとしてHTTP/1.1を利用しています。 一方で、2015年にレイテンシの短縮を目標とした規格であるHTTP/2が登場しました。 DCDNのサービス開始当初はHTTP/2の普及がそこまで進んでいませんでしたが、近年多くのWebサービスがHTTP/2に対応しています。
そこで、より高速かつ効率的な配信を行うため、HTTP/2への対応を検討しています。 上記課題にて挙げたKubernetes化によって、このような機能の拡張を柔軟に進められると考えています。
まとめ
KADOKAWAグループ向けに提供しているハイブリッドなCDNサービスであるDCDNについて紹介しました。 データセンタとパブリッククラウドを併用することにより、可用性を担保しつつ低コストに静的コンテンツを配信可能です。 CDNサービスを基盤として提供することによって、各サービスごとの運用コストの削減に繋がっています。
今後、課題に対する取り組みについての記事を投稿していきたいと考えています。
最後に、KCS部では一緒に働く仲間を募集してます!
ご興味がある方は是非採用サイトをご確認ください!
-
一般的にCDNと聞くと、複数の拠点にデータセンタを配置することにより、ユーザからのアクセスに対して物理的に近いネットワークを利用して通信する、地理的メリットが思い浮かぶと思います。しかし、DCDNを利用するユーザの多くは日本であることから、DCDNでは東京のデータセンタから主な配信を行っています。↩