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 executeiab -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_http
emapp/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_http
app/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