如何在使用HTML5服务器事件和Java Servlet时防止net :: ERR_INCOMPLETE_CHUNKED_ENCODING? [英] How to prevent net::ERR_INCOMPLETE_CHUNKED_ENCODING when using HTML5 Server events and Java Servlets?

查看:393
本文介绍了如何在使用HTML5服务器事件和Java Servlet时防止net :: ERR_INCOMPLETE_CHUNKED_ENCODING?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始玩服务器事件,我遇到了一个我想了解的错误消息。我真的很快搜索了网页,但没有找到解释,所以我想我可能会做一些非常错误的事情。



在服务器端,我有一个简单的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;
尝试
{
while(run)
{
final ServletResponse resp = asynCtx.getResponse();
run = resp!= null;

if(resp!= null)
{
系统.out.println(推送服务器事件);
final PrintWriter writer = asynCtx.getResponse()。getWriter();
writer.println(data:{time:+ System。 currentTimeMillis()+} \\\
);
writer.flush();
}
else
{
System.out.println(stop beeper ,);
break; //不再运行,我们没有回应
}

Thread.sleep(2000); $ b $ (b)

catch(最终异常e)
{
e.printStackTrace();
}
});

}

在客户端简单地说:

  $(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(开始接收事件...)
});

当我加载HTML文件时,它可以正常工作,接收事件并将其写入控制台。但 30秒后出现错误信息:
$ b GET [HttpOfLocalhost] / events net :: ERR_INCOMPLETE_CHUNKED_ENCODING



为什么?

请求会被杀死,并立即启动一个新的请求,所以它不会终止应用程序,但在控制台上的错误消息并不好。



我的开发者控制台的屏幕截图:





请求/ resposne详情:





计时,这表明它总是在30秒后出现:


谢谢!

解决方案

好吧,所以我无法停下来仔细观察发生了什么。

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



我使用的是:

  System.out.println(Current Timeout is:+ asynCtx.getTimeout()+ms); 

显示:

 当前超时为:30000 ms 

可以将超时设置为0.但是,事件线程会一直运行(不幸的是)。
我使用的另一个解决方案是添加一个 AsyncListener 添加到 AsyncContext 并调用 complete()方法在<一个href =https://docs.oracle.com/javaee/6/api/javax/servlet/AsyncListener.html#onTimeout(javax.servlet.AsyncEvent) =nofollow> onTimeout()方法。



从complete()方法的API文档中获得:
$ b


完成异步操作是在用于初始化此AsyncContext的请求
上启动的,并关闭用于初始化此AsyncContext的响应
。任何类型为
的AsyncListener的监听器都会在创建了
的AsyncContext的ServletRequest中注册,并会在其onComplete
方法中调用。

我的监听器的源代码:

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

$ b $ @Override
public void onTimeout(AsyncEvent asyncEvent)throws IOException
{
//这将优雅地关闭请求和上下文
();
asyncEvent.getAsyncContext()。complete();
System.out.println(onTimeout(...));
}

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

@覆盖
public void onStar tAsync(AsyncEvent asyncEvent)抛出IOException
{
System.out.println(onStart(...));
}
});

所以,是因为缺乏知识。我希望这对某人有帮助。


i just started to play around with Server Events and i run into a chrome error message i would like to understand. i searched the web real quick but didn't find an explanation so i guess i may do something terribly wrong.

On the server side i have a simple servlet that accepts requests and creates a dummy event creator task:

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

}

on the client i simply:

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

when i load the HTML file it works fine, events are received and written to the console. But after 30 seconds i get an error message:

GET [HttpOfLocalhost]/events net::ERR_INCOMPLETE_CHUNKED_ENCODING

why?

the request than gets killed and a new one is started immediately so it doesn't kill the application but error messages on the console aren't nice.

screenshot of my developer console:

request/resposne details:

timing, this shows that it always occurs after 30 seconds:

Thanks!

解决方案

Ok, so i couldn't stand still and look closer whats happening.

The AsyncContext object has a setTimeout(...) method. Per default in my version of tomcat (Tomcat embedded 8) the value is set to 30,000 ms (30 seconds). That's exactly the duration after i got the net::ERR_INCOMPLETE_CHUNKED_ENCODING error in my chrome console.

i checked using:

System.out.println("Current Timeout is: " + asynCtx.getTimeout() + " ms");

which showed:

Current Timeout is: 30000 ms

so to avoid the net:ERR message someone could set the timeout to 0. But than the event thread keeps running forever (unfortunately). Another solution, which i used, is to add a AsyncListener to the AsyncContext and call the complete() method inside the onTimeout() method.

from the API doc of the complete() method:

Completes the asynchronous operation that was started on the request that was used to initialze this AsyncContext, closing the response that was used to initialize this AsyncContext. Any listeners of type AsyncListener that were registered with the ServletRequest for which this AsyncContext was created will be invoked at their onComplete method.

the source code of my listener:

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

so yes, it was due lack of knowledge. i hope this is helpful for someone.

这篇关于如何在使用HTML5服务器事件和Java Servlet时防止net :: ERR_INCOMPLETE_CHUNKED_ENCODING?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆