在 HTTP 503 上重新建立 TCP 连接
Re-establish TCP connection on HTTP 503
我们在部署在 k8s 集群上的 Java 应用程序中使用 okhttp。我们的源应用程序没有启用 istio,并使用 envoy sidecar 连接到目的地。连接链如下所示:
SRC --------> 特使 -> DST
所以实际上 SRC 应用程序不是直接与 DST 应用程序建立连接,而是与它前面的 Envoy 代理建立连接。当 DST 应用程序关闭时,它会终止 DST 和 Envoy 之间的所有连接,但 SRC 和 Envoy 之间的连接保持打开状态。这就是 SRC 应用程序开始收到 503 错误的原因。另一条从 SRC 到 DST 的消息也得到 503,因为我们一直重复使用在 okhttp 的连接池中建立的空闲连接。
此问题的解决方案是重新建立新的 TCP 连接,而不是使用连接池中的空闲连接之一。
是否可以配置 okhttp 以根据收到的单个 HTTP 503 终止整个 TCP 连接?
像这样的东西应该可以工作
import okhttp3.OkHttpClient
import okhttp3.Request
fun main() {
val client = OkHttpClient.Builder()
.eventListenerFactory(LoggingEventListener.Factory())
.addNetworkInterceptor { chain ->
chain.proceed(chain.request()).also { response ->
println(response.code)
if (response.code == 503) {
println("closing")
chain.connection()?.socket()?.close()
}
}
}
.build()
val response1 = client.newCall(Request.Builder().url("https://httpbin.org/get").build()).execute()
val response2 = client.newCall(Request.Builder().url("https://httpbin.org/status/503").build()).execute()
val response3 = client.newCall(Request.Builder().url("https://httpbin.org/get").build()).execute()
}
我们在部署在 k8s 集群上的 Java 应用程序中使用 okhttp。我们的源应用程序没有启用 istio,并使用 envoy sidecar 连接到目的地。连接链如下所示:
SRC --------> 特使 -> DST
所以实际上 SRC 应用程序不是直接与 DST 应用程序建立连接,而是与它前面的 Envoy 代理建立连接。当 DST 应用程序关闭时,它会终止 DST 和 Envoy 之间的所有连接,但 SRC 和 Envoy 之间的连接保持打开状态。这就是 SRC 应用程序开始收到 503 错误的原因。另一条从 SRC 到 DST 的消息也得到 503,因为我们一直重复使用在 okhttp 的连接池中建立的空闲连接。 此问题的解决方案是重新建立新的 TCP 连接,而不是使用连接池中的空闲连接之一。 是否可以配置 okhttp 以根据收到的单个 HTTP 503 终止整个 TCP 连接?
像这样的东西应该可以工作
import okhttp3.OkHttpClient
import okhttp3.Request
fun main() {
val client = OkHttpClient.Builder()
.eventListenerFactory(LoggingEventListener.Factory())
.addNetworkInterceptor { chain ->
chain.proceed(chain.request()).also { response ->
println(response.code)
if (response.code == 503) {
println("closing")
chain.connection()?.socket()?.close()
}
}
}
.build()
val response1 = client.newCall(Request.Builder().url("https://httpbin.org/get").build()).execute()
val response2 = client.newCall(Request.Builder().url("https://httpbin.org/status/503").build()).execute()
val response3 = client.newCall(Request.Builder().url("https://httpbin.org/get").build()).execute()
}