Я пытаюсь добиться сопрограмм блокировки ввода-вывода (kotlin) таким образом, чтобы получать больше сетевых вызовов, чем потоков. Понятно, как использовать сопрограммы таким образом, чтобы не блокировать основной поток, однако в конечном итоге каждая сопрограмма запускается в протекторе, и сеть вызывает блокировку этого потока (для сравнения, использование NodeJS позволяет повторно использовать рабочий поток, в то время как другие запросы жду ответа, чтобы вернуться).
Мой вариант использования заключается в том, что для каждого входящего запроса мне нужно сделать 2-3 независимых внешних вызова, объединить ответ и вернуться. Делать это последовательно - пустая трата времени. Параллельное выполнение этого потребует от моего сервиса выполнения примерно в 2-3 раза большего количества входящих потоков (что составляет около 1 КБ потоков только для ожидания ввода-вывода).
Во многих примерах процедур используется delay
, что позволяет одновременно использовать потоки для нескольких процедур. Однако, используя реальный вариант использования сетевых вызовов, я не могу этого достичь.
Чего мне не хватает? Как я могу приостановить сопрограмму, пока внешняя служба не ответит?
Например, этот пример работает только на 5 потоках, но повторно использует потоки более 1000 вызовов, поэтому все заканчивается в течение ~ 100 мс (каждая операция составляет 100 мс)
val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
(1..1000).forEach {
launch(myPool) {
delay(100)
}
}
}
В противоположность этому, на самом деле выполняется только 5 одновременных вызовов в 5 потоках, и переход к следующему выполняется только после завершения. Я хочу, чтобы все вызовы выполнялись "параллельно", используя возможность отправки запроса в ожидании ответа - так же, как это делается в NodeJS :
val restTemplate = RestTemplate()
val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
(1..1000).forEach {
launch(myPool) {
restTemplate.getForObject("http://myTest.com", String::class.java) // Say it takes 100ms to response
}
}
}