Scaling Rails Needs A Lot Of Nginx Instances - ruby-on-rails

We have built a rails app and are trying to support around 6k concurrent users making on average 6 request each per minute, with an average rails web transaction response time of 700 ms.
We did the maths, and it works out that we would need around 420 nginx/passenger instances running (we are not running in multithreaded mode due to legacy codebase that may not be threadsafe). This seems like an awful lot of nginx instances needed to support this kind of load.
We are running 20 nginx/passenger instances per server at the moment, so we need about 20 servers to get to the 420 instances of nginx/passenger required to serve that traffic.
Here is the math:
6k Users X 6 RPM Per User = 36k Total RPM
36k X .7 Seconds (AVG response time) = 25200 seconds of processing
25200/60 = 420 instances (Divide by 60 to fit all that processing into 1 min)
Does anybody have any experience around this that could help us out?
Is this just how it has to be with the amount of servers we must run?
thanks

Related

how to determine no of requests in production

we are running rails app in production (single master node) with nginx as web and puma as rack server and wanted to calculate no of request our server can handle. I know there are tools available like ApacheBench which works like
ab -k -c 350 -n 20000 example.com
It takes few parameters like in above command 350 simultaneous connections until 20 thousand requests. This approach can give req per seconds count for a single URL. But, I am interested in determining request per seconds for dynamic system which serves dynamic content.
Is there any built-in tool which can give me request per second count.
Way Around (Manual Calculations)
I have installed an Analytics tool rorvswild it is very similar to NewRelic. It gives me response time of every route I have in ruby on rails application. It also gave average response time of all the routes, which is 250ms If average response time of system is T can I calculate no of request system can handle will be 1000/T?
Also I am running puma behind NGINX, which is multithreaded and running 5 threads so eventually
no of requests per second = thread_count * (1000/T)
In my case thread_count = 5
Thank You so much for reading, you suggestions will be very helpful.

Advice on number of dynos

I'm new to Heroku, and would like to have some idea of how I can go about guesstimating the number of dynos that might be needed for a RoR app (need to give some number to customer).
The app is already running on the free 1 dyno. Here's some basic info about the app:
App is mainly database reads, with very little writes
Possibly heavy DB load, with queries involving distance calculations (from lat-long, using gmaps4rails)
From some basic testing with WAPT (eval version), it looks like a typical search request takes a min. ~1.3s, avg. ~2s, max. 4-5s
Again from WAPT testing, up to 20 concurrent users and observing the Heroku logs, I don't seem to be seeing any requests being queued
Other requests are largely static assets
How would I get some rough idea of the number of dynos needed, to handle X concurrent users, or how many concurrent users the single dyno can likely handle?
Update: Heroku changed their dyno pricing prolicy https://www.heroku.com/pricing, so the these information might not correct anymore.
According to this article http://neilmiddleton-eu.herokuapp.com/getting-more-from-your-heroku-dynos/, if you use Unicorn, 1 dyno can handle 1 million request per day (100ms per request). So if you host all media in S3, 1 page view need 3 requests (1 html, 1 pipe-lined css, 1 pipe-lined javascript), 1 dyno can handle roughly 300.000 page view a day, or 80 page view per seconds with Unicorn.
Let's say 1 user will view 1 page in 5 seconds, and your application can manage to respond in 300ms, technically, you will have roughly 400 concurrent users with 1 dyno.
But actually our application (quite heavy), 1 dyno can only accept 1/10 of those, around 50 concurrent users.
Hope this help you!

Apache+Passenger Optimization Questions?

I am working to optimize the speed of a Rails application we have in production.
It is built on an Apache,Passenger,Rails 2.35, Ubuntu on an m1.large EC2 instance (7.5GB RAM, 4 Compute Units) We will be switching to nginx in the near term, but have some dependancies on Apache right now.
I'm running load tests against it with ab and httperf.
We are seeing consistently 45 request/sec varying between 30 - 200 concurrent users for a simple API request to get a single record from a database table with 100k records indexed. It seems very slow to me.
We are focusing on both application code optimization as well as server configuration optimization.
I am currently focused on server configuration optimization. Here's what I've done so far:
Passenger adjusted PassengerMaxPoolSize to (90% Total Memory) / (Memory per passenger process, 230mb) Apache
adjusted MaxClients to 256 max.
I did both independently and together I saw no impact to the
req/sec.
Another note is that this seems to scale linearly by adding servers. So doesn't seem to be a database issue. 2 servers 90 req/sec, 3 servers was around 120 request/sec... etc
Any tips? It just seems like we should be getting better performance by adding more processes?

Is 100 or less requests per second (for non-cached pages) what one can expect with Rails?

Preface: Please don't start a discussion on premature optimization, or anything related. I'm just trying to understand what kind of performance I can get from a single server with rails.
I have been benchmarking ruby on rails 3 and it seems the highest rate of requests per second I can get is around 100 requests per second.
I used phusion passenger with nginx, and Ruby 1.8.7.
This is on a ec2 m1.large instance:
7.5 GB memory
4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute Units each)
850 GB instance storage
64-bit platform
I/O Performance: High
API name: m1.large
The page was a very simple action that wrote a single row into mysql.
user = User.new
user.name = "test"
user.save
I am assuming no caching (memcache, etc), I just want to get a feel for the raw numbers.
I used apache bench on the same ec2 instance, and I used varying levels of # of requests (from 1000 to 10000 and varying numbers of concurrent requests 1/5/10/25/50/100).
The EC2 m1.large instance is really not that fast, so these numbers aren't surprising. If you want performance, you can either spring for a larger instance, as there are now some with 80 ECUs, or try a different provider.
I've found that Linode generally offers higher performance for the same price, but is not as flexible and doesn't scale to very large numbers of servers as well. It's a much better fit if you're in the "under 20 servers" phase of rolling out.
Also don't think that MySQL is a no-cost operation.

High traffic rails perf tuning

I was attempting to evaluate various Rails server solutions. First on my list was an nginx + passenger system. I spun up an EC2 instance with 8 gigs of RAM and 2 processors, installed nginx and passenger, and added this to the nginx.conf file:
passenger_max_pool_size 30;
passenger_pool_idle_time 0;
rails_framework_spawner_idle_time 0;
rails_app_spawner_idle_time 0;
rails_spawn_method smart;
I added a little "awesome" controller to rails that would just render :text => (2+2).to_s
Then I spun up a little box and ran this to test it:
ab -n 5000 -c 5 'http://server/awesome'
And the CPU while this was running on the box looked pretty much like this:
05:29:12 PM CPU %user %nice %system %iowait %steal %idle
05:29:36 PM all 62.39 0.00 10.79 0.04 21.28 5.50
And I'm noticing that it takes only 7-10 simultaneous requests to bring the CPU to <1% idle, and of course this begins to seriously drag down response times.
So I'm wondering, is a lot of CPU load just the cost of doing business with Rails? Can it only serve a half dozen or so super-cheap requests simultaneously, even with a giant pile of RAM and a couple of cores? Are there any great perf suggestions to get me serving 15-30 simultaneous requests?
Update: tried the same thing on one of the "super mega lots and lots of CPUs" EC2 thing. Holy crap was that a lot of CPU power. The sweet spot seemed to be about 2 simultaneous requests per CPU, was able to get it up to about 630 requests/second at 16 simultaneous requests. Don't know if that's actually cost efficient over a lot of little boxes, though.
I must say that my Rails app got a massive boost to supporting about 80 concurrent users from about 20 initially supported after adding some memcached servers (4 mediums at EC2). I run a high traffic sports site that really hit it a few months ago. Database size is about 6 gigs with heavy updates/inserts.
MySQL (RDS large high usage) cache also helped a bit.
I've tried playing with the passenger settings but got some curious results - like for example each thread eats up 250 megs of RAM which is odd considering the application isn't that big.
You can also save massive $ by using spot instances but don't rely entirely on that - their pricing seems to spike on occasion. I'd AutoScale with two policies - one with spot instances and another with on demand (read: reserved) instances.

Resources