web应用在部署时通常会部署多个实例,但是这多个实例能并发处理成百上千的请求,那么每个实例肯定都能并发处理多个请求。我们知道SpringBoot支持并发处理多个请求,如果采用默认的tomcat servlet容器,springboot可以并发处理200个请求。
接下来就通过简单的demo来验证本地启动的单实例SpringBoot应用能并发处理多个请求。
1 接口搭建
controller代码如下。
@RestController
@RequestMapping("/concurrent/request")
public class MultiConcurrentRequest {
@RequestMapping(value = "/multi", method = RequestMethod.GET)
public ResponseEntity<Map<String, String>> dummytsp(@RequestParam(value="msg", defaultValue="Hello") String msg) {
System.out.println("" + new Date() + " : start : ThreadId " + Thread.currentThread().getId() + " : param : " + msg);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("" + new Date() + " : end : ThreadId " + Thread.currentThread().getId() + " : param : " + msg);
Map<String, String> response = new HashMap<>();
response.put("message", msg);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
2 并发验证
通过PostMan或者浏览器同时发送两个请求:
http://localhost:8080/concurrent/request/multi?msg=bei
http://localhost:8080/concurrent/request/multi?msg=jing
控制台输出结果:可以看到发送的2个请求是在2个线程中并发处理的。
3 怎么调试
起初打断点验证时,发现并不完全是并发处理的。断点位置如下:
也是同时发送2个请求,执行结果如下。首先在15分58秒发起的2个请求,第1个请求最新遇到断点,这时第2个请求始终没进入。然后在16分05秒时按F9继续运行,可以看到第2个请求进来了,并也遇到断点暂停了;这时第1个请求虽然往下走了,但是一直到16分17秒再次按F9继续运行时,第1个请求也没有打印结束信息。16分17秒按F9继续运行后,间隔5秒后控制台输出第2个请求的结束信息。
这样的结果给人感觉2个请求在一会并行一会串行处理,不符合第2节的结论。查资料发现,原来IDEA的断点支持两次suspend策略:
- All:当任一线程遇到断点时,所有线程都被暂停。
- Thread:当某个线程遇到断点时,只有该线程被暂停,其他线程继续执行。
将上述断点的Suspend策略调整为Thread后,调试现象就和第2节的结论一致了。