I am in the middle of upgrading an old Rails and PostgreSQL app from 2.1 to Rails 3 (via a successful intermediate 2.3.11 step).
Finally, when I got all the Rspecs running smoothly, I installed Mongrel 1.2.0.pre2 and got it up and running - all OK. Even the JMeter test case with 100 concurrent users passed OK.
But when I tried the same with Unicorn! server, it works fine when I am using it myself, but when I get it under load with JMeter, it starts giving 100% errors from the moment, where JMeter tries to POST a login. At the same time when I check some specific page, it gives me weird errors like this:
undefined method `eq' for nil:NilClass
At the terminal I get the following output (but only a few times):
message type 0x43 arrived from server while idle
message type 0x5a arrived from server while idle
WARNING: there is already a transaction in progress
EDIT: this seems to be an issue with shared PGconnect
object, so I removed some of previous text
I found that PostgreSQL docs specify that PGconn
object must not be shared between threads making concurrent requests.
Is Unicorn! or AR mixing requests from different threads in the same PGconn
object?
Database.yml:
production:
adapter: postgresql
encoding: unicode
database: ***
username: ***
password: ***
host: 127.0.0.1
I even tried to add this to no avail:
allow_concurrency: true
unicorn.conf:
worker_processes 8
working_directory "/full/path/to/app"
listen '/tmp/app.sock', :backlog => 512
timeout 30
pid "/full/path/to/app/tmp/pids/puppetmaster_unicorn.pid"
preload_app true
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end
Specs:
If Rails version should be the culprit, of course I can upgrade to the latest. I just started off with what the service provider has.
It's critical not to share database connections between processes. When you run Rails with preload_app Rails will establish the AR connection(s) before the unicorn master forks the workers. The example unicorn.conf.rb has a recommendation to disconnect the AR connection in the before_fork hook. AR will automatically reestablish a fresh connection as each worker requires it post-fork.
excerpt from http://unicorn.bogomips.org/examples/unicorn.conf.rb:
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
# ...
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With