「LINE DEVELOPER DAY 2019」レポート

DAY-1,時系列データベース‘Flash’とは?/LBaaS実現への道

この記事を読むのに必要な時間:およそ 5 分

多層のロードバランサアーキクチャ

そこで,ロードバランサ設計の根本的な見なおしが行われ,新たに3つの要件が設定されました。1つめは,デベロッパとオペレータの両方のオペレーションコストを減らすことです。従来までの手動ベースのものではなく,APIドリブンで,人の手を介さずに,ユーザがロードバランサを必要なときにすぐに手に入れられるようにする必要があります。

2つめは,サービスの拡大や突発的なトラフィックの増加に応じて,しっかりスケールできるということです。もともとあったセッションテーブルの枯渇問題への対処のほか,必要に応じて容易にロードバランサの数を増やせるようにします。

3つめは,アベイラビリティに関するもので,スケーラビリティに関する要件と同じですが,容易にロードバランサの数を増やして冗長化できることに加え,障害時にその影響の範囲を可能な限り小さくすることです。

こうしたロードバランサを考えるうえで参考になったのは,GoogleやFacebookといった大手のロードバランサの設定でした。2010年から2016年にかけて,大手企業が論文やブログでロードバランサに関する発表を数多く行いました。それらには,すでに自社開発のロードバランサが使用されており,それに至った経緯や5年以上の運用経験から得た知見が盛り込まれていました。リサーチの結果,こうした大手企業も当時LINEが抱えていたのと共通した問題を持ち,独自開発に至った経緯があることがわかりました。

その結果採用されたのは,大手でも事例の多い多層のロードバランサアーキクチャでした。これは,サーバをL7LBやL4LBで負荷分散して,そのL7LBをL4LBで負荷分散するという,複数のロードバランサを多段でつなげるような構成になっています。

多層構造のロードバランサアーキテクチャ

多層構造のロードバランサアーキテクチャ

ロードバランサクラスタの各種コンポーネントを束ねるコントローラは,シンプルなPythonのWebアプリとして実装されています。おもな役割は,APIでデベロッパからのリクエストを受け,ロードバランサの作成・削除・設定といったオペレーションを自動で行うことです。これらは,⁠Verda」の専属UIチームが開発したもので,直感的に操作が行えるようになっています。

ロードバランサのコントローラ画面

ロードバランサのコントローラ画面

自動テストとCI/CDでサービス性能を維持

ロードバランサによってパフォーマンスを出すことも重要ですが,それをいかに維持するかということも重要な要素です。高いパフォーマンスは,L4LBのユーザが期待するサービスの一部であり価値でもあります。新機能開発でコードに変更が行われたときに,パフォーマンスが低下したという事象に,いち早く気が付けるようにしておく必要があります。

これらは,自動テストやCI/CDでコードの品質を担保していくことで,継続的にパフォーマンスの計測も行っていかなくてはならないということでもあります。そこで取り組んだのが,パフォーマンステストの自動化です。

個人の開発者がそれぞれパフォーマンスをテストし,その結果をアップロードするというやり方もできますが,実験環境やちょっとしたパラメータの違いなどが生じて,結果どうしを平等に比較できないことがあります。

それを避けるために,共通のテストベッドを用意したほか,開発フローに乗せることができるようにGitHubから自動的にCI/CDのプラットフォームを介してテストがトリガされるようにしています。こうしたしかけによって,継続的なテストを行うことが可能となっています。

PullRequestをトリガにパフォーマンステストが自動で行われるしくみ

PullRequestをトリガにパフォーマンステストが自動で行われるしくみ

蘇るセッションテーブルの枯渇問題

続いて,デベロッパからの要請で機能追加を行った事例の紹介が行われました。L4LBをステートレス化することで,過去の運用で問題になっていたセッションテーブルの枯渇問題は解決できましたが,ステートレス化することで新たな問題も生じています。それは,サーバのグレースフルシャットダウンができなくなるという問題です。また,フェールオーバーも難しくなります。その問題の原因は,ステートレスのL4LBの実装にあります。

パケットに書かれているクライアントとサーバの識別情報(5tuple)をもとにHash表を引き,転送先のサーバが決定されるというアルゴリズムでした。この方法では,パケットに書かれている情報から計算のみで転送先を決定できます。そのため,どのクライアントがどのサーバにつながっているのかといった情報をロードバランサに記録しておく必要がなく,ステートレス化を実現していました。

L4ロードバランサのステートレス化に起因する問題

L4ロードバランサのステートレス化に起因する問題

サーバ管理者がアプリをアップデートするために,一部のサーバをシャットダウンするとHash表を更新する必要があります。このとき,停止するサーバへのコネクションは来ないようにしたうえで,すでに接続されているクライアントは接続が終了するまで待ってシャットダウンしますが(グレースフルシャットダウン⁠⁠,ステートレスのロードバランサではこうしたことはできません。また,Hash表を更新したときに,他サーバの既存のセッションが切れてしまう可能性があります。これがフェールオーバーが難しいという問題です。

それらの問題に対処するために,セッションキャッシングと呼ばれる手法が採用されています。これは,Hashで求めた転送先を,セッションキャッシュと呼ばれるキャッシュに随時保存していくという方法です。

ユーザからパケットが来たとき,セッションキャッシュを検索してヒットすれば,そのアドレスに転送します。キャッシュミスの場合は,通常のHash表で転送先サーバを決定し,その結果をキャッシュに記録していきます。

これにより,サーバがサービスアウトしたり障害が発生してHash表が更新されたりした場合でも,情報が残ったままの状態になります。セッションキャッシュのサーバが生きているうちは,どのサーバとどのクライアントがつながっているのかという情報がロードバランサ上に残っています。そのため,セッションが切れてしまうという事態を防ぐことができるのです。

セッションキャッシング

セッションキャッシング

しかし,このセッションキャッシングは,過去に問題になっていたセッションテーブルの枯渇問題と同様の問題を抱えています。同時接続しているクライアントの数が増えると,セッションキャッシュの容量が圧迫されていきます。さらに,TCP SYN Flood攻撃を受けると,意図的に枯渇が誘発されます。

つまり,ロードバランサをステートレスにすると,セッションテーブルの枯渇問題は解決されるものの,グレースフルシャットダウンやフェールオーバーができなくなります。しかし,セッションキャッシングを用いた実装にしてしまうと,TCP SYN Floodといった攻撃に弱くなってしまうのです。

こうした問題を解決するために選択した方法が,ステートフルとステートレスを状況に応じて使い分けるというハイブリット的な手法です。通常時はセッションキャッシュを用いたステートフルなモードでロードバランサを動作させますが,TCP SYN Flood攻撃を受けると,一定時間ステートレスなモードにフォールバックします。これにより,グレースフルシャットダウンやフェールオーバーがやりやすいステートフルな実装を使いつつ,他者からの攻撃からも強いロードバランサを実現しています。

これらは3ヵ月ほどかけて実装され,現在も稼働中です。この機能をリクエストしていたメディアプラットフォームのチームは,検証を終えて「Verda」にサービスを移行しています。個々のアプリの要求に応じて必要な機能を実装していくことにより,柔軟にLINEのサービスに特化したロードバランサの開発を目指していく予定です。

詳細なレポートや資料,動画はLINE Engineering Blogで公開される予定です。ぜひこちらもご覧いただき,会場の雰囲気や盛り上がりを体感してみてください。

著者プロフィール

高島修(たかしまおさむ)

コンピュータホビー雑誌『ログイン』の編集者やドワンゴでモバイルサイトの企画・運営等を経て,2014年よりフリーで活動中。XRやPCなどのIT系やゲームをメインに,年間120本以上の取材をこなしています。

バックナンバー

「LINE DEVELOPER DAY 2019」レポート