Spring 使用 DeferredResult 进行长轮询
Spring Long Polling with DeferredResult
我有一个 Spring MVC 3.2 应用程序,我需要向该 Web 服务添加一个长轮询以进行实时聊天。
我关注了这篇文章Spring MVC 3.2 Preview: Chat Sample。
主题休息控制器:
private final Map<DeferredResult<String>, Long> chatRequests =
new ConcurrentHashMap<DeferredResult<String>, Long>();
@RequestMapping(value="/{topicId}/updates" , method=RequestMethod.POST)
public @ResponseBody DeferredResult<String> isNewTopic(
@PathVariable Long topicId,
Model model, HttpSession session,
@RequestParam(required = true) String data) throws InterruptedException, CircularDefinitionException{
logger.info("New long polling request "+topicId);
final DeferredResult<String> result = new DeferredResult<String>();
this.chatRequests.put(result, topicId);
result.onCompletion(new Runnable() {
@Override
public void run() {
chatRequests.remove(result);
logger.info("Remove request from queue!");
}
});
Timestamp timestamp = new Timestamp(Long.valueOf(data)*1000L);
String updates = talkService.findNewTopicResponce(topicId,timestamp);
if (!updates.isEmpty()) {
result.setResult(updates);
}
return result;
}
@RequestMapping(value= "/{categoryId}" + "/addAnswer", method=POST)
public @ResponseBody Map respTopic(
@PathVariable Long categoryId,
@RequestParam String msg,
@RequestParam(required = false) String imageUrl,
@RequestParam(required = false) String title,
@RequestParam long talkId,
HttpServletRequest request
) throws CircularDefinitionException, MessagingException,TalkNotExistException{
........................
for (Entry<DeferredResult<String>, Long> entry : this.chatRequests.entrySet()){
if(entry.getValue().equals(talkId)){
entry.getKey().setResult(""+talkId);
}
}
}
现在的问题是:
当我调用“/{topicId}/updates”时,如果 30 秒后没有任何应答,服务器 return 错误 500,如果有人写了一条消息,服务器 return 正确的消息但是服务器总是在30秒后响应,我需要服务器在有人写新消息时而不是在超时过程中立即响应。
我刚遇到同样的问题,我遇到了这个类似的问题:Tomcat 7 server error after 10 seconds when long polling
基本上,你必须告诉Tomcat不要超时。为此,您可以编辑 server.xml
Tomcat 文件(在 conf
目录中)以包含 asyncTimeout
参数。这会告诉你的 Tomcat 一分钟后超时:
<Connector port="8080" protocol="HTTP/1.1" asyncTimeout="60000" connectionTimeout="20000" redirectPort="8443" />
使用值 -1 告诉 Tomcat 永远不会超时。
我有一个 Spring MVC 3.2 应用程序,我需要向该 Web 服务添加一个长轮询以进行实时聊天。 我关注了这篇文章Spring MVC 3.2 Preview: Chat Sample。
主题休息控制器:
private final Map<DeferredResult<String>, Long> chatRequests =
new ConcurrentHashMap<DeferredResult<String>, Long>();
@RequestMapping(value="/{topicId}/updates" , method=RequestMethod.POST)
public @ResponseBody DeferredResult<String> isNewTopic(
@PathVariable Long topicId,
Model model, HttpSession session,
@RequestParam(required = true) String data) throws InterruptedException, CircularDefinitionException{
logger.info("New long polling request "+topicId);
final DeferredResult<String> result = new DeferredResult<String>();
this.chatRequests.put(result, topicId);
result.onCompletion(new Runnable() {
@Override
public void run() {
chatRequests.remove(result);
logger.info("Remove request from queue!");
}
});
Timestamp timestamp = new Timestamp(Long.valueOf(data)*1000L);
String updates = talkService.findNewTopicResponce(topicId,timestamp);
if (!updates.isEmpty()) {
result.setResult(updates);
}
return result;
}
@RequestMapping(value= "/{categoryId}" + "/addAnswer", method=POST)
public @ResponseBody Map respTopic(
@PathVariable Long categoryId,
@RequestParam String msg,
@RequestParam(required = false) String imageUrl,
@RequestParam(required = false) String title,
@RequestParam long talkId,
HttpServletRequest request
) throws CircularDefinitionException, MessagingException,TalkNotExistException{
........................
for (Entry<DeferredResult<String>, Long> entry : this.chatRequests.entrySet()){
if(entry.getValue().equals(talkId)){
entry.getKey().setResult(""+talkId);
}
}
}
现在的问题是:
当我调用“/{topicId}/updates”时,如果 30 秒后没有任何应答,服务器 return 错误 500,如果有人写了一条消息,服务器 return 正确的消息但是服务器总是在30秒后响应,我需要服务器在有人写新消息时而不是在超时过程中立即响应。
我刚遇到同样的问题,我遇到了这个类似的问题:Tomcat 7 server error after 10 seconds when long polling
基本上,你必须告诉Tomcat不要超时。为此,您可以编辑 server.xml
Tomcat 文件(在 conf
目录中)以包含 asyncTimeout
参数。这会告诉你的 Tomcat 一分钟后超时:
<Connector port="8080" protocol="HTTP/1.1" asyncTimeout="60000" connectionTimeout="20000" redirectPort="8443" />
使用值 -1 告诉 Tomcat 永远不会超时。