如何在使用HTML5 Server事件和Java Servlet时阻止net :: ERR_INCOMPLETE_CHUNKED_ENCODING?

Chr*_*ris 11 java google-chrome servlet-3.0 server-sent-events

我刚刚开始使用Server Events,我遇到了一个我想了解的chrome错误消息.我快速搜索网络但没有找到解释所以我想我可能会做一些非常错误的事情.

在服务器端,我有一个简单的servlet接受请求并创建一个虚拟事件创建者任务:

private Executor executor = Executors.newSingleThreadExecutor();

public void doGet(final HttpServletRequest request, final HttpServletResponse response)
{
  final AsyncContext asynCtx = request.startAsync(request, response);

  response.setHeader("Cache-Control", "no-cache");
  response.setContentType("text/event-stream");
  response.setCharacterEncoding("utf-8");

  executor.execute(() -> {
    boolean run = true;
    try
    {
      while (run)
      {
        final ServletResponse resp = asynCtx.getResponse();
        run = resp != null;

        if (resp != null)
        {
          System.out.println("pushing a server event.");
          final PrintWriter writer = asynCtx.getResponse().getWriter();
          writer.println("data: {time: " + System.currentTimeMillis() + "}\n");
          writer.flush();
        }
        else
        {
          System.out.println("stopping beeper, no response object available anymore.");
          break; // do not run anymore, we got no response
        }

        Thread.sleep(2000);
      }
    }
    catch (final Exception e)
    {
      e.printStackTrace();
    }
  });

}
Run Code Online (Sandbox Code Playgroud)

在客户端我简单地说:

$(document).ready(function ()
{

   var source = new EventSource("/events");
   source.onmessage = function (event)
   {
     console.log("received event: " + JSON.stringify(event));
     document.getElementById("eventContainer").innerHTML += event.data + "<br/>";
   };

   console.log("start to receive events...")
});
Run Code Online (Sandbox Code Playgroud)

当我加载HTML文件时,它工作正常,事件被接收并写入控制台.但是30秒后我收到一条错误消息:

获取[HttpOfLocalhost]/events net :: ERR_INCOMPLETE_CHUNKED_ENCODING

为什么?

请求被杀死并且立即启动新的请求,因此它不会终止应用程序,但控制台上的错误消息并不好.

我的开发者控制台截图:

在此输入图像描述

请求/ resposne详细信息:

在此输入图像描述

计时,这表明它总是在30秒后发生:

在此输入图像描述

谢谢!

Chr*_*ris 6

好的,所以我不能停滞不前,仔细观察发生了什么。

AsyncContext对象具有的setTimeout(...)方法。在我的tomcat版本(Tomcat嵌入式8)中,默认情况下,该值设置为30,000毫秒(30秒)。这正是我在Chrome控制台中出现net :: ERR_INCOMPLETE_CHUNKED_ENCODING错误之后的持续时间。

我检查使用:

System.out.println("Current Timeout is: " + asynCtx.getTimeout() + " ms");
Run Code Online (Sandbox Code Playgroud)

显示:

Current Timeout is: 30000 ms
Run Code Online (Sandbox Code Playgroud)

因此,为了避免出现net:ERR消息,可以将超时设置为0。但不幸的是,事件线程永远无法运行。我使用的另一种解决方案是将AsyncListener添加到AsyncContext并在onTimeout()方法内调用complete ()方法。

从complete()方法的API文档中:

完成在用于初始化此AsyncContext的请求上启动的异步操作,并关闭用于初始化此AsyncContext的响应。向其创建此AsyncContext的ServletRequest注册的所有AsyncListener类型的侦听器都将在其onComplete方法中被调用。

我的侦听器的源代码:

asynCtx.addListener(new AsyncListener()
{
  @Override
  public void onComplete(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onComplete(...)");
  }

  @Override
  public void onTimeout(AsyncEvent asyncEvent) throws IOException
  {
    // this will close the request and the context gracefully
    // and the net:ERR is gone.
    asyncEvent.getAsyncContext().complete();
    System.out.println("onTimeout(...)");
  }

  @Override
  public void onError(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onError(...)");
  }

  @Override
  public void onStartAsync(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onStart(...)");
  }
});
Run Code Online (Sandbox Code Playgroud)

是的,这是由于缺乏知识。我希望这对某人有帮助。

  • 请告诉我。我有此错误,但是我不使用Asynk。我转到页面,并且出现此错误。 (2认同)