java.net.SocketException:Socket Closed,尽管输入和输出流在读取,写入后关闭

时间:2017-11-02 08:55:42

标签: java multithreading sockets http httpurlconnection

我正在运行多线程java应用程序,其中下面的方法将由多个线程(大约300个)并行执行。我只在线程数较多时看到此异常,但在线程数小于50时则看不到。 我在stackoverflow中阅读了一些帖子,代码看起来对所描述的帖子抱怨。任何帮助,将不胜感激。提前谢谢。

这是我的方法:

public static String invokeWebService(String request, String fwfmId, BatchVO batchVO){
    String responseString = "";
    //log the request string
    Logger_trace.info("Service request for input "+ fwfmId +":: "+CommonUtil.removeCrLf(request));
    try {
            URL url = new URL(batchVO.getWebServiceUrl());
            HttpURLConnection  urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Content-type", "text/xml; charset=utf-8");

            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setConnectTimeout(Integer.parseInt(batchVO.getConnectionTimeOut()));
            urlConnection.setReadTimeout(Integer.parseInt(batchVO.getReadTimeOut()));
            OutputStream outputStream = urlConnection.getOutputStream();
            outputStream.write(request.getBytes());
            outputStream.flush();

            //get response form input stream and convert into string
            InputStreamReader inputStreamReader = new InputStreamReader(urlConnection.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = bufferedReader.readLine()) != null) {
                response.append(inputLine);
            }

            responseString = response.toString();

            //close resources
            bufferedReader.close();
            inputStreamReader.close();
            outputStream.close(); 

            //log the response string
            logger_trace.info("Service response for input "+ fwfmId +":: "+ CommonUtil.removeCrLf(responseString));

            //Update Database columns
            updateRecordInTable(request, responseString, fwfmId, batchVO.getDataSource(), batchVO.getBatchId());    

        } catch (SocketConnectException e) {
            logger_trace.error("WebserviceHandler.invokeWebService : SocketConnectException block : "+fwfmId +" ", e);
            updateRecordInTableWithTimeout(fwfmId, batchVO.getDataSource(), batchVO.getBatchId());
        } catch (SocketTimeoutException e) {
            logger_trace.error("WebserviceHandler.invokeWebService : SocketTimeoutException block : "+ fwfmId+" ", e);
            updateRecordInTableWithTimeout(fwfmId, batchVO.getDataSource(), batchVO.getBatchId());
        } catch (MalformedURLException e) {
            logger_trace.error("WebserviceHandler.invokeWebService : MalformedURLException block : ", e);
        } catch (IOException e) {
            logger_trace.error("WebserviceHandler.invokeWebService : IOException block : ", e);
        } catch(Exception e){
            logger_trace.error("WebserviceHandler.invokeWebService : General Exception block : ", e);
        }
        return responseString;
    }

例外:

 [ERROR] 2017-10-31 03:18:54,435 [main] TRACE -
 WebserviceHandler.invokeWebService : IOException block : 
 java.net.SocketException: Socket Closed
         at java.net.AbstractPlainSocketImpl.setOption(AbstractPlainSocketImpl.java:212)
 ~[?:1.8.0_131]
         at java.net.Socket.setTcpNoDelay(Socket.java:980) ~[?:1.8.0_131]
         at weblogic.net.http.HttpClient.openServer(HttpClient.java:411)
 ~[wlfullclient.jar:12.2.2.0.0]
         at weblogic.net.http.HttpClient.openServer(HttpClient.java:511)
 ~[wlfullclient.jar:12.2.2.0.0]
         at weblogic.net.http.HttpClient.New(HttpClient.java:313) ~[wlfullclient.jar:12.2.2.0.0]
         at weblogic.net.http.HttpURLConnection.getHttpClient(HttpURLConnection.java:314)
 ~[wlfullclient.jar:12.2.2.0.0]
         at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:760)
 ~[wlfullclient.jar:12.2.2.0.0]
         at weblogic.net.http.SOAPHttpURLConnection.getInputStream(SOAPHttpURLConnection.java:41)
 ~[wlfullclient.jar:12.2.2.0.0]
         at ca.bell.webservice.WebServiceHandler.invokeWebService(WebServiceHandler.java:56)
 [MigrationTool.jar:?]
         at ca.bell.webservice.ExecuteMigrationWork.performRun(ExecuteMigrationWork.java:40)
 [MigrationTool.jar:?]
         at ca.bell.workmanagement.work.Work.call(Work.java:155) [MigrationTool.jar:?]
         at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_131]
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 [?:1.8.0_131]
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 [?:1.8.0_131]
         at java.lang.Thread.run(Thread.java:748) [?:1.8.0_131]

1 个答案:

答案 0 :(得分:0)

有趣。让我们从最近的异常来源开始分析堆栈跟踪。从AbstractPlainSocketImpl的{​​{3}}开始,强制执行的第一个前提是:

public void setOption(int opt, Object val) throws SocketException {
  if (isClosedOrPending()) {
    throw new SocketException("Socket Closed");
  }
...

由于HttpURLConnection的范围仅限于方法invokeWebService,我们可以排除套接字上并发操作的假设,因为它似乎很好并且没有关闭套接字,我相信isClosedOrPending会返回true,因为套接字的文件描述符是null

public boolean isClosedOrPending() {
    /*
     * Lock on fdLock to ensure that we wait if a
     * close is in progress.
     */
    synchronized (fdLock) {
        if (closePending || (fd == null)) {
            return true;
        } else {
            return false;
        }
    }
}

此分析中有疑问的是fd文件描述符为null的原因。但是,这在现阶段并不重要。如果我们相信我们的假设,我们可以得出的一个结论是,您为系统创建了太多的连接来处理。

我们如何解决这个问题?在这里,我们需要退一步,看看我们是否可以重构代码以限制并发连接的数量。我需要更多有关您具体实施的详细信息,以缩小设计候选人的范围,否则无限。例如,连接池是否合适?我们应该实施背压并扼杀客户吗?我们应该水平扩展并分配负载吗?