有人可以解释一下如果将协程应用到Feign之类的http客户端(如果它使用同步http调用),是否有任何用处?由于它直到收到响应才被阻塞,因此通过编写如下代码不会获得任何收益(就最大程度地减少线程停机时间而言):
async {feignApi.getSomeMeaningfulData1()}
async {feignApi.getSomeMeaningfulData2()}
//And waiting for the result to combine.
我们要不要? 据我了解,如果满足以下条件,它可能会有用:
1)http客户端在通过网络读取数据时在内部使用了某种暂停功能,例如
suspended fun readChunkOfData()
在某个循环中,然后工作线程将不会等待空闲以等待新数据块的来临(它可以在第二个请求上工作,然后来回切换直到请求完成)。我对常规http客户端在内部的工作方式了解不多,所以我需要澄清一下。
2)至少它没有等到另一台服务器上处理了请求。
有可能吗?
我应该在Feign中使用Ktor框架的某些部分作为httpClient来解决此问题吗?
答案 0 :(得分:1)
如果您在GUI应用程序中使用了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)
}
相同的推理适用于您具有顶级事件循环且每个事件处理程序必须快速完成才能维持事件处理吞吐量的任何情况。