Почему этот код Ruby, пытающийся вызвать HTTP API, приостанавливает процесс?

#ruby-on-rails #ruby #http

Вопрос:

Я пытаюсь вызвать api (из контроллера), сохранить полученный ответ JSON в переменной, а затем получить доступ к частям значения переменной по желанию (на мой взгляд). Следующий код зависает:

в контроллере:

 parsed_response = JSON.parse(HTTP.get('http://localhost:3000/api/v2/storefront/products')) @products = parsed_response['data']  

в поле зрения:

 lt;%= @products %gt;  

Вышесказанное ничего не отображает, зависает процесс, и мне приходится kill -9 выключать сервер. Что я здесь делаю не так, это каким-то образом делает HTTP.get запрос более одного раза подряд, что приводит к зависанию процесса? Связано ли это с тем, что #parse и #get вызываются одновременно в одной строке?

(Я использую здесь gem ‘http’)

Комментарии:

1. Если я загружу этот URL-адрес в свой браузер, он отлично отобразит ответный пакет JSON.

2. Что такое ваш веб-сервер? Пума?

3. Да, мой веб-сервер-Puma (я запускаю его в режиме разработки на своем локальном компьютере).

4. Тогда я предполагаю, что это Rack::Lock «виновато». Попробуйте установить config.allow_concurrency=true в среде разработки (или config.threadsafe! ) — это может помочь. Но, честно говоря, я бы пересмотрел решение — http-запросы к собственным конечным точкам-невероятная трата ресурсов…

Ответ №1:

Я предполагаю, что ваш сервер (puma, unicorn,..) принимает ограниченное количество параллельных HTTP-соединений.

Предположим, что ваше приложение принимает только одно соединение за раз:

  • Ваш запрос localhost:3000/page_1 , поэтому вы занимаете эту связь. Никто не сможет подключиться к вашему серверу, пока это соединение не закончится.
  • localhost:3000/page_1 хочет подключиться localhost:3000/page_2 , он должен подождать, пока активное соединение не закончится. Поскольку он не может подключиться, он ждет… до истечения тайм-аута или до тех пор, пока вы не убьете свой сервер.

Комментарии:

1. Я думаю, что это должно быть как-то связано с моим кодом, с тех пор я обнаружил, что это работает; response = (HTTP.get('http://localhost:3000/api/v2/storefront/products')) parsed_response = JSON.parse(response) @products = parsed_response['data'] И поскольку это работает как с рендерингом браузера @products, так и с вызовом API, который происходит непосредственно перед этим с контроллера, это определяет, что мой сервер может принимать параллельные http-соединения, не так ли? Возможно, это метод цепочки в 1-й исходной строке? Но если так, то почему?