我对以下谜团感到困惑。在测试我的应用程序时,我经常(可能有25%的时间)在连接SSL套接字时得到两分钟的延迟。我使用的是Java 8,Ubuntu 16.04。当我使用wireshark时,我可以看到没有任何内容通过网络发送到目标服务器。也许可能有其他网络流量,如DNS解析。延迟总是2分钟,不确定度不超过几秒钟。挂起之前的最后一条日志消息是:
DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Connecting socket to redacted:443 with timeout 0
在调试器中暂停验证它是否在PlainSocketImpl类中的套接字连接代码中被阻止:
native void socketConnect(InetAddress address, int port, int timeout)
我很确定我是否注意到这种挂起是否发生在其他应用程序中,我认为这只会影响我的Java程序。我的(Kotlin)代码如下:
import org.apache.http.client.methods.HttpPost
import org.apache.http.config.RegistryBuilder
import org.apache.http.conn.socket.ConnectionSocketFactory
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager
import org.apache.http.util.EntityUtils
import java.security.SecureRandom
import javax.net.ssl.*
fun main(args: Array<String>) {
val client = SSLClient()
val auth = AuthRequest()
val ares = auth.post(client)
val token = ares.value
println(token)
}
class SSLClient {
val client : CloseableHttpClient
init {
val config = Config
config.loadCerts()
val ctx = SSLContext.getInstance("TLSv1.2")
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(config.clientSSLCerts, config.keyPassword.toCharArray())
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(config.serverSSLCerts)
ctx.init(kmf.keyManagers, tmf.trustManagers, SecureRandom())
val sslsf = SSLConnectionSocketFactory(ctx)
val r = RegistryBuilder.create<ConnectionSocketFactory>()
.register("https", sslsf)
.build()
val cm = PoolingHttpClientConnectionManager(r)
client = HttpClients.custom()
.setConnectionManager(cm)
.build()
}
fun post(endpoint : String) : HttpPost {
val post = HttpPost(endpoint)
post.addHeader("Content-Type", "application/xml")
return post
}
fun execute(post : HttpPost, xmlBody : String) : String {
println(xmlBody)
post.entity = StringEntity(xmlBody, Charsets.UTF_8)
client.execute(post).use { response ->
response.allHeaders.forEach { println(it.toString()) }
println(response.statusLine.toString())
if (response.statusLine.statusCode !in 200..299) {
throw Exception(response.statusLine.toString())
}
val entity = response.entity
if (entity == null || entity.contentLength == 0L) {
throw Exception("No body content in HTTP response")
}
val result = EntityUtils.toString(entity)
println(result)
return result
}
}
}
我必须提供的最后一条线索是,在调试器中暂停的时间并不计入两分钟。我可以等待五分钟暂停,取消暂停,它仍然需要两分钟。这告诉我它没有等待外部流程完成,因为外部流程会在暂停时间内取得进展。