Асинхронный ввод-вывод (I/O) позволяет выполнять операции чтения/записи без блокировки основного потока выполнения. Рассмотрим подходы к асинхронному I/O в Ruby.
require 'socket'
server = TCPServer.new(1234)
sockets = [server]
loop do
# Ожидание готовности сокетов (таймаут 1 сек)
ready = IO.select(sockets, nil, nil, 1)
if ready
ready[0].each do |socket|
if socket == server
# Новое подключение
client = server.accept
sockets << client
else
# Чтение данных
data = socket.read_nonblock(1024, exception: false)
if data == :wait_readable
next
elsif data.nil?
# Соединение закрыто
sockets.delete(socket)
socket.close
else
# Обработка данных
process_data(data)
end
end
end
end
end
require 'eventmachine'
EM.run do
EM.start_server("0.0.0.0", 8080) do |conn|
def conn.receive_data(data)
send_data("Echo: #{data}")
end
end
end
require 'async'
Async do |task|
server = Async::IO::TCPServer.new('0.0.0.0', 8080)
while (client = server.accept)
task.async do |subtask|
while (data = client.read(1024))
client.write("Echo: #{data}")
end
end
end
end
EventMachine:
Celluloid::IO:
Async (Ruby 3+):
nio4r:
Подход | Плюсы | Минусы |
---|---|---|
IO.select | Встроен в Ruby, прост | Масштабируемость ограничена |
EventMachine | Богатая экосистема | Устаревающая архитектура |
Fibers (Async) | Легковесные, современные | Требует Ruby 3+ |
Threads | Простота программирования | GIL ограничивает в MRI |
require 'async/http/internet'
Async do
internet = Async::HTTP::Internet.new
responses = [
internet.get("https://example.com"),
internet.get("https://ruby-lang.org")
]
responses.each do |response|
puts "Got #{response.status}"
end
ensure
internet.close
end
IO Multiplexing:
Buffer Management:
Connection Pooling:
GIL в MRI:
Состояние гонки:
Сложность отладки:
Асинхронный I/O в Ruby эволюционировал:
Ключевые моменты:
Рекомендации: