Ruby で高速に OAuth で認証して アクセス する方法
結論から言うと、強力な CPU と大容量のメモリを用意して Thread を大量に作るのが一番速い。
ださいことこの上無いが、これが速いんだから仕方ない。
def self.post tokens = [] User.all.each do |u| tokens << OAuth::AccessToken.new(consumer, u.token, u.secret_token) end tokens.each do |a| @t = Thread.start do res = a.post('/statuses/update.json', {:status => "なるほど四時じゃねーの"}) rescue nil end end @t.join end
こんなの。本当にださいのだけど、これで十分なのだからしょうがない。というか Ruby でやる限りこれが一番速い。うちのそれなりのサーバーで twitter 相手で 100req/s ぐらいは出る。 CPU 使用率 70% ぐらいをうろうろする。
なるほど四時じゃねーの(http://4ji.ssig33.com)は今このだっさいコードで動いています。
ちなみに同じことを EventMachine でやるとこんな感じかな。
def self.oquno EM.run do multi = EventMachine::MultiRequest.new User.all.each do |u| request = EventMachine::HttpRequest.new('http://twitter.com/statuses/update.json') http = request.post(:body => {'status' => 'なるほど四時じゃねーの'}, :head => {"Content-Type" => "application/x-www-form-urlencoded"}) do |client| consumer.sign!(client, OAuth::AccessToken.new(consumer, u.token, u.secret_token)) end multi.add http end multi.callback do EM.stop_event_loop end end end
なにがボトルネックになってるのかは知らんが、 em-http-request を使うと、 twitter 相手に 35req/s ぐらいしか出ない。ちなみに何も考えないでシリアルにアクセスすると 1req/s ぐらいしか出ない。
twitter が十分に遅いというのを勘案しても、驚異的に遅い。ちなみに curl を使ってパラレルに HTTP アクセスする typhoeus は OAuth にろくに対応していない。
じゃあ em-http-request に使い道は無いかというとそうではなくて、 Twitter Streaming API を OAuth 経由でアクセスするのに使えます。
def self.fuba EM.run do u = User.find_by_name('ssig33') request = EventMachine::HttpRequest.new('http://betastream.twitter.com/1/statuses/filter.json?track=http') http = request.get(:head => {"Content-Type" => "application/x-www-form-urlencoded"}) do |client| consumer.sign!(client, OAuth::AccessToken.new(consumer, u.token, u.secret_token)) end http.stream { |chunk| print chunk } end end
BASIC 認証はそのうち廃止されるらしいので、 Streaming API にアクセスしているコードは、順次このように OAuth に置き換えるのがよいでしょう。 http://nl.amatz.com/ とかで em-http 使った Streaming Access を実際に投入してる。