Atom上でRailsプロジェクト内のファイル移動を楽にするRails-Transporterというパッケージを書いた
最近Emacsからgithub製のテキストエディターであるAtomに移行しました。慣れるまで1週間ほど移行期間は必要でしたがデフォルトの設定で十分高機能で使いやすいです。自分は普段の仕事ではRailsアプリの開発をする事が多いのでRails開発で使える便利そうなパッケージを探してみたんですが、自分にあいそうなものがなかったのでrails-transporterというパッケージを作りました。
プロジェクト内のファイル移動を簡単にすることを目的にしており、下記のコマンドが使えるようになります。
20150323 追記
- キーバインドを変更
- コマンドを追加
Command
open-controller(ctrl-r c)
model, view, controller-specのどれかを開いてる時、
app/models/blog.rb app/views/blogs/show.html.erb spec/controllers/blogs_controller_spec.rb
関連するcontrollerを開きます。
app/controllers/blogs_controller.rb
open-view(ctrl-r v)
controllerのアクションメソッド内カーソルがある時に対応するviewを開きます。
下記例でindexメソッド内にカーソルがあれば対応するviewを開きます。
class UsersController < ApplicationController def index @users = User.all end def show @user = User.find(params[:id]) end end
open-view-finder(ctrl-r v f)
controller, modelのどれかを開いてる時、
app/controllers/blog_controller.rb app/models/blog.rb
関連するviewのリストを開きます
app/views/blogs/show.html.erb app/views/blogs/index.html.erb
open-model(ctrl-r m)
controller, view, model-specのどれかを開いてる時、
app/controllers/blogs_controller.rb app/views/blogs/show.html.erb spec/models/blog_spec.rb
関連するmodelを開きます。
app/models/blog.rb
open-helper(ctrl-r h)
controllerを開いてる時、
app/controllers/application_controller.rb
関連するhelperを開きます。
app/helpers/application_helper.rb
open-spec(ctrl-r s)
controller, helper, modelのどれかを開いてる時、
app/controllers/blogs_controller.rb app/helpers/blogs_helper.rb app/models/blog.rb
関連するspecを開きます。
spec/controllers/blogs_controller_spec.rb spec/helpers/blogs_helper_spec.rb spec/models/blog_spec.rb
open-partial-template(ctrl-r p)
view内のrenderメソッドにカーソルがある時、
render "form"
関連する部分テンプレートを開きます。
app/views/blogs/_form.html.erb
open-asset(ctrl-r a)
カーソルがstylesheet_link_tag、javascript_include_tagにある時、
<%= javascript_include_tag "application" %> <%= stylesheet_link_tag "application" %>
関連するassetマニフェストファイルを開きます。
app/assets/javascripts/application.js app/assets/stylesheets/application.js
assetマニフェストファイル内のrequireメソッドにカーソルがある時、
//= require blogs
関連するassetファイルを開きます。
app/assets/javascripts/blogs.js.coffee
assetマニフェストファイル内のrequire_tree、require_directoryにカーソルがある時、
//= require_tree shared //= require_directory shared
関連するassetファイルのリストを開きます。
app/assets/javascripts/shared/file1.js.coffee app/assets/javascripts/shared/file2.js.coffee app/assets/javascripts/shared/file3.js.coffee
open-migration(ctrl-r d m)
migrationのリストを開きます
db/migrate/20140502021836_create_blogs.rb db/migrate/20140512015127_create_entries.rb
open-layout(ctrl-r l)
controllerに対応するlayoutファイルを開きます。
open-factory(ctrl-r f)
model、model-specに対応するfactoryファイルを開きます。
RailsでArgumentError: invalid byte sequence in UTF-8が発生する場合の解決策
Railsで作成されたアプリケーションのリクエストURLにURLエンコード(壊れていてUTF8にデコードできない)された文字列を含めるとArgumentErrorが発生します。
再現方法
サンプルプロジェクトを構築
# railsの最新版をインストール $ gem install rails # プロジェクトのセットアップ $ rails new invalid-byte-sequence-in-utf8-demo $ cd invalid-byte-sequence-in-utf8-demo $ bundle install # 開発サーバ起動 $ rails server => Booting WEBrick => Rails 4.0.4 application starting in development on http://0.0.0.0:3000 => Run `rails server -h` for more startup options => Ctrl-C to shutdown server [2014-03-30 16:02:55] INFO WEBrick 1.3.1 [2014-03-30 16:02:55] INFO ruby 2.0.0 (2013-11-22) [x86_64-darwin13.0.0] [2014-03-30 16:02:55] INFO WEBrick::HTTPServer#start: pid=2000 port=3000
サンプルURL
# 正常なリクエストは成功
http://localhost:3000
# 不正な文字列を付与したリクエストは失敗
http://localhost:3000/?%8E%96%9B%26frac12%3Bae%9A%84%97%94%9F%9A%84%26sup3%3B%84ae%80
ArgumentError - invalid byte sequence in UTF-8:が発生する。
対応方法
この例外を無視する事もできるが解決する方法も2つある。
例外が発生するより前の段階で400 bad requestを返すようにする
このブログポストに書いてあり通り、Rackミドルウェアを追加してURLがUTF8にデコードできるかどうか検査して、できない場合は400エラーを返すシンプルな実装方法。
デコードできない文字列を無視して処理する
utf8-cleanerを使ってデコードできない文字列を無視してしまって、正常にデコード出来る文字列だけを処理する。
utf8-cleanerがやってる事
lib/utf8-cleaner/middleware.rb
1. Rackミドルウェアを追加してsanitize_envメソッドが各リクエストの前処理として呼び出される
2. sanitize_envメソッドではHTTP_REFERERやPATH_INFOといったURLに関連する環境変数のチェックをしている
3. 各環境変数に%が含まれる場合は後述のuri_string.rbで定義されているURIString#cleanedメソッドにその値を渡して実行している
module UTF8Cleaner class Middleware SANITIZE_ENV_KEYS = [ "HTTP_REFERER", "PATH_INFO", "QUERY_STRING", "REQUEST_PATH", "REQUEST_URI", "HTTP_COOKIE" ] def initialize(app) @app = app end def call(env) @app.call(sanitize_env(env)) end private def sanitize_env(env) SANITIZE_ENV_KEYS.each do |key| next unless value = env[key] if value.include?('%') env[key] = URIString.new(value).cleaned end end env end end end
utf8-cleaner/lib/utf8-cleaner/uri_string.rb
1. cleanedメソッドはまず渡された文字列がUTF8としでデコードできるか検査する
2. 文字列に問題なければなにもしない、問題がある場合は文字列を1文字ずつ検査
4. 文字が'%'の場合はその次とその次の文字をチェックして何バイトのUTF8の文字になるかをチェック
5. 不正な文字として判断されたらURL文字列から除かれる
6. 最終的に不正な文字列は除かれているのでArgumentErrorは発生しなくなる
module UTF8Cleaner class URIString attr_accessor :data def initialize(data) self.data = data end def cleaned if valid? data else encoded_char_array.join end end def encoded? data.include?('%') end def valid? valid_uri_encoded_utf8(data) end private # Returns an array of valid URI-encoded UTF-8 characters. def encoded_char_array char_array = [] index = 0 while (index < data.length) do char = data[index] if char == '%' # Skip the next two characters, which are the encoded byte # indicates by this %. (We'll change this later for multibyte characters.) skip_next = 2 # How long is this character? first_byte = '0x' + (data[index + 1] + data[index + 2]).upcase bytes = utf8_char_length_in_bytes(first_byte) # Grab the specified number of encoded bytes utf8_char_encoded_bytes = next_n_bytes_from(index, bytes) # Did we get the right number of bytes? if utf8_char_encoded_bytes.length == bytes # We did. Is it a valid character? utf8_char_encoded = utf8_char_encoded_bytes.join if valid_uri_encoded_utf8(utf8_char_encoded) # It's valid! char_array << utf8_char_encoded # If we're dealing with a multibyte character, skip more than two # of the next characters, which have already been processed. skip_next = bytes * 3 - 1 end end index += skip_next else # This was not an encoded character, so just add it and move to the next. char_array << char end index += 1 end char_array end def valid_uri_encoded_utf8(string) URI.decode(string).force_encoding('UTF-8').valid_encoding? end # Grab the next num_bytes URI-encoded bytes from the raw character array. # Returns an array like ['%E2', '%9C', '%93'] def next_n_bytes_from(index, num_bytes) return [] if data.length < index + (3 * num_bytes) num_bytes.times.map do |n| # Look for percent signs in the right places pct_index = index + (3 * n) if data[pct_index] == '%' byte = data[pct_index + 1..pct_index + 2] else # An expected percent sign was missing. The whole character is invalid. return [] end '%' + byte end end # If the first byte is between 0xC0 and 0xDF, the UTF-8 character has two bytes; # if it is between 0xE0 and 0xEF, the UTF-8 character has 3 bytes; # and if it is 0xF0 and 0xFF, the UTF-8 character has 4 bytes. # first_byte is a string like "0x13" def utf8_char_length_in_bytes(first_byte) if first_byte.hex < 'C0'.hex 1 elsif first_byte.hex < 'DF'.hex 2 elsif first_byte.hex < 'EF'.hex 3 else 4 end end end end
まとめ
utf8-cleanerを使うことでこのようなリクエストであっても正常に処理できるがそもそもリクエストされたURLを改変して処理するのでもはや処理する意味がない気がする。参考にさせてもらったブログの人がthis issue is not super-importantって言ってるのに同意でこの例外は無視してもいいし、気になる人は400エラーを返すのが一番綺麗なやり方かなと思う。
それでもこのようなリクエストを正常なレスポンスで返したい場合は自己責任でutf8-cleanerを使うといいと思う。
Apache Passengerの設定項目について調べた
PassengerはRailsを動かす事ができるアプリケーションサーバである。
Apache版の設定項目について調べたので自分用の備忘録として残しておく。
バージョン
Passenger-4.0.37
http://www.modrails.com/documentation/Users%20guide%20Apache.html
Configuring Phusion Passenger
PassengerRoot
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerroot_lt_directory_gt
apacheのpassengerモジュールの置いてあるディレクトリを指定する。
普通はインストーラを実行した時に表示されるのでそれを使えばよい。rubyのインストール場所をかえた場合などはこちらの値も変更する必要がある。
PassengerDefaultRuby
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerDefaultRuby
アプリケーションとInternalHelper(例:PassengerPreStart)が使うRubyインタプリタを指定する。
PassengerRoot同様にインストーラ実行時に表示されるのでそれを使えば良い。
Deployment options
PassengerEnabled
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerEnabled
指定したコンテクストでPassengerを無効化出来る。
PassengerRuby
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerRuby
VirtualHostやDirectory等のコンテクストで使うRubyインタプリタを指定できる。PassengerDefaultRubyをOverrideできる。
この設定ができることにより、アプリケーション毎に使うRubyのバージョンを混在することが可能になる。
ただし、InternalHelperスクリプトは常にPassengerDefaultRubyで指定されたインタプリタを使う。
PassengerPython
PassengerRubyと同じ。
PassengerNodejs
PassengerRubyと同じ。
PassengerAppEnv
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerAppEnv
下記の環境変数を指定する。stagingなど指定することでアプリケーションの環境を切り替える事ができる。
RAILS_ENV
RACK_ENV
WSGI_ENV
NODE_ENV
PASSENGER_ENV
RailsEnv
PassengerAppEnvのエイリアス。
RackEnv
PassengerAppEnvのエイリアス。
PassengerAppRoot
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerAppRoot
アプリケーションのルートディレクトリを指定する。
デフォルトはDocumentRootの親ディレクトリ
PassengerRestartDir
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerrestartdir_lt_directory_gt
アプリケーションを再起動するためにはrestart.txtをtouchする必要がある。
restart.txtを配置するディレクトリを指定する。
デフォルトはPassengerAppRoot配下のtmpディレクトリ。
PassengerRollingRestarts(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerRollingRestarts
OSS版の最大の弱点と言っても過言ではないのがdeploy後のダウンタイムである。Rolling Restartをonにすることでunicornのようにゼロダウンタイムdeployが可能になる。
通常のRestartの場合、workerプロセスを一度全てshutdownしてから新しいプロセスを作るのに対して、1プロセスずつ入れ替えてdeployしてくれるのがRollingRestartsである。
Phusion Passenger Enterprise: rolling restarts from Phusion on Vimeo.
PassengerResistDeploymentErrors(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerResistDeploymentErrors
DeployしたコードにSyntaxErrorなどがあった場合、壊れたコードは実際には使われずにDeploy前のバージョンが使われてDeployに失敗した事がログに出力される。
この機能はRollingRestart機能が有効になっていないと作動しないので注意が必要だ。
Phusion Passenger Enterprise: deployment error resistance from Phusion on Vimeo.
Process spawning options
PassengerSpawnMethod
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerSpawnMethod
worker生成の方法を指定する。
smartとdirectがありsmartはアプリケーションコードをcacheするために生成がdirectに比べて速いが、アプリがMemcachedとのコネクションを持っている場合などは注意が必要になる。
RailsでMemcachedを使っている場合は下記設定をアプリのコードに書いてworkerプロセス毎に再接続を行う必要がある。
if defined?(PhusionPassenger) PhusionPassenger.on_event(:starting_worker_process) do |forked| if forked # We're in smart spawning mode. reestablish_connection_to_memcached else # We're in direct spawning mode. We don't need to do anything. end end end
PassengerLoadShellEnvvars
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerLoadShellEnvvars
シェルがbashの場合、環境変数をロードする。
Security options
PassengerUserSwitching
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerUserSwitching
全てのPassengerプロセスを同一のユーザーにしないことでセキュリティを担保する
PassengerGroup
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerGroup
Passengerのプロセスはデフォルトではconfign/enviroment.rbかconfig.ruファイルの所有グループを引き継ぐが、
この設定を入れることで上書きすることができる。
PassengerDefaultUser
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerDefaultUser
user switching supportが失敗した またら無効の場合に、このオプションで指定したユーザーでプロセスが動く。
デフォルトはnobody。
PassengerDefaultGroup
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerDefaultGroup
user switching supportが失敗した またら無効の場合に、このオプションで指定したグループでプロセスが動く。
デフォルトはPassengerDefaultUserのグループ。
PassengerFriendlyErrorPages
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerFriendlyErrorPages
Passengerを立ち上げる時にDBの設定が間違っていたりすると立ち上げに失敗してエラーの原因をbacktraceとともに下記のような画面を表示してくれて嬉しいのだが、
プロダクション環境でこのメッセージを表示してしまうとサーバの情報を外部に漏らす可能性がある。この設定をoffにすることで非表示にできる。
Resource control and optimization options
下記動画にあるように、Enterprise版だとより柔軟なリソースコントロールが可能になる。
Phusion Passenger Enterprise: resource control from Phusion on Vimeo.
PassengerMaxPoolSize
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxPoolSize
1つのサーバで立ち上がるWorkerプロセスの最大値を設定する。
マルチスレッドモデルを使わない場合はこの数値がPassengerが同時に処理することができるリクエスト数になる。
サーバのメモリが足りない場合は数値を下げる必要がある。
デフォルトは6。
3に指定した場合、立ち上がるworkerプロセスはサーバ内で最大でも3個までとなる。
$ ps aux | grep "[P]assenger RackApp" u 3778 5.0 6.3 141180 109172 ? Sl 07:20 11:25 Passenger RackApp: /var/www/test-app/current u 27640 3.6 6.3 141560 109604 ? Sl 03:21 16:54 Passenger RackApp: /var/www/test-app/current u 29392 3.9 6.4 142200 111356 ? Sl 04:07 16:38 Passenger RackApp: /var/www/test-app/current
QueueSizeという名前が混乱を招くがworkerプロセスの数を意味する。
設定の目安はPhusionのブログに書いてあり、
http://blog.phusion.nl/2013/03/12/tuning-phusion-passengers-concurrency-settings/
シングルスレッドの場合の計算式:
max_app_processes = (TOTAL_RAM * 0.75) / RAM_PER_PROCESS サーバのメモリが1.7GBで1プロセスのメモリ使用が100MBの場合は: 12.75 = (1700MB * 0.75) / 100MB
マルチスレッドの場合の計算式:
max_app_threads_per_process = ((TOTAL_RAM * 0.75) - (NUMBER_OF_PROCESSES * RAM_PER_PROCESS * 0.9)) / (RAM_PER_PROCESS / 10) NUMBER_OF_PROCESSESはRuby(MRI)の場合CPUの数で考えていいようだ(JRUBYやRubiniusの場合は1で考える)。 Rubyを使っていてサーバのCPUが2でメモリが1.7GBで1プロセスのメモリ使用が100MBの場合は: 109.5 = ((1700MB * 0.75) - (2 * 100MB * 0.9)) / (100MB / 10)
※32bitシステムの場合はmax_app_threads_per_processは200より大きくするべきではない
上記の計算結果を設定してあげればよい。
#シングルスレッドの場合: PassengerMaxPoolSize 12 # マルチスレッドの場合 PassengerMaxPoolSize 2(CPUの数) PassengerThreadCount 109
PassengerMinInstances
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMinInstances
全体または1つのアプリケーションで立ち上げるWorker数の下限をglobalとアプリケーションどちらにでも指定する事が可能。
PassengerMaxInstances(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxInstances
全体または1つのアプリケーションで立ち上げるWorker数の上限をglobalとアプリケーションどちらにでも指定する事が可能。
例えば、websiteとblogをvirtulhostに設定していてwebsiteへのアクセスが多い場合は下記のように設定することでwebsiteの同時実行処理リクエスト数を2にするといったカスタマイズが可能である。
PassengerMaxRequestQueueSize 3 <VirtualHost *:80> PassengerMaxInstances 2 RailsEnv production ServerName www.hakutoitoi.com </VirtualHost> <VirtualHost *:80> PassengerMaxInstances 1 RailsEnv production ServerName blog.hakutoitoi.com </VirtualHost>
プロセスリスト:
$ ps aux | grep "[P]assenger RackApp" u 3778 5.0 6.3 141180 109172 ? Sl 07:20 11:25 Passenger RackApp: /var/www/website/current u 27640 3.6 6.3 141560 109604 ? Sl 03:21 16:54 Passenger RackApp: /var/www/website/current u 29392 3.9 6.4 142200 111356 ? Sl 04:07 16:38 Passenger RackApp: /var/www/blog/current
PassengerMaxInstancesPerApp
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengermaxinstancesperapp_lt_integer_gt
一つのアプリケーションで立ち上げるWorkerプロセスの上限をグローバルで指定する事が可能。
PassengerMaxInstancesのようにアプリケーションごとに柔軟にプロセス数を指定することはできないので全てのアプリケーションの最大プロセス数は同一になる。
PassengerMaxRequestQueueSize 2 PassengerMaxInstancesPerApp 1 <VirtualHost *:80> RailsEnv production ServerName www.hakutoitoi.com </VirtualHost> <VirtualHost *:80> RailsEnv production ServerName blog.hakutoitoi.com </VirtualHost>
プロセスリスト:
$ ps aux | grep "[P]assenger RackApp" u 3778 5.0 6.3 141180 109172 ? Sl 07:20 11:25 Passenger RackApp: /var/www/website/current u 27640 3.6 6.3 141560 109604 ? Sl 03:21 16:54 Passenger RackApp: /var/www/blog/current
PassengerPoolIdleTime
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerPoolIdleTime
1つのwokerが設定した秒数の間idle状態が続いた場合、そのworkerはメモリ節約のためshutdownされる。
デフォルトは300秒。
idle状態がどのくらい続いてるかはpassenger-statusコマンドのLast usedの項目で確認できる。
$ sudo /usr/local/bin/passenger-status | grep -B 1 "Last used" * PID: 27640 Sessions: 0 Processed: 14570 Uptime: 9h 10m 6s CPU: 3% Memory : 103M Last used: 23s ago * PID: 29392 Sessions: 0 Processed: 14477 Uptime: 8h 24m 0s CPU: 4% Memory : 104M Last used: 4m 40s ago
この例だとPID29392のworkerがidle状態のまま4分40秒経っているためもうすぐshutdownされる。
PassengerMaxPreloaderIdleTime
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxPreloaderIdleTime
workerを生成・破棄するSpawnerプロセスがshutdownするまでのidle時間の設定。
デフォルトは300秒で、その間workerプロセスに変動がなければshutdownされる。
PassengerStartTimeout
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerstarttimeout_lt_seconds_gt
workerプロセスの開始に設定した秒数以上かかったら失敗する。
デフォルト90秒。
PassengerConcurrencyModel(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerConcurrencyModel
マルチスレッドモデルを有効にできる。
PassengerThreadCount(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerThreadCount
マルチスレッドが有効な時に一つのプロセスがいくつのスレッドを使えるようにするか設定する。
デフォルトは1。
PassengerMaxRequests
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxRequests
ここに設定したリクエスト数を処理するとwokerプロセスが再起動する。
アプリケーションがメモリリークを起こしている場合には必要な設定だろう。
デフォルトは0で無効になっている。
PassengerMaxRequestTime(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxRequestTime
リクエストの処理時間が設定値を超えたらworkerを再起動する。
デフォルトは0で無効になっている。
リクエストの処理に時間がかかりすぎてアプリケーション全体がつまって止まってしまう危険性を減らす事ができる。
下記の設定をすると/expensive_computationへのリクエストだけtimeoutまでの時間を伸ばせるといった柔軟な設定を行える。
<VirtualHost *:80> ServerName www.example.com DocumentRoot /webapps/my_app/public PassengerMaxRequestTime 2 <Location /expensive_computation> PassengerMaxRequestTime 10 </Location> </VirtualHost>
この設定が必要になる時は大体アプリケーションが遅いことに問題があるので、問題を特定して迅速に修正すべきだろう。
PassengerMemoryLimit(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMemoryLimit
ここに指定したメモリ数を超えるメモリをwokerプロセスが使うと再起動する。
アプリケーションがメモリリークを起こしている場合には必要な設定だろう。
デフォルトは0で無効になっている。
PassengerStatThrottleRate
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerstatthrottlerate_lt_integer_gt
設定ファイル(config/envrironment.rb)や再起動ファイル(restart.txt)をチェックするタイミングを指定できる。
0の場合は各リクエストを処理するタイミングで行う。
秒数を指定した場合はその秒数毎にチェックする。
PassengerPreStart
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerPreStart
デフォルトではPassengerは最初にリクエストがあるまでプロセスをstartさせない。この設定を入れることでapacheを起動した時に指定したURLだけはアクセスがなくてもアプリケーションを事前にstartしてくれる。
PassengerHighPerformance
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerHighPerformance
onに設定すると少し高速化されるがmod_rewriteやmod_autoindexなどのモジュールが使えなくなる。
Connection handling options
PassengerBufferUpload
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerBufferUpload
onの場合、POSTでアップロードされたデータはアプリケーションに送られる前にバッファされる。遅いクライアントからのアップロードを守るが、アップロード進捗を追跡する機能は使えなくなる。
デフォルトはon。
PassengerBufferResponse
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerBufferResponse
onの場合、apacheにレスポンスをバッファさせる。
apache版のPassengerの場合、2つのレスポンスバッファリングシステムが有効である。
- Apache response buffering system(PassengerBufferResponseでon/offできる)
- Phusion Passenger response buffering system(この設定はPassengerBufferResponseがoffでも常に有効である)
基本的にはPassengerのほうがバッファしてくれるので遅いクライアントからの攻撃があってもoffで問題はない。
もし何がしかの理由でapacheレベルのバッファリングをしたい場合は、このオプションをonにすることで有効にすることができる。
注意して欲しいのはこのオプションをonにした場合はストリーミングレスポンスを作るのが不可能になること。
下記のコードは1秒毎にレスポンスを返すコードだがPassengerBuggerResponseをonにした場合は10秒後に全体のレスポンスを返す挙動になってしまう、offの場合なら期待通りに動く。
render :text => lambda { |response, output| 10.times do |i| output.write("entry #{i}\n") output.flush sleep 1 end }
※大きいサイズのレスポンスを返す場合はこの設定はoffにすべきだろう、なぜならレスポンスはメモリにバッファされるのでメモリ使用量が極端に大きくなってしまう。
PassengerErrorOverride
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerErrorOverride
400番以上のエラーページをPassengerデフォルトのものから自分の好きなページに変更できる。
PassengerMaxRequestQueueSize
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxRequestQueueSize
全てのwokerがリクエスト処理中の状態で新規のリクエストがくるとリクエストキューに格納されてidleになったwokerが順次このキューにたまったリクエストを処理するのだがこのキューの最大サイズをアプリケーション毎に設定できる。
デフォルトは100で、100を超えたらキューにはためずにクライアントに503エラーを返すようになる。
この動作は非常に重要でアプリケーションになんかしらの問題が起きている事を把握できる。例えば:
- PVがいきなり増加した
- フルテーブルスキャンやフルインデックススキャン等の非常に時間のかかる処理を行うようになった
- 巨大なテーブルにインデックスの追加を行ったため、テーブルにWRITEロックがかかり全てのwokerが更新処理中でロック解除待ちになっている
などなど。
キューにたまっているリクエスト数はpassenger-statusコマンドで知ることができる。
$ sudo /usr/local/bin/passenger-status | grep "Requests in queue" Requests in queue: 0
この例ではキューはたまってないことを意味する。
また下記設定を追加することで503エラーページをカスタマイズすることが可能である。
PassengerErrorOverride on ErrorDocument 504 /error504.html
Compatibility options
PassengerResolveSymlinksInDocumentRoot
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerResolveSymlinksInDocumentRoot
Passenger-2.2以降の場合、DocumentRootがシンボリックリンクだった場合にconfig/environment.rbを探せないが、
この設定をonにすることで2.2以前の動作になるので探せるようになる。
新しいアプリケーションに関してはDocumentRootはシンボリックにしないほうがいいだろう。
PassengerAllowEncodedSlashes
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt
スラッシュがURLencodeされたリクエストを処理できるようにする。
Logging and debugging options
PassengerLogLevel
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerLogLevel
ログレベルを指定する。
- 0: errorとwarningのみ
- 1: important debugも表示
- 2: debugをもっと表示
- 3: さらにdebugを表示
PassengerDebugLogFile
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerdebuglogfile_lt_filename_gt
デバッグとエラーログを出力するファイルを変更できる。
デフォルトではapacheのグローバルなerrorlogになっている。
PassengerDebugger(enterprise限定)
http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerdebugger_lt_on_off_gt
Passengerでデバッガを使うことができる。
Rails開発の場合、ローカルのmacでwebrickを立ち上げて行う事が多い。その時にデバッグするのと同じようにPassengerを使っている場合でもデバッグできるようになる。
デフォルトはoff。
Phusion Passenger Enterprise: live IRB and debugging console from Phusion on Vimeo.
Advanced options
PassengerTempDir
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerTempDir
Passengerが使うtmpファイルを置くディレクトリを指定できる。
デフォルトは/tmp。
この値を変更している場合は、passenger-status等のコマンドを使う場合に環境変数でディレクトリを指定しなければならない。
export PASSENGER_TMPDIR=/my_temp-dir sudo -E passenger-status # The -E option tells 'sudo' to preserve environment variables.
PassengerUploadBufferDir
http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerUploadBufferDir
大きいファイルをPOSTされた場合に、Passengerはデータをファイルにバッファする。
そのディレクトリを指定する。
デフォルトはシステムのtmpディレクトリのサブディレクトリになる(PassengerTempDirを指定している場合はそのサブディレクトリ)。
Deprecated or removed options
Deprecatedなので割愛する。