すぐやらなきゃいけないことと、それ以外と。

月燈火のサーバ負荷がどうしようもない状況になってきたので、改修する必要が出てきた。何が足を引っ張っていたのかというと、登録されているフィードを巡回して新着記事を取得、要約して類似記事を探すという一連の処理。
この処理はcronで1日1回実行されているんだけど、従来の実装はこんな感じだった。

  • 処理起動用のアクションをcronからcurlでキック
  • アクションないで全フィードごとの巡回処理をAP4Rのキューに追加
  • AP4Rによって1フィードの巡回アクションがキックされる
  • フィード内の新着ページが登録され、AP4Rのキューに次の3タスクが追加される
    • ページの内容取得
    • 文章要約
    • 類似ページ検索
  • それぞれのタスクが消化される

綺麗にAP4Rを使った非同期実装。なんだけど、各タスクがRailsのアクションとして実行されると言うことは、それだけHTTPだのRailsだののオーバーヘッドが効いてくる上にdispatcherを一つ占拠することになる。FastCGIで動いているのでRails起動のオーバーヘッドはないけど、それ以外のも結構あるようでかなり時間がかかる。
そこで、内容取得~類似検索までを一本のスクリプトにまとめた上で、script/runnerを使って処理するように変更。フィード巡回処理は定期実行以外にも使われる可能性があるので従来の実装のまま。
この書き直しの結果、処理に取られるリソースが劇的に減った。従来の実装だとヘタすると12時間かかってた(!)のが、1時間に収まってしまうようになった。いくら何でも減りすぎなんだけど、処理結果はちゃんと出来上がってるので問題はないらしい。これで月燈火自体のレスポンスもかなり改善され、同一サーバに収容してる読書びよりに悪影響を与えることもなくなった。


AP4Rとscript/runner、使い分けてやるのが弱いサーバにとっては優しい。AP4Rで非同期実装すると、同期処理みたいにクライアントをブロックはしないけど出来るだけ速やかに処理を始め、終えてくれるのが利点。クライアントがいつ処理を要求するかわからない場合にはこれが最適。逆に、夜間バッチ処理みたいなことをやる場合はscript/runnerでやってしまった方がいい。