ActiveResourceをUNIX Domain Socketで使ってみる
現状、内部APIとの通信はHTTPで行われており、localhostへの接続とはいえそれなりに通信コストがかかっているため、今後、内部APIはPHP-FPMで動かし、unix domain socket経由で叩けるようにしたいところです。
http://inside.pixiv.net/blog/2012/11/08/pixiv-dot-comfalsequan-ti-xiang/
ふむふむ。
ActiveResource で UNIX Domain Socket 叩けるんだろうかと思って実験してみた。
このあたりを参考にしながら準備。
適当な Rails アプリケーションを作って、
% rails new crazyresource -J -O % cd crazyresource
Gemfile を作って、
source 'https://rubygems.org' gem 'rails', '3.2.11' gem 'activeresource'
bundle install して、
% bundle install --path vendor/bundle
適当な scaffold を作る。(bookmark というのは参考にしたサイトにあわせた)
% bundle exec rails generate scaffold bookmark title:string url:string comment:text
で、まずは普通に http://localhost:8080 からリソースを取得するようにしてみて、
% vi app/models/bookmark.rb
class Bookmark < ActiveResource::Base self.site = 'http://localhost:8080/' end
次にポート 8080 に nginx を立てた。
% mkdir nginx % mkdir nginx/logs % mkdir nginx/html % echo '[{"comment":"Google Search","id":1,"title":"Google","url":"http://www.google.com/"}]' > nginx/html/bookmarks.json % vi nginx/nginx.conf
nginx.conf はこんな感じ。
worker_processes 1; events { worker_connections 1024; } http { server { listen 8080; server_name localhost; location / { root html; } } }
nginx 起動。
% nginx -p $PWD/nginx -c nginx.conf % curl "http://localhost:8080/bookmarks.json" [{"comment":"Google Search","id":1,"title":"Google","url":"http://www.google.com/"}]
ここまでできたら Rails を起動して、
% bundle exec rails server
リソースが取得できることを確認。
% curl "http://localhost:3000/bookmarks.json" [{"bookmark":{"comment":"Google Search","id":1,"title":"Google","url":"http://www.google.com/"}}]
nginx は UNIX Domain Socket でもリクエストを受け付けられるので、設定を以下のように変えて、
worker_processes 1; events { worker_connections 1024; } http { server { listen unix:/tmp/nginx.sock; server_name localhost; location / { root html; } } }
nginx を再起動すると、
% nginx -s stop % nginx -p $PWD/nginx -c nginx.conf
curl "http://localhost:3000/bookmarks.json"
は失敗するようになる。
これでようやく準備完了。
次に、unix_socket_hack というのを使う。
Gemfile にこういうのを追加して、bundle install する。
gem 'unix_socket_hack', :git => 'git://github.com/walf443/unix_socket_hack.git'
実は Net::HTTP だと unix_sock_hack がうまく動かないので、 https://github.com/walf443/unix_socket_hack/issues/2 に書いたような変更を 対応してもらいました。vendor/bundle/ruby/1.9.1/bundler/gems/unix_socket_hack-93e97dea2425/lib/unix_socket_hack.rb
に加える。
localhost:8080 への TCPSocket を乗っ取って /tmp/nginx.sock への UNIXSocket にしたいので、 config/application.rb
にこういうのを追加しして、
require 'unix_socket_hack' UNIXSocketHack.apply({ 'localhost:8080' => '/tmp/nginx.sock' })
Rails を再起動すると、また動くようになった。
% curl "http://localhost:3000/bookmarks.json" [{"bookmark":{"comment":"Google Search","id":1,"title":"Google","url":"http://www.google.com/"}}]
nginx のログに unix: というのがあるので、ちゃんと UNIX Domain Socket でアクセスしてることがわかる。
% tail -f nginx/logs/access.log unix: - - [20/Jan/2013:18:10:23 +0900] "GET /bookmarks.json HTTP/1.1" 200 85 "-" "Ruby"