帰ってきた大規模Webサービスの裏側

第1回バーストトラフィックの発見と対処

はじめに

初めまして、⁠株)ミクシィの中野和貴です。私はシステム本部運用部インフラグループネットワークチームという部署で働いており、ほかのメンバーと共にmixiのネットワーク部分全般に関して設計・保守・運用を行っています。ここでは『WEB+DB Press』Vol.50~55にて連載されていた「大規模Webサービスの裏側」で紹介しきれなかったエピソードや、その後のインフラ事情を紹介していきます。

日々大量のトラフィックが流れるmixiのネットワークですが、大きくなってくるとやはりいろいろな問題も出てきます。今回はそれらの問題の中で普段運用しているとなかなか気付きにくいバーストトラフィックに起因する問題事例を紹介します。

ミクシィのネットワーク構成と問題の発覚

mixiでは主要なネットワーク機材にはお金をかけていますが、サービス規模からどうしてもラック数が多くなってしまうため、エッジスイッチには安価で故障率の低いものを選定して使用していました。ここが今回の話の焦点となります。

ではまず、mixi全体のネットワーク構成から話を進めていきましょう。mixiのネットワークは図1に示しているように、ごく一般的な構成で成り立っています。コアスイッチやボーダルータのような主要スイッチの間は10Gbps、コアからエッジへは1Gbpsでの接続です。

ある日、部内でスループットが頭打ちになってしまっているポートがあるという話が出てきました。対象ポートのトラフィックグラフを見てみると、確かにピークタイムでTCPの制御が働き、トラフィックが頭打ちしてしまっているようです。そこでさらに調べてみると、けっこうな数のポートが同様の傾向を示していることが判明し、詳しく調査を始めることとなりました。

図1 mixiネットワーク構成
図1 mixiネットワーク構成

またしても原因はmemcached?

そもそも対象となったポート配下にいるサーバは、何の用途でサービスに投入されていたのでしょうか。確認したところ、すべてmemcachedサーバとしてサービスに投入されていました。memcachedといえば、2010年8月にmixiで発生した大規模障害の原因であったのは記憶に新しいところですが、これとは別にネットワーク側でもちょっとした問題が発生していたのです。

通常時では起こらないトラフィックの頭打ちがなぜピークタイムだけ起こるのか。単純に考えればピークタイム時のトラフィックがスイッチの性能限界を超えてしまっているからということで片付いてしまうでしょう。しかしながら、この現象が起こっているときのエッジスイッチの総スループット量はSNMPSimple Network Management Protocolから取得したグラフを見ると600Mbps強でした。仮にすべてのトラフィックがショートパケット(64バイト)だと仮定しても、アップリンクが1Gbpsあれば、約760Mbpsがスイッチの上限値となります⁠。ですので今回の事象の答えとしては適切ではありません。

※)
スイッチの処理限界理論値は「アップリンクポートのbps×(パケット内のデータ長÷パケット長⁠⁠」で求まります。今回の値をあてはめると、1000000000×(64÷84)=761.9Mbpsとなります。

バーストトラフィックとは

では、結局何が原因で問題が発生していたのでしょうか。結論から書いてしまうと、スイッチの性能限界を超えたトラフィックが流れたことによりパケットがドロップされていたためでした。しかし、グラフを見る限りスイッチ性能を超えたトラフィックが流れていないのは先ほど説明したとおりです。この矛盾はどこから出てきたのでしょうか。その答えはmemcachedの応答タイミングから考えることができます。

memcachedはご存じのとおりメモリ領域にデータとオブジェクトを置き、リクエストを高速に処理する分散メモリキャッシュシステムです。mixiサービス内のmemcachedは数十ms間隔でリクエストに対して応答を行っているのですが、ここが今回問題となった点です。

memcachedはリクエストに対して1つのmemcachedからのみ応答があるわけではなく、複数台のサーバから応答が返ってきます。そのため、多量のリクエストがある場合は相当数のサーバからほぼ同時にレスポンスが返ってくることになります。しかもこれが数十ms間隔で継続的に発生します。このような状態のトラフィックグラフは図2のようになります。

このように、瞬間的に突出した流量を示すようなトラフィックをバーストトラフィックと言い、これが発生しているときにスイッチの限界性能を超えてしまうため、パケットが頭打ちしていたのです。

この問題の厄介な点は、数ms単位でのサンプリングをしなければバーストトラフィックを発見できないところです。数ms単位でのサンプリングはアナライザのような高価な機器が必要となってしまい、非常にコストがかかります。SNMPを使ってトラフィックグラフを生成しているだけでは気づくことができません。私たちも推測をもとに、協力会社とアナライザを使って検証した結果やっとこの原因を究明することができました。

図2 バーストトラフィック(分解能:1ms)
図2 バーストトラフィック(分解能:1ms)

バーストトラフィックへの対処

このように原因がバーストトラフィックによるものだと判明したわけですが、次は対処法を考えなければなりません。memcachedをカスタマイズして応答タイミングをずらすなどの方法を使っている会社もあるようですが、mixiではネットワーク側からのアプローチでこの問題に対処するという方針で解決を図りました。

これにはいくつか理由があります。まず、いくら応答時間をずらすなどのアプローチで原因解決をしても、スイッチポート配下のmemcachedサーバ数が増大していった時点でバーストトラフィックの発生する可能性は増えてきてしまう点。次に、mixiの運用部は少人数であるため、アプリケーション側での対応を実施すると運用しきれなくなることが懸念された点。最後に、そもそもサービスネットワークのグランドデザイン自体が数年前のもののため、今後のサービス規模拡大やサーバの性能向上によるトラフィックの増大も視野に入れると、memcached部分のネットワークにだけ対応しても中長期的に見ればほかのシステム部分でも起こり得る問題になるのではと考えたからです。

これらの方針に加えて、そもそも最近のトラフィックの増大から1Gbpsでのネットワークに限界を感じていたこともあり、コアからエッジまでの間を10Gbpsでつなぐ新設計へと移行することにしたのです。

この力技な解決法だけでもこのバーストトラフィックの問題は解消できます。しかし、今後長期的に使えるネットワークにしていくにはこれだけでは足りません。今後CPUの処理性能向上や省電力化が進むにつれ、1ラックあたりのサーバ搭載密度は上がっていきます。そうすると必然的にラック単位でのトラフィック量が上がっていき、上位スイッチ側のポート単位でのトラフィック量が増えていきます。そうなると、現状でのサーバ搭載密度では解決できていたバーストトラフィックが、中長期的に見ればまた問題になってしまう可能性があるからです

根本的な解決に向けて

そもそもなぜパケットのドロップが発生してしまうのでしょうか。スイッチは基本的にパケットを受け取るとそれを内部にあるバッファへとパケットを溜めつつ順次処理を行っています。性能限界内にあるパケット量であればそのまま普通に処理されていくのですが、バーストトラフィックのようにさばききれない量のパケットがくると徐々にバッファを食いつぶしていき、最終的にはバッファにも溜めきれない状況になり、その段階で頭打ちしてしまうことになります。

このため、前述したように将来的にサーバの搭載密度が向上していくことを考えると、アップリンクの帯域だけ増やしてあげても結局同じ問題に直面してしまうことになってしまうのです。そこで私たちは現状使っているエッジスイッチよりもバッファサイズの大きなスイッチや、スイッチの性能自体が高い機器を数台選定し検証を行うことにしました。

既存スイッチの性能検証

新機種の検証を行う前にまず、現状のエッジスイッチの性能を再度確認してみます。確認はスネークテストと呼ばれる手法で行いました。これは図3のようにうねうねとLANケーブルを繋いで全ポートに負荷をかける検証方法です。縦2ポートに同一VLANをそれぞれ割り当てていき、LANケーブルをたすき掛けに接続することで全ポートをまんべんなく使ってトラフィックを流すことができるので、スイッチ単体の性能を調べるときには最適な手法です。

ここでは次の条件でテストを行いました。

  • パケットサイズ:64バイト
  • アップストリーム:750Mbps
  • ダウンストリーム:750Mbps
  • 検証時間:5分間

検証した結果、パケットドロップは0%であり、今使っているエッジスイッチでも通常のトラフィックであれば理論値までは問題なく処理できることが改めて確認できました。バーストトラフィックが流れていなければ、今後しばらくはアップリンク1Gbpsを超えない限りこのスイッチで持ちこたえられたでしょう。

図3 スネークテスト
図3 スネークテスト

選定試験

次にリプレース候補スイッチの検証です。まずはバーストトラフィックを流してみます。今回私たちは4台の候補機器を検証しました。まずはダウンリンクを1Gbps、アップリンクを10Gbpsで接続しバーストトラフィックを流していきます。検証時の構成は図4を参照ください。

図4 検証構成1
図4 検証構成1

まずは現状サービスで流れているのに近いバーストトラフィックを流していきます。条件は次のとおりです。

  • パケットサイズ:256バイト
  • アップストリーム:50Mbps/ポート(バースト時、490Mbps/ポート)
  • ダウンストリーム:50Mbps/ポート
  • 検証時間:5分間

パケットサイズがスネークテストの時と変わっていますが、これはスネークテストではスイッチがきちんと性能どおりの処理を行えるかを見るために一番負荷のかかるショートパケットを流しているのに対し、こちらの試験では実際のサービスで流れるパケットサイズの割合から見たパケットサイズを使っているからです。結果としては表1のようになりました。

表1 スイッチの検証結果
機種スイッチAスイッチBスイッチCスイッチD
ドロップ率0%0%0%0%
最大遅延0.007ms0.010ms0.086ms0.081ms
表2 スイッチの検証結果(過酷編)
機種既存スイッチスイッチAスイッチBスイッチCスイッチD
ドロップ率8%11%11%0%0%
最大遅延1.64ms0.67ms0.50ms4.84ms4.83ms

結果として、現状レベルのバーストトラフィックはアップリンクが10Gbps接続であれば候補の4台の機器どれでもパケットをドロップすることなく通信ができるようです(当たり前と言えば当たり前ですが⁠⁠。検証機のアップリンクが1Gbpsから10Gbpsへと帯域が増大したことにより、一度に多量のパケットが送出することができるようになったためバッファにパケットが溜まらずに流れている様子がうかがえます。

さらに過酷に検証

では、ここからが本題です。じわじわとスイッチを虐めていくことにします。先ほどは検証機からのアップリンクを10Gbps接続で検証を行いましたが、ここではそこも1Gbpsに変更してバーストトラフィックを流していきます。その他の条件は先ほどと同様です。こうした構成にすることで、よりスイッチ自身の処理性能を見ることができます。この検証の結果は表2のようになりました。

アップリンクを1Gbpsとしてのテストでしたので、現状使用しているエッジスイッチも一緒に検証比較をしてみました。この段階でバーストトラフィックをさばけるスイッチとさばききれないスイッチとが出てきました。後者のスイッチでは平均10%もパケットをドロップしてしまっています。

なお、表には載っていませんが、この検証における既存スイッチのスループットを確認すると、現状サービスネットワークで出ている問題の部分のものと近似していました。ですので、この試験結果と同レベルのパケットドロップおよび遅延が発生していたと考えられます。これではサービスネットワーク内でも支障が出てしまっていたことでしょう。

また、今回の選定機材よりも現状使っているエッジスイッチでロス率が低いのには少し驚きました。選定機材はすべてL3でも使える機器なのですが、エンタープライズ向けの安いL2スイッチのほうがこのような単純なパケット処理には分があるのかもしれません。

最終試験と機器決定

引き続き、ドロップ率0%だった2台に対して最後の検証試験をしていきます。両者を比較した場合、次のような違いがありました。

  • スイッチC:パケットバッファは多くはないがパケット処理性能が高い
  • スイッチD:パケットバッファを多く搭載し、処理するまでの時間をより稼ぐことができる

アップストリーム、ダウンストリーム共に1Gbpsでのバーストトラフィックには耐えることができたわけですが、アップストリームが常時10Gbpsあり、かつ10Gbpsを超えるバーストトラフィックが流れる状況ではどうなるでしょうか。というわけで、最後の検証の条件を次のように設定しました。

  • パケットサイズ:256バイト
  • アップストリーム
    • 1Gポート×2:平均100Mbps(0.1秒 900Mbpsにてバースト)
    • 10Gポート:平均9.0Gbps
  • ダウンストリーム:50Mbps/ポート

サーバ側にも10Gbpsを使うため、構成は図5のように変わります。

図5 検証構成2
図5 検証構成2

この構成では、9.2Gbpsのトラフィックを常時発生させ、瞬間的に1.6Gbpsのトラフィックをそこへ上乗せし、合計で10.8Gbpsとすることでバーストトラフィックを生成させています。アップリンクが1Gbpsのときにはパケットをドロップすることなく耐えることのできた2台ですが、この条件ではどうなるでしょうか。その結果が表3です。

スイッチCはパケットを少しドロップしてしまいました。一方、パケットバッファが大きいスイッチDは、ここでもドロップすることなくすべてのパケットをさばくことができました。

スイッチDのほうの最大遅延がスイッチCに比べて3倍ありますが、これはパケットバッファに溜まった大量のパケットを順次処理しているため、パケットをドロップしない代わりにどうしてもある程度の遅延が発生してしまうためです。10Gbpsという帯域を食いつぶせるパケット量というのはかなりの量です。いくらパケットを高速にさばくことのできるスイッチだとしても、やはりバーストトラフィックが発生するような場所ではパケットバッファが大きいほうが有利だということをこれらの検証により確信することができました。

この結果をふまえ、私たちは新しいエッジスイッチとしてスイッチDを選択することにしました。

表3 スイッチの検証結果(最終)
機種スイッチCスイッチD
ドロップ率1%0%
最大遅延0.60ms1.88ms

さいごに

このような経緯で、今ではスイッチDを用いたmemcachedの運用が始まっています。さまざまなログやデータからも、平均的にピーク時のスループットが向上しているのが確認できています。パケットがドロップされることによるパケットの再送がなくなった分、少しでもサービスの応答速度の向上へ貢献できたのではないかと思っています。

今後ユーザの数が増え続けていく限り、memcachedサーバは増えていきます。そんな中、アプリケーション側だけでなく、それを裏で支えるネットワーク側も適切に見直しを行うことがシステム全体の品質向上へ貢献するのではないでしょうか。最近では高速SSD(Solid State Drive)のようなサーバレスポンス向上が期待できるパーツなども増えてきています。

みなさんもサーバの監視グラフを見ていて「あれっ?」と思うことがあるときはぜひネットワークのほうも気にしてみてください。今回の事例のように思わぬ改善点が見つかるかもしれません。

mixiではインフラエンジニアを募集しています。

詳細はこちら

おすすめ記事

記事・ニュース一覧