【问题标题】:Servlet is writing data to outputstream of another servletServlet 正在将数据写入另一个 Servlet 的输出流
【发布时间】:2012-11-10 05:25:38
【问题描述】:

我有两个servlet,如下:

public class ServletA extends HttpServlet {
  public void doGet(final HttpServletRequest request, 
                    final HttpServletResponse response) {
    // Kick off some async processing
    RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
      @Override
      public void completed(ResponseInfo responseInfo) {
        // Send some data to database
        TransactionManager.getInstance().create(...);
      }
    )};
    // Send response to client
    response.getWriter().println("ServletA: SUCCESS");
  }
}

public class ServletB extends HttpServlet {
  public void doGet(final HttpServletRequest request, 
                    final HttpServletResponse response) {
    // Use a CountDownLatch to force synchronous processing on an asynchronous construct
    final CountDownLatch completedSignal = new CountDownLatch(1);
    RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
      @Override
      public void completed(ResponseInfo responseInfo) {
        // Send some data to database, and send response to client
        TransactionManager.getInstance().create(...);
        response.getWriter().println("ServletB: SUCCESS");
        completedSignal.countDown();
      }
    )};
    completedSignal.await();
  }
}

问题是,在重负载下,调用 ServletA 的客户端有时会收到“Servlet B: SUCCESS”作为响应。

为什么会这样?如何解决?

谢谢。

【问题讨论】:

    标签: apache servlets asynchronous tomcat7 anonymous-class


    【解决方案1】:

    向 ServletB 添加 AtomicBoolean 以确保响应对象仅在修复问题后才使用:

    public class ServletB extends HttpServlet {
      public void doGet(final HttpServletRequest request, 
                        final HttpServletResponse response) {
        // Use a CountDownLatch to force synchronous processing on an asynchronous construct
        final CountDownLatch completedSignal = new CountDownLatch(1);
        // Use an AtomicBoolean to ensure response is only used once
        AtomicBoolean responseSent = new AtomicBoolean(false);
        RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
          @Override
          public void completed(ResponseInfo responseInfo) {
            // Ensure response has not already been sent
            if(!responseSent.compareAndSet(false, true)) { return; }
            // Send some data to database, and send response to client
            TransactionManager.getInstance().create(...);
            response.getWriter().println("ServletB: SUCCESS");
            completedSignal.countDown();
          }
        )};
        if(!completedSignal.await(60, TimeUnit.SECONDS)) {
          // Ensure response has not already been sent
          if(responseSent.compareAndSet(false, true)) {
            response.sendError(503);
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-17
      • 2011-12-14
      • 1970-01-01
      • 2013-06-06
      • 2010-10-07
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      相关资源
      最近更新 更多