2014年12月29日月曜日

nginxとunicornの環境でtimeoutエラーが出たときの対応

nginx+unicornな環境で、かなり大きいファイルをダウンロードしたいとの要望があって、
実装してみたらタイムアウトが出てしまったのでそのときにした対応を載せていきます。

まず最初にunicorn.logに出てたエラーがこれです。
E, [2014-12-19T10:06:30.924665 #17078] ERROR -- : worker=1 PID:17094 timeout (31s > 30s), killing
E, [2014-12-19T10:06:30.973611 #17078] ERROR -- : reaped # worker=1
nginx.logにもエラーが出ていました。
2014/12/19 10:06:30 [error] 26747#0: *54198 upstream prematurely closed connection while reading response header from upstream, client: 172.23.151.25, server: aaa.bbb.com, request: "GET /user_list HTTP/1.1", upstream: "http://unix:/tmp/unicorn.sock:/user_list", host: "aaa.bbb.com", referrer: "https://aaa.bbb.com/"
unicornのtimeoutの設定を30秒にしていたので、それを超えたタイミングでエラーになったようです。
なので次はtimeoutを90秒に変えてリトライしてみました。

今度はnginx.logに違うエラーが出ていました。
2014/12/19 10:20:18 [error] 26747#0: *54253 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 172.23.151.25, server: aaa.bbb.com, request: "GET /user_list HTTP/1.1", upstream: "http://unix:/tmp/unicorn.sock/user_list", host: "aaa.bbb.com", referrer: "https://aaa.bbb.com/"
nginxのタイムアウト設定まわりでエラーになっていると思われるので、
いろいろなタイムアウト設定を一つずつ追加していってみました。
    send_timeout 120s;
    fastcgi_read_timeout 120s;
    fastcgi_send_timeout 120s;
 
    location @unicorn {
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Proto https;
      proxy_pass http://unicorn;
      proxy_send_timeout 120s;
      proxy_read_timeout 120s;
    }
上から順にこれだけタイムアウトの設定を追加していったところ、エラーが出ないようになりました。
すべては必要なさそうに思えたので検証していったところ、これだけでOKでした。
proxy_read_timeout 120s;

参考URL
http://server-setting.info/centos/nginx-upstream-timed-out.html
http://hack.aipo.com/archives/3738/
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout

2014年12月27日土曜日

CentOS6.5にruby2.2.0を入れてみた

CentOS6.5にruby2.2.0を入れてみました。

rubyのバージョン管理はrbenvとruby-buildでやっています。
そのインストールは別途調べてください。

まずはruby-buildをアップデートします。
アップデート後にインストールできるバージョンを確認すると、2.2.0が追加されています。
# rbenv install -l
Available versions:
  1.8.6-p383
  1.8.6-p420
  1.8.7-p249
  1.8.7-p302
  1.8.7-p334
  1.8.7-p352
  1.8.7-p357
  1.8.7-p358
  1.8.7-p370
  1.8.7-p371
  1.8.7-p374
  1.8.7-p375
  1.9.1-p378
  1.9.1-p430
  1.9.2-p0
  1.9.2-p180
  1.9.2-p290
  1.9.2-p318
  1.9.2-p320
  1.9.2-p326
  1.9.2-p330
  1.9.3-dev
  1.9.3-preview1
  1.9.3-rc1
  1.9.3-p0
  1.9.3-p125
  1.9.3-p194
  1.9.3-p286
  1.9.3-p327
  1.9.3-p362
  1.9.3-p374
  1.9.3-p385
  1.9.3-p392
  1.9.3-p429
  1.9.3-p448
  1.9.3-p484
  1.9.3-p545
  1.9.3-p547
  1.9.3-p550
  1.9.3-p551
  2.0.0-dev
  2.0.0-preview1
  2.0.0-preview2
  2.0.0-rc1
  2.0.0-rc2
  2.0.0-p0
  2.0.0-p195
  2.0.0-p247
  2.0.0-p353
  2.0.0-p451
  2.0.0-p481
  2.0.0-p576
  2.0.0-p594
  2.0.0-p598
  2.1.0-dev
  2.1.0-preview1
  2.1.0-preview2
  2.1.0-rc1
  2.1.0
  2.1.1
  2.1.2
  2.1.3
  2.1.4
  2.1.5
  2.2.0-dev
  2.2.0-preview1
  2.2.0-preview2
  2.2.0-rc1
  2.2.0
  jruby-1.5.6
  jruby-1.6.3
  jruby-1.6.4
  jruby-1.6.5
  jruby-1.6.5.1
  jruby-1.6.6
  jruby-1.6.7
  jruby-1.6.7.2
  jruby-1.6.8
  jruby-1.7.0-preview1
  jruby-1.7.0-preview2
  jruby-1.7.0-rc1
  jruby-1.7.0-rc2
  jruby-1.7.0
  jruby-1.7.1
  jruby-1.7.2
  jruby-1.7.3
  jruby-1.7.4
  jruby-1.7.5
  jruby-1.7.6
  jruby-1.7.7
  jruby-1.7.8
  jruby-1.7.9
  jruby-1.7.10
  jruby-1.7.11
  jruby-1.7.12
  jruby-1.7.13
  jruby-1.7.14
  jruby-1.7.15
  jruby-1.7.16
  jruby-1.7.16.1
  jruby-1.7.16.2
  jruby-1.7.17
  jruby-1.7.18
  jruby-9.0.0.0-dev
  jruby-9.0.0.0+graal-dev
  jruby-9000-dev
  jruby-9000+graal-dev
  maglev-1.0.0
  maglev-1.1.0-dev
  maglev-2.0.0-dev
  mruby-dev
  mruby-1.0.0
  rbx-1.2.4
  rbx-2.0.0-dev
  rbx-2.0.0-rc1
  rbx-2.0.0
  rbx-2.1.0
  rbx-2.1.1
  rbx-2.2.0
  rbx-2.2.1
  rbx-2.2.2
  rbx-2.2.3
  rbx-2.2.4
  rbx-2.2.5
  rbx-2.2.6
  rbx-2.2.7
  rbx-2.2.9
  rbx-2.2.10
  ree-1.8.6-2009.06
  ree-1.8.7-2009.09
  ree-1.8.7-2009.10
  ree-1.8.7-2010.01
  ree-1.8.7-2010.02
  ree-1.8.7-2011.03
  ree-1.8.7-2011.12
  ree-1.8.7-2012.01
  ree-1.8.7-2012.02
  topaz-dev

早速2.2.0をインストールしてみます。
# rbenv install 2.2.0
Downloading ruby-2.2.0.tar.gz...
-> http://dqw8nmjcqpjn7.cloudfront.net/7671e394abfb5d262fbcd3b27a71bf78737c7e9347fa21c39e58b0bb9c4840fc
Installing ruby-2.2.0...
 
BUILD FAILED (CentOS release 6.5 (Final) using ruby-build 20141225-1-g45b75ed)
 
Inspect or clean up the working tree at /tmp/ruby-build.20141226162728.13624
Results logged to /tmp/ruby-build.20141226162728.13624.log
 
Last 10 log lines:
make[3]: ディレクトリ `/tmp/ruby-build.20141226162728.13624/ruby-2.2.0/ext/fiddle/libffi-3.2.1' から出ます
linking shared-object fiddle.so
/usr/bin/ld: ./libffi-3.2.1/.libs/libffi.a(raw_api.o): relocation R_X86_64_32 against `.text' can not be used when making a shared object; recompile with -fPIC
./libffi-3.2.1/.libs/libffi.a: could not read symbols: Bad value
collect2: ld はステータス 1 で終了しました
make[2]: *** [../../.ext/x86_64-linux/fiddle.so] エラー 1
make[2]: ディレクトリ `/tmp/ruby-build.20141226162728.13624/ruby-2.2.0/ext/fiddle' から出ます
make[1]: *** [ext/fiddle/all] エラー 2
make[1]: ディレクトリ `/tmp/ruby-build.20141226162728.13624/ruby-2.2.0' から出ます
make: *** [build-ext] エラー 2
エラーが出ました。
libffi云々でエラーが出ました。
libffiのインストール状況とリポジトリの情報を調べてみました。
# yum list installed|grep libffi
libffi.x86_64           3.0.5-3.2.el6   @anaconda-CentOS-201311291202.x86_64/6.5

# yum search libffi
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
 * base: ftp.tsukuba.wide.ad.jp
 * epel: ftp.tsukuba.wide.ad.jp
 * extras: ftp.tsukuba.wide.ad.jp
 * updates: ftp.tsukuba.wide.ad.jp
============================================================================= N/S Matched: libffi =============================================================================
libffi-devel.i686 : Development files for libffi
libffi-devel.x86_64 : Development files for libffi
libffi.i686 : A portable foreign function interface library
libffi.x86_64 : A portable foreign function interface library
 
  Name and summary matches only, use "search all" for everything.
libffi-devel.x86_64を入れてみて、再度2.2.0のインストールを実行すると成功しました。
# rbenv versions
  2.2.0

参考URL
http://qiita.com/MorimotoYasunori@github/items/fb81946fc088b18d6a3a

2014年12月21日日曜日

jquery mobileを使っていたら次のページが表示されない

スマホ用サイトを作っててjquery mobileを使ってたら、
次のページに遷移したら真っ白で表示されなかった時の対応です。

まず普通に開発してたらこんな感じの記載をするかと思います。
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.js"></script>

そうすると、最初のページはちゃんと表示されるけれども、
次のページに遷移すると真っ白になりました。
どうやらjquery mobileがajaxで遷移を制御しているのと、
次のページをキャッシュしてそうなあたりが原因なようです。
ということで、以下の記述を入れるとよさそうです。
<script>
    $(document).bind("mobileinit", function(){
        $.mobile.ajaxEnabled = false;
        $.mobile.pushStateEnabled = false;
    });
</script>

これをjquery mobileのjs読み込みの前に入れます。
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
    $(document).bind("mobileinit", function(){
        $.mobile.ajaxEnabled = false;
        $.mobile.pushStateEnabled = false;
    });
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.js"></script>

表示されなかった現象は解決して、ちゃんと遷移できるようになりました。


参考URL
http://blog.ym405nm.info/archives/528

2014年12月10日水曜日

capistrano3でproduction環境にdeployしたらassets precompileが走らなかった件

railsアプリを作っててcapistrano3でdeployをするようにしていたのですが、
production環境にdeployしたらcssやjsが見れなくて調べたところ、
assets precompileが走ってなかったためでした。
で、なぜassets precompileが走らなかったか調べてみた時のことを書いていきます。

まず、Capfileはこんな感じで、
require 'capistrano/rails/assets'はちゃんと記述していました。
# Load DSL and Setup Up Stages
require 'capistrano/setup'
 
# Includes default deployment tasks
require 'capistrano/deploy'
 
# Includes tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/bundle_rsync'
require 'capistrano3/unicorn'
 
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

deploy/production.rbのserver設定は以下のように書いていました。
server 'host0001', user: 'root', roles: %w{app}

この設定でだめだったので、とりあえずいろいろとGoogle先生で調べてみましたがよくわかりませんでした。
なので、capistranoのソースを読んでみたところ、原因がわかりました。
precompileを実行するためのrolesはwebじゃないと動かないように書いてありました。
capistaranoのコードから抜粋
  namespace :assets do
    task :precompile do
      on roles(fetch(:assets_roles)) do
        within release_path do
          with rails_env: fetch(:rails_env) do
            execute :rake, "assets:precompile"
          end
        end
      end
    end
......
    set :assets_roles, [:web]

なので、deploy/production.rbのserver設定を以下のように変更したところ、ちゃんとprecompileが動くようになりました。
server 'host0001', user: 'root', roles: %w{app web}
完全に無知のためにはまった内容ですが、何かの役に立てばと思って書いてみました。


参考URL
https://github.com/capistrano/rails/blob/5f112183dad808078a56c8558046d84d182eddf6/lib/capistrano/tasks/assets.rake

2014年12月3日水曜日

railsでcsvダウンロードできるようにしたらexcelで文字化けした件

データをcsvでダウンロードしたいって要望があったので、
railsでcsvダウンロード機能を作ったら、excelで開いたら文字化けするって言われた時の対応です。

バージョンは以下で試しました。
ruby 2.1.2
rails 4.1.5

まず最初に書いたcsvダウンロード部分を抜粋。
ローカルにファイルを出力して、それをsend_fileで返す形です。
  filename = '/tmp/test.csv'
  line = ['aa','bb','cc']
  open(filename,"w"){|f|
    f.puts(line.join(','))
  }
 
  stat = File.stat(filename)
  send_file(filename, :filename => 'test.csv', :length => stat.size)
この形だとファイルの文字コードがUTF-8になります。
UTF-8だとexcelで開いた時には文字化けしました。
(Libre Officeだと最初にencodeをどれにするか聞かれたので、UTF-8にすれば問題なく開けました。)

最初の処理から文字コードを変えた形。
  filename = '/tmp/test.csv'
  line = ['aa','bb','cc']
  open(filename,"w:cp932"){|f|
    f.puts(line.join(','))
  }
 
  stat = File.stat(filename)
  send_file(filename, :filename => 'test.csv', :length => stat.size)
ローカルにファイルを出力するタイミングで
文字コードの指定を「cp932」にしてあげると、
文字化けせずにexcelで開けるようになりました。
macのexcelでもUTF-8だと文字化けしたのが、excelがっかりだなぁと思ったりした次第です。

参考URL
http://tmtms.hatenablog.com/entry/20120812/ruby_encoding