Асинхронные http-вызовы с сопрограммами (с использованием http-клиента, такого как Feign) - PullRequest
0 голосов
/ 08 октября 2018

Может кто-нибудь объяснить, есть ли смысл в применении сопрограмм к http-клиентам, таким как Feign, если он использует синхронные http-вызовы?Поскольку он блокируется до получения ответа, мы не получаем никакой прибыли (с точки зрения минимизации времени простоя потоков) от написания такого кода:

  async {feignApi.getSomeMeaningfulData1()}
  async {feignApi.getSomeMeaningfulData2()}
  //And waiting for the result to combine.

не так ли?Как я понял, это может быть полезно, если:

1) http-клиент использовал некоторую функцию приостановки внутри при чтении данных по сети, например suspended fun readChunkOfData() в некотором цикле, и тогда рабочий поток не будет ждатьВ ожидании поступления нового фрагмента данных (он может работать со вторым запросом, а затем переключаться назад и вперед до тех пор, пока запросы не будут выполнены).Я не знаю много о том, как обычные http клиенты работают внутри, поэтому мне нужно кое-что прояснить

2) по крайней мере он не дождался обработки запроса на другом сервере.

Возможно ли это вообще?

Должен ли я использовать некоторую часть платформы Ktor в качестве httpClient в Feign для решения этой проблемы?

1 Ответ

0 голосов
/ 09 октября 2018

Если вы используете Feign в приложении с графическим интерфейсом, сопрограммы будут очень полезны, даже если Feign является блокирующим API.

В сочетании с пулом потоков сопрограммы могут превратить блокирующий вызов в приостановляющий вызов изперспектива звонящего.Поскольку блокировка потока GUI исключена, это отличное совпадение.Вы сохраняете точно такую ​​же модель программирования синхронизации (простой вызов функции, который возвращает результат HTTP), и при этом соблюдаете ограничения потока GUI.

Базовый пример с Android:

class MyActivity : AppCompatActivity(), CoroutineScope {
    lateinit var masterJob: Job
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + masterJob

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        masterJob = Job()
        this.launch {
            val github: GitHub = feignCall("https://api.github.com")
            val contributors = github.contributors("OpenFeign", "feign")
            findViewById<TextView>(R.id.about_text_view).text = contributors.toString()
        }
    }

    override fun onDestroy() {
       super.onDestroy()
       masterJob.cancel()
}

suspend inline fun <reified T> feignCall(url: String) = withContext(Dispatchers.Default) {
    Feign.builder().decoder(GsonDecoder()).target(T::class.java, url)
}

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

...