2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
提供:LINE株式会社
リンクをコピー
記事をブックマーク
イ・ビョクサン氏:それではプレゼンテーションをはじめます。まずこのセッションに参加していただき、ありがとうございます。イ・ビョクサンです。LINEのAPI Gatewayチームでソフトウェアエンジニアをしています。今日はHTTP/2とTLSによる、LINEのクライアントとサーバーの接続性向上についてお話しします。
本日のアジェンダです。まず私たちが何を解決しようとしたのか、その背景を説明します。そして、接続性を向上させるために行った3つの主なアプローチを説明します。最後に、まとめをお話ししたいと思います。
まず背景についてです。詳細を説明する前に、この発表の範囲を明確にしておきたいと思います。この図は、LINE Messaging Platformの全体的な構図を表しています。LINEのクライアントは、LEGYと呼ばれるAPI Gatewayを介して、Talk Serverや連携サービスと直接または間接的に通信します。
LEGYは、LINE Event GatewaYの略です。ここからは、LEGYとAPI Gatewayを同じ意味で使っていきます。talk-serverと連携サーバーは、それぞれ独自のビジネスロジックを実行して、メッセージングやメディア送信などのLINE機能を提供します。LEGYの主な役割の1つは、LINEのクライアントとの接続を管理することです。このプレゼンテーションでは、LINEのクライアントとLEGY間の通信に焦点を当てます。
LINEサービスへのトラフィックの多くはLEGYを経由するため、LEGYは効率的かつ信頼性の高い方法で接続を処理できなければなりません。またセキュアであることも必要です。LINEのクライアントとAPI Gatewayの間のプロトコルが、どのように変更されたかを見てみましょう。
2011年にサービスを開始したLINEでは、HTTP/1.1を採用していました。ご存知のように、HTTP/1.1はリクエストとレスポンスのペアを1つのコネクションで処理するのが基本です。LINEの主な機能の1つに、HTTP/1.1を通じて新着メッセージの到着をクライアントに知らせるものがありました。そのため我々は、ロングポーリングという手法を用いました。
仕組みはこうなっています。LINEのイベントは、すべてオペレーションとして定義されています。クライアントはfetchOpsというAPIを使ってイベントを同期し、オペレーションを開始します。LEGYはfetchOpsのリクエストをロングポーリングとして処理します。LEGYは、クライアントからfetchOpsリクエストを受け取った直後に、Talk Serverに渡します。
しかし、talk-serverがコンテンツなしと応答すると、LEGYはtalk-serverからpublishを待ちます。新しいオペレーションが作成されると、talk-serverはLEGYにpublishリクエストを送信します。talk-serverからpublishを取得した後、LEGYは元のfetchOpsリクエストをtalk-serverに再送し、その応答をクライアントに返します。
2012年末から、LEGYではHTTP/2の基礎となるSPDYを採用しています。HTTP/1.1とは異なり、SPDYは1つのコネクションを確立し、複数のリクエストとレスポンスを1つのコネクション内で多重化します。
このほかにも、HTTP/1.1より改良された点をSPDYは持っています。まず1つ目は、ヘッダーの圧縮です。大きなヘッダーを含んだHTTPリクエストを圧縮することで、サイズを小さくすることができます。これは、ネットワークの帯域幅を削減するには良いことですが、LEGYが圧縮状態を保存するためにメモリを大量に使用するという問題があります。そのため、接続によっては、この方法によるヘッダー圧縮をLEGYが正しく扱うことができていませんでした。
クライアントからの多くのリクエストは、同じHTTPヘッダーを繰り返し持つ可能性が高く、それが何であるかわかっているため、LEGYではそのような繰り返しのヘッダーをキャッシュして、ネットワークの帯域幅とメモリ使用量の両方を削減することにしました。
接続の中でLEGYは、リクエストを受け取るとキャッシュ可能なヘッダーをメモリに保持し、キャッシュキーをクライアントに返します。その後のリクエストでは、クライアントはキャッシュキーをHTTPヘッダーとして添付するだけで、LEGYはキャッシュされたヘッダーを復元してから、talk-serverにリクエストを送信します。
2つ目の改善は、Server Pushです。Server Pushは、1つのリクエストに対して複数のレスポンスを可能にします。その目的は、Webページをレンダリングするための追加リソースの取得を高速化することです。しかし、「Server Push」とは呼ばれていますが、それはリクエストをかならず1つ必要とします。一部のLINEサービスではロングポーリングにおける空の204 No Contentの応答を避けるために、SubscribeとPushのパターンが必要です。
つまり、リクエストを必要としない未承諾のPushを送れるようにすることが必要です。これを可能にするために、すべてのPushストリームをstream 0に紐づけています。stream 0は、SPDYでは使用されておらず、SPDYの仕様上では無効な値とされています。我々のPushでは、クライアントはまずLEGYを通じてサービスにSubscribe要求を送信します。
その後、サービスがLEGYにPushリクエストを送信すると、LEGYは関連するクライアントとの接続を見つけます。LEGYはデータをストリームで送信し、それをstream 0に関連付けます。ちなみに、fetchOpsのAPIはこのパターンではなく、ロングポーリングとして動作します。
セキュリティも通信において非常に重要です。SPDYでは、より堅牢なセキュリティのためにTLSの使用が推奨されています。しかし当時は、TLSを使うと3Gモバイルネットワークの接続確立が遅くなるため、非常に大きなオーバーヘッドとなっていました。モバイルネットワークは遅く、切断や再接続が頻繁に発生していました。
そこでLEGY Encryptionという暗号方式を自社開発しました。これは接続全体ではなく、メッセージ本文と一部の機密性の高いヘッダーのみを暗号化するものです。ハンドシェイクのプロセスは、TLS1.3の0-RTTハンドシェイクに似ています。暗号化キーの交換とHTTPリクエストとレスポンスの処理が、同時に行われます。
LEGY Encryptionを使用する場合、LEGY Encryptionに関するメタデータがヘッダーに追加されます。リクエストやレスポンスに含まれる機密性の高いヘッダーは、すべてメッセージ本文に移され、オリジナル本文とともに暗号化されます。Wi-Fiネットワークで接続するクライアントは通常TLSを使用し、モバイルネットワークで接続するクライアントはLEGY Encryptionを使用します。
LINEのクライアントとLEGYの接続性を向上させるために、社内独自で使ってきた技術を紹介してきましたが、問題もあります。まずSPDY自体が非推奨となっており、我々のSPDYプロトコルに対応したライブラリがありません。なので、自分たちでSPDYのコードを書いて管理する必要があります。
2つ目の問題は、我々のプロトコルが標準に準拠していないことです。これは混乱を招き、ネットワークのデバッグを困難にします。
最後の問題は、TLSのほうが社内独自の暗号化方法よりも優れていて安全ですが、私たちはすべての接続でTLSを使用しているわけではません。
我々の使命は、UXを損なうことなく、高い信頼性とセキュアな接続性を確保することです。。これらのLEGYの3つの問題点を解決するLINTサブプロジェクトとして解決を試みました。LINT(LINE Improvement for Next Ten years)とは、急成長の際に見落としてきた技術長期課題をLINE Platformの次の10年を見据えて解決するプロジェクトです。
このサブプロジェクトの目標はは古いSPDYプロトコルをHTTP/2に置き換え、標準に準拠したPushメカニズムを採用して、クライアントのネットワーク環境にかかわらず、すべての接続にTLSを採用することです。では何を検討して、何が行われたかを説明していきたいと思います。
HTTP/2を使うのは非常にシンプルです。SPDYのプロトコルをHTTP/2に置き換えるだけです。ちなみに、標準的なHTTP/2を使用しており、ヘッダーキャッシュはHTTPで使用されている効率的なヘッダー圧縮法であるHPACKに置き換えられているため、使用していません。ここではSPDYとHTTP/2の比較ではなく、どのようにして安全にHTTP/2に切り替えたかに焦点を当てたいと思います。
移行を失敗させる2つの悪いケースがあります。1つ目のケースは、サーバーの実装にバグがあることです。クライアントと違って、サーバーはいつでも修正できますが、重要なのは修正にどれぐらい時間がかかるかということです。バグが単純なものではなく相応に時間がかかる場合は、修正されるまでHTTP/2を完全に無効にしておく必要があります。これが最善の対処法です。これには、クライアントがHTTP/2を使用しないように制御する機能が必要です。
2つ目のケースは、クライアント側のHTTP/2にバグが多い場合です。この場合、クライアントはリクエストの送信やレスポンスの取得に失敗する可能性があります。失敗は、一時的にも永続的にも起こり得ます。最悪の場合、LINEの全サービスへのリクエストが失敗するということになります。このような状況に対処するためには、クライアントがHTTP/2だけではなく、既存のSPDYも使用できるように維持する必要があります。
この図は、通信の仕組みを説明したものです。プロトコルを直接使うのではなく、ネットワーク抽象化レイヤーを入れてプロトコルを管理しています。どのプロトコルを使用するかを決めて、プロトコルレベルの問題を処理します。デフォルトはHTTP/2です。この抽象化層は、HTTP/2への移行だけでなく、将来のプロトコルへのアップデートにも役立ちます。
何か問題が起こると、抽象化レイヤーがそれを検知し、SPDYに切り替えます。このようにして、クライアントは前バージョンのように問題なくLINEのサービスを利用できます。すべてのクライアントでHTTP/2を無効にする必要がある場合は、外部設定を更新します。更新された設定は、クライアントのネットワーク抽象化レイヤーに伝播されます。
すると抽象化レイヤーは、使用可能なプロトコルリストからHTTP/2を除外し、クライアントはSPDYのみを使用するようになります。もちろん設定でHTTP/2をオンにすれば、ネットワーク抽象化レイヤーは再びHTTP/2を使い始めます。
クライアントの設定には、conn-infoと呼ばれるLEGYで定義されているネットワーク設定を使用します。クライアントは最初にこのconn-infoをLEGYから取得してネットワークの動作を決定します。どこに・どのように接続するか、いくつかの機能パラメーターを定義します。これは決して新しいものではありません。私たちは、HTTP/2が次の主要なプロトコルとみなされる前から、長い間conn-infoを定義して使用してきました。なぜこれが必要なのでしょうか。
それは信頼性のためです。LINEはグローバルなサービスとしてLEGYのPoP (Point of Presence)が世界中にいくつもあります。クライアントは高速で安定した通信を行うために、適切なPoPに接続できなくてはなりません。国によってネットワークの特性が異なるため、すべてのネットワークに同じネットワークポリシーを適用することはできません。クライアントの種類ごとに、独自のネットワーク設定を行い、その上で、動作するプラットフォームでのパフォーマンスを最適化できます。
またサービス機能は、アプリケーションのアップデートに合わせて追加・削除されます。そのため、基本的にはユーザーの国、クライアントの種類、そしてバージョンに応じて設定をコントロールしています。主な使用例としては、新年の準備が挙げられます。新年を迎えた直後は、トラフィックが急増することがわかっているので、自動リクエスト・再試行を無効にしたり減らしたりするように、conn-infoを設定しています。
ここではconn-infoの例を紹介します。トップレベルのキー、ここではLEGYが設定項目を示しています。この例では、LEGYサーバーの項目を設定します。次のレベルのキーは、国です。この例ではallとJPの2つがあります。allはフォールバック設定のような働きをします。日本のユーザーに使用されるJPの設定が適していない場合、クライアントはallの設定を使用します。
次のレベルでは、クライアントの種類とバージョンを指定します。この例ではクライアントのバージョンに応じて、異なる構成を定義しています。バージョンa.b.cのAndroidクライアントとバージョンx.y.zのiPhoneクライアントは、1つ目の設定を使用し、その他のクライアントは2つ目の設定を使用します。他のクライアントタイプは設定されていませんので、この構成は使用できません。
なお実際の設定ではすべてのクライアントがLEGYに接続する必要があるため、すべてのクライアントタイプとバージョンに対応した設定を行います。設定項目はモバイルとWi-Fiの2つのグループに分かれています。これはクライアントの現在のネットワーク環境に応じて、どの設定項目を使用するかを指定するものです。
それぞれにLEGYサーバーの情報が、優先順位付けで記載されています。クライアントのネットワーク抽象化レイヤーはこれを参照し、使用する適切なプロトコルを選択します。secureフィールドでは、LEGY暗号化とTLSのどちらを使用するかを指定します。特定のバージョン以降のAndroidやiPhoneのクライアントは、HTTP/2を主要なプロトコルとして使用するように設定されています。
このフィールドをSPDYに置き換えることで、HTTP/2を完全に無効にできます。クライアントがLEGYのconn-infoを使用できないケースがあります。例えばクライアントアプリケーションがユーザー端末に新規にインストールされた場合などです。この場合には、LEGYから取得したconn-infoデータがなくてもクライアントが動作できるように、LEGYはデフォルトのconn-infoをクライアントと共有する必要があります。
デフォルトのconn-infoはLEGYの設定から、別のリポジトリに抽出されます。クライアントはこのリポジトリをソースコードにインポートし、設定はアプリケーションのバイナリ内で展開されます。クライアントが実行されると、まずローカルにconn-infoのキャッシュがあるかどうかを確認します。ない場合は接続先のLEGYサーバーを決定するためにデフォルトのconn-infoを参照し、最新のconn-infoを取得します。
成功した場合は、取得したconn-infoをローカルストレージにキャッシュし、それを使用してネットワークの動作を決定します。失敗した場合は、埋め込まれたデフォルトのconn-infoを使用します。conn-infoはSPDYからHTTP/2へ安全に移行するための、主なツールとして使用されています。これが私たちの、ステップバイステップの移行プロセスです。
すべてのステップにおいて、conn-infoはHTTP/2を最優先のプロトコルと設定して、SPDYはフォールバックのプロトコルとして設定されています。開発環境でのテストのあと、私たちはHTTP/2を本番環境でリリースしましたが、更に細かな段階を踏みました。クライアント側に追加設定を設けて、HTTP/2の使用可能なユーザーをより細かく制限できるように工夫しています。
本番環境では、まずLINE社員にHTTP/2を許可し、次に日本のLINEユーザー、最後に全世界のLINEユーザーにHTTP/2通信を許可しました。ユーザーがHTTP/2の通信の仕様を禁止されている場合、conn-infoのHTTP/2 Entryはクライアントによって単に無視されます。幸いなことに、移行作業中に大きな問題は発生しなかったため、グローバルにHTTP/2を無効にするためのconn-infoの更新は行われませんでした。
現在LEGYへの接続の85パーセントが、HTTP/2を使用しています。近日中にクライアントのSPDYコードの完全削除を準備する予定です。
LINEのクライアント側の視点から解説した記事は以下をご覧ください。
(後半へつづく)
LINE株式会社
関連タグ:
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略