Будет ли этот код на Ruby использовать неблокирующий ввод / вывод под Puma? - PullRequest
0 голосов
/ 25 июня 2018

Я исследую некоторые узкие места в устаревшем приложении Rails.Помимо прочего, он отправляет некоторые HTTP-запросы (на брандмауэрах) на внутренние серверы и передает ответ клиенту, используя объекты следующего класса в качестве тела ответа контроллера:

class Streamer
  def initialize(url)
    @url = url
  end

  def each 
    client = HTTPClient.new
    client.receive_timeout = 7200
    client.send_timeout = 3600
    client.connect_timeout = 7200
    client.keep_alive_timeout = 3600

    client.get_content(@url) { |chunk|
      yield chunk
    }

  end
end

Я являюсьновичок в том, что касается Ruby I / O и многопоточности, и я тоже не настолько опытен в Rails.Предполагается, что это предположение заключается в том, что он (работающий на MRI) блокирует интерпретатор только один раз для каждого фрагмента, и что другие потоки могут выполняться, когда данные поступают из HTTPClient или выходят в браузер -это предположение верно?Или этот код истощит другие темы Puma?

1 Ответ

0 голосов
/ 03 июля 2018

Ответы да и нет, главным образом потому, что терминология в вопросе несколько неясна.

Блокировка ввода-вывода означает, что ввод-вывод ожидает данные.HTTPClient использует блокировку ввода-вывода.Он ожидает поступления данных и возвращается только после получения данных.

Неблокирующий ввод-вывод означает, что уровень ввода-вывода возвращается немедленно, даже если данные отсутствуют (часто с ошибкой EAGAIN или EWOULDBLOCK).

Модуль HTTPClient блокирует поток управления, ожидая ответа HTTP-сервера.

Однако это не мешает другим потокам работать "параллельно" (или, в случаеRuby MRI, чередование).

Предполагается, что при проектировании (работающем на MRI) блокировка интерпретатора будет выполняться только один раз для фрагмента, а другие потоки могут выполняться, пока данные либовходящий из HTTPClient или выходящий из браузера - это предположение верно?

В общем, предположение является правильным (или достаточно близким, чтобы оно не имело значения).

GIL (глобальная блокировка интерпретатора) в Ruby MRI обеспечивает выполнение одного потока для кода Ruby.Он предотвращает истинный параллелизм и напоминает многопотоковую модель, используемую одноядерными процессорами.

Однако, поскольку код IO выполняется вне GIL, другие потоки будут работать, пока IO ожидает входящегоданные (блокировка write, read или select).

В общем случае Ruby будет управлять планированием потоков, чтобы чередовать выполнение потоков Ruby, обеспечивая параллельное выполнение (хотя и не параллельное выполнение).

Или этот код будет истощать другие потоки Puma?

Я не уверен, что вы подразумеваете под голодом ...

Код будет голодатьПоток Puma pool , но сами потоки будут продолжать работать беспрепятственно.

Для пояснения:

Puma имеет пул потоков для HTTP-запросов и обработки задач.Количество потоков ограничено.

Поток HTTPClient будет "зависать", ожидая завершения ввода-вывода и не вернется в пул потоков, уменьшая пул (в целом) и, возможно, вызывая нехватку ресурсов.

Например, если все потоки ожидают ответа HTTPClient, никакие запросы не будут обрабатываться, пока поток не станет снова доступным (HTTPClient и остальная часть работы завершены).

Нас другой стороны, сам поток позволит другим потокам работать одновременно с использованием чередованного планирования.Итак, другие темы не умирают от голода, но Пума в целом может.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...