我一直在努力解决一些看起来非常基本的问题,这个问题与使用 Jetty continuations 进行长轮询有关。
为了简单起见,我删除了所有应用程序特定的代码,只留下简单的延续相关代码。
我在下面粘贴我的 servlet 的 doPost 方法。我需要一些专家指导的关键问题是
- 在下面的代码块中,如果我按原样运行它并触发带有大约 200 字节的 post 正文的 post 请求,那么 500 个长轮询连接的内存量约为 20 MB。
- 好像我将突出显示的块注释为“减少内存占用:: 下面的注释块”,然后内存占用降至 7 MB
在这两种情况下,我都等待系统稳定,多次调用 GC,然后通过 jConsole 读取内存。它并不精确,但差异是如此之大且可以解释,以至于这里或那里的几个 100 字节的精度无关紧要。
我的问题爆发了,考虑到我的服务器需要保持 100K 连接,如果不是更多的话。在这里,这种无法解释的大小增加最终导致使用了接近 GB 的额外堆。
(是什么导致了这种额外的堆使用,即使从流中读取的内容也没有保留在 doPost 方法的范围之外。但它仍然添加到堆中......我错过了什么?)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Continuation cc = ContinuationSupport.getContinuation(req);
//if continuation is resumed, then send an answer back with
//hardcoded answer
if (cc.isResumed()) {
String myJson = "{\"1\",\"2\"}";
res.setContentType("application/json");
res.setContentLength(myJson.length());
PrintWriter writer = res.getWriter();
writer.write(myJson);
writer.close();
}
// if it is the first call to doPost ( not reentrant call )
else if (cc.isInitial()) {
//START :: decrease memory footprint :: comment this block :: START
// store the json from the request body in a string
StringBuffer jsonString = new StringBuffer();
String line = null;
BufferedReader bufferedReader = req.getReader();
while ((line = bufferedReader.readLine()) != null) {
jsonString.append(line);
}
//here jsonString was parsed and some values extracted
//though that code is removed for the sake of this publish
// as problem exists irrespective...of any processing
line = null;
bufferedReader.close();
bufferedReader = null;
jsonString = null;
// END :: decrease memory footprint :: comment this block :: END
cc.setTimeout(150000);
cc.suspend();
}
}