自己写了一个很简单的实现非阻塞的对于请求的消息队列处理,前台代码:
<script type="text/javascript">
function go() {
var timestamp = (new Date()).valueOf();
$.ajax({
url:"${pageContext.request.contextPath}/go",
data:"param="+timestamp,
success:function(data){
}
});
}
</script>
</head>
<body>
<input type="button" onclick="go()" value="提交" />
</body>
首页我做了个按钮,每按一次向后台传一个当前时间参数.模拟发出请求.
@RequestMapping("/go")
public void go(@RequestParam(value = "param", required = true) String param) {
service.add(param);
System.out.println("添加成功");
}
后台这里接收到参数,然后处理业务.
public class ServiceImpl implements Service {
private static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
@Override
public void add(String param) {
queue.add(param);
}
@Override
public String get() {
return queue.poll();
}
}
业务层add方法,将请求参数放到队列中,等待处理
<body>
<h1>${ret }</h1>
</body>
响应页面.
@RequestMapping("/get")
public String get(Model model) {
String ret = service.get();
if(null != ret) {
model.addAttribute("ret", ret);
}else {
model.addAttribute("ret", "下单成功,请稍后查询结果");
}
System.out.println("处理成功");
return "get";
}
如果没处理完,则响应友好信息.
public class ServiceImpl implements Service {
private static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
@Override
public void add(String param) {
queue.add(param);
}
@Override
public String get() {
return queue.poll();
}
}
从ConcurrentLinkedQueue队列中取出信息,并删除.如果没有则返回null;
如果需要判断队列是否为空的话,最好使用isEmpty判断,使用size的话会造成处理时间过长.
执行的效果是,多次按提交按钮,将多条请求添加到队列中,用户响应页面每次刷新得到队列中的信息,如果取完队列中信息将得到友好提示.
这次用到了ConcurrentLinkedQueue非阻塞队列的先入先出原理,使用这个类是线程安全的,非阻塞也提供了良好的体验.
如果使用linkedblockingdeque阻塞队列,如果队列中没有信息,用户响应页面将一直阻塞等待,造成连接时间过长.
实际中我认为可以这样用:当非常多请求的提交时,将请求数据放入消息队列.按需求编写定时器,定时定量的取出队列中数据进行处理,缓解服务器压力.前台使用友好反馈信息,一定时间再次请求得到响应数据.
不过这样并不适合解决高并发,快速响应的情况.应该考虑集群、分布式、动静分离、数据库读写分离等技术范畴.
ActiveMQ消息总线技术,遇到问题再说.