Tôi đang chơi xung quanh với đồng thời trong Ruby (1.9.3-p0) và đã tạo một tác vụ proxy I/O-heavy rất đơn giản. Trước tiên, tôi đã thử cách tiếp cận không chặn:Đồng thời Ruby: không chặn I/O và chủ đề
require 'rack'
require 'rack/fiber_pool'
require 'em-http'
require 'em-synchrony'
require 'em-synchrony/em-http'
proxy = lambda {|*|
result = EM::Synchrony.sync EventMachine::HttpRequest.new('http://google.com').get
[200, {}, [result.response]]
}
use Rack::FiberPool, :size => 1000
run proxy
=begin
$ thin -p 3000 -e production -R rack-synchrony.ru start
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 5.602 seconds
HTML transferred: 21900 bytes
Requests per second: 17.85 [#/sec] (mean)
Time per request: 5602.174 [ms] (mean)
=end
Hmm, tôi nghĩ mình phải làm điều gì đó sai. Thời gian yêu cầu trung bình là 5.6 cho một nhiệm vụ mà chúng tôi chủ yếu chờ I/O? Tôi đã thử một số khác:
require 'sinatra'
require 'sinatra/synchrony'
require 'em-synchrony/em-http'
get '/' do
EM::HttpRequest.new("http://google.com").get.response
end
=begin
$ ruby sinatra-synchrony.rb -p 3000 -e production
== Sinatra/1.3.1 has taken the stage on 3000 for production with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 5.476 seconds
HTML transferred: 21900 bytes
Requests per second: 18.26 [#/sec] (mean)
Time per request: 5475.756 [ms] (mean)
=end
Hmm, tốt hơn một chút, nhưng không phải là điều tôi gọi là thành công. Cuối cùng, tôi đã thử triển khai luồng:
require 'rack'
require 'excon'
proxy = lambda {|*|
result = Excon.get('http://google.com')
[200, {}, [result.body]]
}
run proxy
=begin
$ thin -p 3000 -e production -R rack-threaded.ru --threaded --no-epoll start
>> Thin web server (v1.3.1 codename Triple Espresso)
$ ab -c100 -n100 http://localhost:3000/
Concurrency Level: 100
Time taken for tests: 2.014 seconds
HTML transferred: 21900 bytes
Requests per second: 49.65 [#/sec] (mean)
Time per request: 2014.005 [ms] (mean)
=end
Điều đó thực sự thực sự đáng ngạc nhiên. Am i thiếu cái gì ở đây? Tại sao EM biểu diễn quá tệ ở đây? Có một số điều chỉnh tôi cần phải làm không? Tôi đã thử kết hợp khác nhau (Unicorn, một số cấu hình Rainbows, vv), nhưng không ai trong số họ đến thậm chí gần với đơn giản, cũ I/O-chặn luồng.
Ý tưởng, nhận xét và - rõ ràng - đề xuất triển khai tốt hơn rất được hoan nghênh.
Bạn không nên sử dụng máy chủ ở xa để kiểm tra, độ trễ có thể thay đổi. Bạn nên thử lại thử nghiệm async với ít sợi hơn, với 20 sợi tôi nhận được 300ms/yêu cầu so với 1s/yêu cầu với 1000 sợi bằng cách sử dụng đường ab chính xác của bạn. Máy chủ luồng của bạn đang sử dụng nhóm chủ đề eventmachine mặc định là 20 luồng theo mặc định. – Schmurfy
Không chắc chắn, thiết lập kích thước hồ bơi sợi đến 20 thực sự làm giảm hiệu suất trên hộp của tôi. – BSM
Có thể không phải 20 nhưng 1000 thực sự cao, tôi đã thử nghiệm với máy chủ cục bộ để thời gian phản hồi thực sự thấp. – Schmurfy