Доброго времени суток.
Имеется задача: Опрашивать внешний API, который отдает определенный набор данных на глубину 180+ дней от текущей даты. POST-запрос отправляется в формате XML, в нем задаются 3 параметра "ИЗ ГОРОДА", "В ГОРОД", "ДАТА".
API поддерживает обработку нескольких направлений ( до 40 ) на одну дату.
API поддерживает множественные подключения ( до 10 одновременных ) и множественные запросы ( до 100 / сек )
Так как направлений много - примерно 75_000, то кол-во запросов = 13_500_000 если опрашивать каждое на каждый день на глубину 180 дней от текущей даты.
Для экономии времени на опросах направлений решено использовать http persistent connection чтобы сократить время на переоткрытие соединенния для каждого запроса + запрашивать разом 40 направлений. А так же разогнать это при помощи threads/forks.
В качестве http-клиента используется gem 'net-http-persistent', '4.0.0'
Вопрос - как это правильно сделать? Опрос при помощи Python-скрипта показывает в разы лучшую производительность
На ruby делается так:
dates = ['2020-11-10', '2020-11-11', '2020-11-12', .... ]
directions.each_slice(7500) do |slice|
fork do
fork_counter = 10
Signal.trap("CLD") { fork_counter += 1 }
#
uri = URI("https://api.url/")
http = Net::HTTP::Persistent.new(name: "slice_#{rand(1..10000)}")
#
http.max_requests = 100000000
http.keep_alive = 600
http.read_timeout = 5
http.reuse_ssl_sessions = true
#
post = Net::HTTP::Post.new(uri)
#
slice.each_slice(40) do |directions_to_ask|
Process.wait if fork_counter <= 0
fork_counter -= 1
headers = { 'Content-Type' => 'text/xml', 'Accept-Encoding' => 'gzip', 'Connection' => 'Keep-Alive' }
headers.map{ |k,v| post.add_field(k,v) }
segments = directions_to_ask.map{ |x|
"<OriginDestination date='#{date}' origin='#{x[0]}' destination='#{x[1]}'></OriginDestination>"
}
data = <<-SOAP
<SOAP-ENV:Envelope>
.....
.....
<SOAP-ENV:Body><SchedulesAvailability">#{segments.join("\n")}</SchedulesAvailability></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP
post.body = data
response = http.request(uri, post)
end
http.shutdown
end
end
Process.waitall
Что можно исправить/ускорить?
Возможно есть ошибка. Заранее спасибо за ответ.