使用协程的异步 http 调用(使用像 Feign 这样的 http 客户端)

Asynchronous http calls with coroutines (using an http client like Feign)

有人可以解释一下,如果使用同步 http 调用,将协程应用于 Feign 等 http 客户端是否有任何用处?由于它在收到响应之前一直处于阻塞状态,因此我们不会从编写如下代码中获得任何收益(就最小化线程停机时间而言):

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

我们要不要? 据我了解,如果满足以下条件,它可能会有用:

1) http 客户端在通过网络读取数据时在内部使用了某种暂停功能,例如 suspended fun readChunkOfData() 在某个循环中,然后工作线程不会空闲等待新数据块的到来(它可以在第二个请求上工作,然后来回切换直到请求完成)。我不太了解常规的 http 客户端在内部是如何工作的,所以我需要一些说明。

2) 至少它没有等到请求在另一台服务器上被处理。

有可能吗?

我是否应该在 Feign 中使用 Ktor 框架的某些部分作为 httpClient 来解决这个问题?

如果您在 GUI 应用程序中使用 Feign,即使 Feign 是阻塞的,协程也会提供很大的帮助 API。

配合线程池,协程可以从调用者的角度将阻塞调用变成挂起调用。因为阻塞 GUI 线程是不可能的,所以这是一个很好的匹配。您保留完全相同的同步编程模型(returns 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)
}

相同的推理适用于您拥有顶级事件循环且每个事件处理程序必须快速完成以维持事件处理吞吐量的任何情况。