Решение
Я переключаюсь на единорога в режиме разработки. Для предотвращения тупиковой ситуации необходим один рабочий процесс для каждого уровня рекурсии, поэтому я использую 2 рабочих процесса.
Проблема
Я работаю над сервером Thin в своей среде разработки. Я использую порт 3000 (по умолчанию в среде разработки). Моя проблема заключается в том, чтобы заставить сервер делать запросы самому себе.
Допустим, у меня есть следующий контроллер:
# app/controllers/recursions_controller.rb
class RecursionsController < ApplicationController
# /recursions
def index
# synchronously call recursions#show
RestClient.get("http://localhost:3000/recursions/1")
# finish!
render :text => 'index'
end
# /recursions/:id
def show
# finish immediately
render :text => 'show'
end
end
Вот соответствующий маршрут:
# config/routes.rb
resources :recursions
Вот вывод из журнала запросов, когда я первоначально запрашиваю recursions#index
:
[INFO] 2013-01-15 12:09:05 -0800 Started GET "/recursions" for 127.0.0.1 at 2013-01-15 12:09:05 -0800
Processing by RecursionsController#index as HTML
Completed 500 Internal Server Error in 60049ms
[FATAL] 2013-01-15 12:10:05 -0800 RestClient::RequestTimeout (Request Timeout):
app/controllers/recursions_controller.rb:8:in `index'
Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.8ms)
Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.7ms)
Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (7.4ms)
[INFO] 2013-01-15 12:10:05 -0800
[INFO] 2013-01-15 12:10:05 -0800
[INFO] 2013-01-15 12:10:05 -0800 Started GET "/recursions/1" for 127.0.0.1 at 2013-01-15 12:10:05 -0800
Processing by RecursionsController#show as XML
Parameters: {"id"=>"1"}
Rendered text template (0.0ms)
Completed 200 OK in 7ms (Views: 5.5ms)
Я подозреваю, что здесь происходит какая-то тупиковая ситуация. Запрос A не может вернуться, пока не вернется запрос B (рекурсивный порядок, ничего не поделаешь), но запрос B не может быть обработан до тех пор, пока не вернется запрос A (очевидное ограничение, встроенное в мой веб-сервер?). Тупик разрешается, когда истекает время ожидания RestClient, вызывая исключение и завершая запрос A с кодом 500. Только тогда обрабатывается запрос B, хотя на данный момент это спорный вопрос.
Мне кажется, что мой веб-сервер не может обрабатывать одновременные запросы. Тем не менее, вот мои вопросы:
Есть ли веб-сервер, на который я могу переключиться в своей среде разработки, который не ограничен таким образом? Мы используем Unicorn в производстве, который может создавать несколько рабочих процессов и, следовательно, обрабатывать параллельные запросы, но Unicorn кажется слишком тяжелым для среды разработки. То же самое, что делает Unicorn решением моей проблемы, может затруднить чтение вывода журнала. Это мое последнее средство.
Есть ли сложный способ сделать запрос к платформам Rails/Rack, чтобы обойти очевидное ограничение параллельных запросов?
Может ли кто-нибудь предоставить мне документы, в которых явно указывается это ограничение? Я не знаю, является ли это ограничением, присущим всем однопроцессным веб-серверам Ruby on Rails или только Thin.
Примечание. Это просто игрушечная задача, демонстрирующая мою проблему с блокировкой. Если вам нужно знать реальную причину этого, я переношу некоторые HTTP-сервисы из другой части нашей инфраструктуры в наше приложение RoR. Наше приложение RoR использует эти службы во многих разных точках нашего кода, поэтому я пытаюсь оставить клиентский код для этих служб нетронутым и изменить только реализацию. Это означает выполнение циклических HTTP-запросов. Это будет оптимизировано позже, когда все стабилизируется.