私は非常に異常な状況に直面しています。HTTP 経由で通信する 2 つの Jboss (7.1) インスタンスがあります。インスタンス A はインスタンス B への HTTP 接続を開き、処理するデータを送信します。接続にはタイムアウトが設定されているため、N 秒後に応答が読み取られない場合、SocketTimeoutEception がスローされます。いくつかのクリーンアップが実行され、接続が閉じられます。インスタンス B にはサーブレットがあり、そのような http リクエストをリッスンし、リクエストが受信されると何らかの計算が行われます。その後、応答が取り込まれ、クライアントに返されます。
問題は、計算に時間がかかりすぎると、クライアント (A) はタイムアウトのために接続を閉じますが、サーバー (B) は通常どおり続行し、しばらくしてから応答を送信しようとすることです。接続が閉じていることを検出してハウスキーピングを行いたいのですが、それができないようです。
HttpServletResponse.flushBuffer() を呼び出してみましたが、例外はスローされません。また、永続的な接続を避けるために、http リクエスト「Connection: close」で明示的に設定しましたが、これは効果がありませんでした。http サーブレットの応答は通常どおり処理され、例外なく void に消えます。何が間違っているのかわかりません。このサイトで次のような他の質問を読みました。
Java の HttpServletResponse には isClientConnected メソッドがありません
Tomcat - サーブレット応答のブロック - フラッシュの問題
しかし、私の場合は機能しません。
jboss サーブレット コンテナーに固有の何かが存在する可能性があり、それが原因で応答が無視またはバッファーされるか、クライアントから閉じようとしても http 接続が再利用される可能性があります (A)。問題を探すためのヒントをいくつか提供していただければ幸いです。私はこれに数日を費やしましたが、関連する進展は見られなかったため、早急に解決する必要があります。
関連するコードは次のとおりです。
クライアントコード (サーバー A):
private static int postContent(URL destination, String fileName, InputStream content)
throws IOException, CRPostException
{
HttpURLConnection connection = null;
//Create the connection object
connection = (HttpURLConnection)destination.openConnection();
// Prepare the HTTP headers
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("content-type", "text/xml; charset=UTF-8");
connection.setRequestProperty("Content-Encoding", "zip");
connection.setRequestProperty("Connection", "close");//Try to make it non-persistent
//Timouts
connection.setConnectTimeout(20000);//20 sec timout
connection.setReadTimeout(20000);//20 sec read timeout
// Connect to the remote system
connection.connect();
try
{
//Write something to the output stream
writeContent(connection, fileName, content);
//Handle response from server
return handleResponse(connection);
}
finally
{
try
{
try
{
connection.getInputStream().close();//Try to explicitly close the connection
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
connection.disconnect();//Close the connection??
}
catch (Exception e)
{
logger.warning("Failed to disconnect the HTTP connection");
}
}
}
private static int handleResponse(HttpURLConnection connection)
throws IOException, CRPostException
{
String responseMessage = connection.getResponseMessage();//Where it blocks until server returns the response
int statusCode = connection.getResponseCode();
if (statusCode == HttpURLConnection.HTTP_OK)
{
logger.debug("HTTP status code OK");
InputStream in = connection.getInputStream();
try
{
if (in != null)
{
//Read the result, parse it and return it
....
}
}
catch (JAXBException e)
{
}
}// if
//return error state
return STATE_REJECTED;
}//handleResponse()
サーバーコード (サーバー B):
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String crXML = null;
MediaType mediaType = null;
Object result;
// Get the media type of the received CR XML
try
{
mediaType = getMediaType(request);
crXML = loadDatatoString(mediaType, request);
result = apply(crXML);
}
catch (Exception e)
{
logger.error("Application of uploaded data has failed");
//Return response that error has occured
....
return;
}
// Finally prepare the OK response
buildStatusResponse(response, result);
// Try to detect that the connection is broken
// and the resonse never got to the client
// and do some housekeeping if so
try
{
response.getOutputStream().flush();
response.flushBuffer();
}
catch (Throwable thr)
{
// Exception is never thrown !!!
// I expect to get an IO exception if the connection has timed out on the client
// but this never happens
thr.printStackTrace();
}
}// doPost(..)
public static void buildStatusResponse(HttpServletResponse responseArg, Object result)
{
responseArg.setHeader("Connection", "close");//Try to set non persistent connection on the response too - no effect
responseArg.setStatus(HttpServletResponse.SC_OK);
// write response object
ByteArrayOutputStream respBinaryOut = null;
try
{
respBinaryOut = new ByteArrayOutputStream();
OutputStreamWriter respWriter = new OutputStreamWriter(respBinaryOut, "UTF-8");
JAXBTools.marshalStatusResponse(result, respWriter);
}
catch (Exception e)
{
logger.error("Failed to write the response object", e);
return;
}
try
{
responseArg.setContentType(ICRConstants.HTTP_CONTENTTYPE_XML_UTF8);
responseArg.getOutputStream().write(respBinaryOut.toByteArray());
}
catch (IOException e)
{
logger.error("Failed to write response object in the HTTP response body!", e);
}
}//buildStatusResponse()