C.Scott Andreas「C500k in Action at Urban Airship」
Urban Airship Blog 2010.8.24のエントリ
C500k in Action at Urban Airship
- push通知サービスの代行サービスをやってるUrban Airshipのシリーズ物のエントリ1回目
- (補足)OpenID関連のサービスやってたVidoopという死亡したスタートアップ(パテントは会社ごと買収されてた)の元メンバーがやってる
- Amazon EC2でクラウド破産は避けたい
- python/c/c++/node.js/java/scalaと色々作っては試した
- NIO(java)に落ち着いた。現在1インスタンスでc500k(使用メモリ2.5GB)
以下斜め読んだ内容
- AirMail PushというサービスのAndroid版の開発を前からずっとやってる
- AirMailのサービスで必要とされること
- 数百万単位のデバイスへの同時接続をサポートできるサーバが必要
- サーバとデバイス間で永続的なソケット通信
- リアルタイムでデバイスにメッセージをpushできる
- 使われてないソケットを検出して閉じる
- ネットワーク外に出たユーザ・ネットワーク内に復帰したユーザとのコネクションのコントロール
- push通知サービスの裏側で稼動してるサーバの設計では色々問題にぶつかって解決してきた
- サーバーを何度も設計しなおした
- 色々やった結論。JavaのNIOを使ったアーキテクチャ
- スレッド/イベント/キューベースのハイブリッド型
- おさらい:デバイスへのpush通知に必要なこと
- 永続的なソケット通信
- Urban Airshipのpush通知用プラットフォームでは数百万単位での同時接続が必要
- 各ノードが大量の同時接続を維持しながらメッセージの受信やpush通知をエレガントにさばくことが必要になる
- 1ノードでどれだけ同時接続をさばけるかが重要
- 1万/nodeの場合
- 100万デバイスだったらサーバ100台必要で、1000万デバイスへのpush通知だったら・・・・
- 金がかかりすぎる・金が足りないということになる
- 1万/nodeの場合
- Helium
- 初代エッジサーバ
- pythonのEventlet使った
- Eventletはいいライブラリ
- 軽量のコルーチンで並列処理
- Eventletのソケットの実装は優秀
- コンテキストスイッチが手軽でオーバーヘッドも少ない
- この点スレッドベースのサーバーと対照的
- 大量のコネクションをコントロールしやすい
- コンテキストスイッチが手軽でオーバーヘッドも少ない
- Eventletベースで作ったHeliumはコードもクリーンで理解しやすかった
- Eventletベースの初代Heliumのパフォーマンス
- インフラには投資はコンスタントにやっている
- 安定さとパフォーマンスの向上のためには必要
- われわれはインフラ屋というよりはプログラマの方が向いてる
- よりパフォーマンス面でもコスト面でも効率のいいソフトウェアを書きたいと思ってる
- なので作り直し。
- Eventletベースの初代Heliumよりもパフォーマンスの優れたソケットサーバーの探求を始めた
- javaのNIOライブラリ
- NIO:new/non-blocking IO
- 軽く試したらかなり優秀だったので、色々検証してみた
- NIOだけの実装、Nettyの上にNIOのせた実装、Scala版Nettyの上にNIO載せた実装。この3つを比較
ベンチマーク1(最大同時接続数)
Implementation | Connections | Memory Used |
---|---|---|
Java Pure NIO | 512,000 + | 2.5 GB |
Java w/Netty | 330,000 | 2.2 GB |
Scala w/Netty | 173,000 | 1.5 GB |
ベンチマーク2(コネクションごとのメモリ使用の効率性)
Implementation | Connections | Memory Used | Delta |
---|---|---|---|
Java Pure NIO | 80,000 + | 581 MB | 1x |
Java w/Netty | 80,000 | 711 MB | 1.3x |
Scala w/Netty | 80,000 | 937 MB | 2.26x |