【发布时间】:2012-02-16 18:27:06
【问题描述】:
我正在研究一个将 http 请求(用于测试目的的 GET)发送到 java servlet 的设置。它的工作原理是,ser 让从浏览器获取请求,对其进行解析并通过 TCP 套接字将其发送到“主”服务器,该服务器处理请求并发送回响应。然后,servlet 提取之前存储在 ConcurrentHashMap 中的 HttpServletResponse,打开 PrintWriter,然后发回响应。一切都很顺利,除了 HttpServletResponse 并不总是将写入 PrintWriter 的信息发回。浏览器每次都会收到“OK”响应,但响应通常不包含我尝试编写的任何信息。
下面是初始 doGet 的代码,它传递 HttpServletResponse 实例,然后是写入响应缓冲区的方法。之后包括浏览器收到的响应。之后,对如何可靠地获得预期结果进行一些观察,以防有助于确定问题。
请注意,唯一的变量似乎是响应是否被写入;我已经倾注了输出日志,并且找不到按预期写入响应的时间与未按预期写入的时间之间的任何其他差异。我写的 HTTPServletResponseListener 每次都会收到响应。
[使用 Glassfish 3.1.1]
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String js = request.getParameter("json");
// Omitting try-catch for space
Message msg = this.parser.parseToMessage(js);
this.sc.send(msg, new HTTPServletResponseListener(response));
}
以及响应时调用的 HTTPServletResponseListener 方法(除了仅将本地 HttpServletResponse 分配给本地字段的构造函数,这是唯一的方法)
public void handleResponse(ResponseMessage response) {
DataParser parser = new JSONParser();
String temp = parser.parseToString(response);
httpResponse.setContentType("application/json");
httpResponse.addHeader("Hmm","yup");
try {
PrintWriter out = httpResponse.getWriter();
out.println(temp);
} catch (IOException ex) {
Logger.getLogger(HTTPServletReponseListener.class.getName()).log(Level.SEVERE,null,ex);
}
}
响应和浏览器接收它们:
当它按预期工作时:
当响应为空时:
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Sun Microsystems Inc./1.6)
Server: GlassFish Server Open Source Edition 3.1.1
Content-Length: 0
Date: Thu, 16 Feb 2012 15:26:35 GMT
当响应符合预期时:
HTTP/1.1 200 OK
Hmm: yup
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Sun Microsystems Inc./1.6)
Server: GlassFish Server Open Source Edition 3.1.1
Content-Type: application/json;charset=ISO-8859-1
Content-Length: 126
Date: Thu, 16 Feb 2012 15:27:30 GMT
观察:
按照这些步骤,我可以在 95% 的时间内得到响应....否则,它的成功率约为 50%。
在浏览器上点击刷新...部署后的前几个请求往往工作得更频繁 在再次点击刷新之前等待至少 5 秒(发送另一个测试请求) 这往往可靠地工作。如果失败,您必须等待 15 秒,然后它往往会再次工作。
如果 HttpServletResponse 是在等待响应之前写入的,那么它每次都有效。
非常感谢您花时间阅读本文。我已经阅读了其他 Stackoverflow 问题,但似乎没有涉及到这个特定问题,除非我错过了连接。
【问题讨论】:
-
sc.send()调用是非阻塞的吗?如果是这样,那么如果 servlet 容器将请求/响应对象池化(大多数情况下都是这样),那么您可能会遇到问题。 -
它确实是非阻塞的,我想你和下面的@tomasz 已经死了,我会尽快更新这个:)