0

次のように、2つのサーブレットがあります。

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();
  }
}

問題は、負荷が高い場合、サーブレットAを呼び出すクライアントが、応答として「サーブレットB:成功」を受け取ることがあることです。

なぜこれが必要ですか?どのように修正できますか?

ありがとう。

4

1 に答える 1

1

AtomicBooleanをServletBに追加して、応答オブジェクトが1回だけ使用されるようにすると、問題が修正されます。

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);
      }
    }
  }
}
于 2012-11-13T18:34:21.933 に答える