Solicitações de aplicativos 1600% mais rápidas com Rails no Heroku

Usando arco-íris! e em-http-request resultou em um aumento de desempenho de 1600% em comparação ao uso de unicórnio e net_http.
(Para o caso de uso descrito abaixo)

Situação

  • Você tem um aplicativo que faz muitas chamadas para uma API de terceiros. Isso costuma acontecer com aplicativos do Facebook, por exemplo.
  • Você deseja hospedá-lo no heroku (preferencialmente um dinamômetro, então é grátis)

Problema

  • Você deseja chamar a API de terceiros de seu controlador e renderizar a resposta
  • Mesmo se você estiver usando o unicórnio para bifurcar vários processos de trabalho, eles serão bloqueados e aguardarão uma resposta do Facebook (ou qualquer outra API potencialmente lenta) na maioria das vezes.

Solução: Use EventMachine e Rainbows!

Aqui está um esboço rápido de como começar a usar o Rainbows! e em-http-requisições no heroku.

Estaremos usando as seguintes joias:
Gemfile

gem 'rainbows'
gem
'em-http-request'
gem
"faraday"

app/controllers/async_controller.rb

class AsyncController < ApplicationController
def index
conn
= Faraday.new "http://slowapi.com" do |con|
con
.adapter :em_http
end
resp
= conn.get '/delay/1'
resp
.on_complete {
@res = resp.body
render

request
.env['async.callback'].call(response)
}
throw :async
end

app/views/async/index.html.erb

<%= @res %>

config/rainbows.rb

worker_processes 3
timeout
30
preload_app
true

Rainbows! do
use :EventMachine
end

before_fork
do |server, worker|
# Replace with MongoDB or whatever
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
end

after_fork
do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
end

config/routes.rb

match 'async_test' =>   'async#index'

Procfile

web: bundle exec rainbows -p $PORT -c ./config/rainbows.rb

também é uma boa idéia definir config.threadsafe!na configuração do seu ambiente Rails

Finalizar

  • Implantar no heroku
  • Execute um benchmark, por exemplo, o seguinte

    ab -n 600 -c 200 http://mycoolasync.herokuapp.com/async_test

  • Aproveite o quão rápido é

Alguns resultados

Eu configurei um aplicativo de teste no heroku e executei
ab -n 600 -c 200 http://mycoolasync.herokuapp.com/async_test

Resultado:

  • Método da velha escola: 183 segundos
  • Método com eventos: 11 segundos

Resultados detalhados para solicitações síncronas tradicionais

Usando não-evented http pedido settting con.adapter :net_httpemapp/controllers/async_controller.rb

Document Path:          /async_test
Document Length: 2755 bytes

Concurrency Level: 100
Time taken for tests: 183.373 seconds
Complete requests: 600
Write errors: 0
Non-2xx responses: 516
Total transferred: 652495 bytes
HTML transferred
: 541903 bytes
Requests per second: 3.27 [#/sec] (mean)
Time per request: 30562.206 [ms] (mean)
Time per request: 305.622 [ms] (mean, across all concurrent requests)
Transfer rate: 3.47 [Kbytes/sec] received

Connection Times (ms)
min mean
[+/-sd] median max
Connect: 101 175 260.7 109 1239
Processing: 1270 28308 5571.9 30115 30978
Waiting: 1146 28156 5882.4 30115 30665
Total: 1376 28484 5582.8 30224 32203

Resultados detalhados para o método de solicitação de eventos novo e sofisticado

Garantido pela instalação emcon.adapter :em_httpapp/controllers/async_controller.rb

Document Path:          /async_test
Document Length: 2758 bytes

Concurrency Level: 100
Time taken for tests: 11.118 seconds
Complete requests: 600
Write errors: 0
Total transferred: 1734330 bytes
HTML transferred
: 1655686 bytes
Requests per second: 53.97 [#/sec] (mean)
Time per request: 1853.048 [ms] (mean)
Time per request: 18.530 [ms] (mean, across all concurrent requests)
Transfer rate: 152.33 [Kbytes/sec] received

Connection Times (ms)
min mean
[+/-sd] median max
Connect: 101 194 283.0 114 1263
Processing: 1136 1485 416.1 1341 3558
Waiting: 1135 1453 346.2 1339 3159
Total: 1250 1679 472.5 1505 3669

Algumas palavras finais

Eu queria ter um título de link-baity uma vez. Então, aqui estamos com 1600% não científicos. Você será o juiz – acho que com a configuração de teste correta, esse número pode ser muito maior. Se você replicou e obteve um resultado melhor, me avise. Vou atualizar esta postagem e dar o crédito a você.

Saúde,
seu amigo
dommmel