
Tornadoは2009年にFriendFeedが社内で使っていたWebサーバを公開した非同期I/O型のPythonフレームワークである。同年にFacebookがFriendFeedを買収したことを契機にオープンソース化され、長時間接続の多いリアルタイムサービスやCometスタイルのプッシュ通信を支える基盤として広まった。本稿ではTornadoが解こうとした問題、イベントループとコルーチンの仕組み、WebSocketなどの応用、現代のasyncioとの関係を解説する。
この記事の目次
- FriendFeedで生まれた非同期Webサーバ
- IOLoopとコルーチンによる並行処理
- WebSocketとリアルタイム配信
- asyncio時代におけるTornadoの位置づけ
- まとめ
FriendFeedで生まれた非同期Webサーバ

FriendFeedは2007年に元Google社員が立ち上げたフィード集約サービスで、ユーザーへ更新を即時配信するために長時間維持されるHTTP接続を大量にさばく必要があった。当時主流だったマルチスレッドサーバではコネクションごとのメモリ消費が大きく、Cometによる擬似プッシュには適していなかった。そこで内部で開発されたのが、epollやkqueueの上に薄く乗る単一スレッドのイベント駆動サーバTornadoである。
2009年9月、FacebookによるFriendFeed買収の直後にApacheライセンスで公開された。ノンブロッキングなHTTPサーバ、WebSocketサーバ、HTTPクライアント、テンプレートエンジンまでを一つのパッケージに含む構成は当時珍しく、Pythonでリアルタイム系を扱うときの定番として急速に普及した。
IOLoopとコルーチンによる並行処理

Tornadoの中核はtornado.ioloop.IOLoopで、ソケットの読み書き準備が整ったイベントを順に取り出してコールバックを呼び出す。古くはコールバックを直接登録するスタイルだったが、2012年のtornado.gen.coroutineデコレータでyieldベースのコルーチンが書けるようになり、コードの見通しが大きく改善した。Futureを待つことで非同期処理を逐次に記述できる。
リクエストハンドラはRequestHandlerを継承し、getやpostメソッドを定義する。非同期メソッドにすれば一つのスレッドで何千もの接続を同時に保持でき、DBアクセスや外部APIコールを並列に走らせても他の接続を阻害しない。AsyncHTTPClientを使えばクライアント側もノンブロッキングに動くため、プロキシ的なサービスにも適している。
WebSocketとリアルタイム配信

TornadoがCometやWebSocketの実装を初期から備えていたことは、ゲームのロビーサーバやチャット、株価ストリーミングといった用途に多用された理由である。WebSocketHandlerを継承してon_messageを実装するだけで双方向通信が完成し、クライアントとの接続を維持したままサーバ側からプッシュできる。
認証はクッキーやJWTを利用し、メッセージのファンアウトはRedisのPub/SubやRabbitMQと組み合わせる構成が定番である。単一プロセスでも数万接続を保持できるとはいえ、水平スケールが必要な場合はTornadoプロセスを複数立ち上げてロードバランサで分散し、状態はメッセージブローカで共有する。
asyncio時代におけるTornadoの位置づけ

Python 3.4で2014年にasyncioが標準ライブラリとして導入されると、独自のIOLoopを抱えるTornadoとの関係が問題になった。Tornadoは段階的にasyncioと相互運用できるよう改修され、5.0(2018年)以降はasyncioのイベントループ上で動作する。これによりaiohttpなど他の非同期ライブラリと自然に組み合わせられるようになった。
新規プロジェクトではFastAPIやStarlette、aiohttpを選ぶケースが増えたが、TornadoはWebSocket対応の成熟度、長年の運用実績、密結合のないシンプルなAPIから、既存資産の延長として現役で使われている。特に長時間接続を前提とするリアルタイム系では、Tornadoの設計思想は今もなお参考になる。
まとめ
Tornadoは「単一スレッドで大量接続を捌く」という実用課題から生まれた非同期Webフレームワークであり、イベントループとコルーチンの組み合わせでリアルタイム通信を素直に書ける。現在はasyncioとの統合が進み、Python非同期エコシステムの一員として安定した地位を保っている。
※本記事はIT用語辞典の手書きドラフトです。公開前に最新情報・出典を確認のうえ加筆修正してください。

コメント