Read Blocking of the HttpsURLConnection

這故事發生在某天service狀態顯示為啟動中,但卻沒執行該執行的工作。後來將heap dump出來,從thread list中看到以下狀況:

我們的URLConnection是有設定timeout的:

URLConnection conn = url.openConnection();
conn.setConnectTimeout(connectionTimeout);
conn.setReadTimeout(readTimeout);
為什麼service已經執行好幾天了,還會存在理應timeout的連線呢?

從call stack中去查看java原始碼可以發現,在sun.net.www.protocol.https.HttpsClient.afterConnect中,會使用SSLSocketFactory去建立socket並且做handshake,期間並沒有設定readTimeout;如果http server並沒吐訊息或自動中斷連線,就有可能造成client程式block住。在這種情況下,即使你做中斷也沒用。
目前我們解決的方式是透過一個wrapper SSLSocketFactory,去設定default timeout:

private Socket setDefaultProp(Socket socket) throws SocketException{
	socket.setSoTimeout(readTimeout);
	return socket;
}
 
@Override
public Socket createSocket(Socket aS, String aHost, int aPort, boolean aAutoClose) throws IOException {
	return setDefaultProp(mSocketFactory.createSocket(aS, aHost, aPort, aAutoClose));
}
而HttpsURLConnection會設定我們自己的SSLSocketFactory:
HttpsURLConnection sslconn = (HttpsURLConnection) conn;
sslconn.setSSLSocketFactory(mySSLSocketFactory);