对于高并发的项目,为了提高系统的承压能力和响应速度,可以使用redis缓存数据和页面静态化,本篇文章就是记录关于项目优化的过程。
一、页面缓存
对于通用页面,一般使用页面缓存,直接将需要返回给用户的页面存储到redis中,然后当有人再次访问时直接出redis中取出直接返回给用户,不在进行其他操作,节省系统资源。
/* 做页面缓存
* */
@GetMapping(value = "/product_list",produces = "text/html")
@ResponseBody
public String product_list(Model model, User user,
HttpServletResponse response,
HttpServletRequest request,
@RequestParam(value = "pageNo",defaultValue = "1")int pageNo,
@RequestParam(value = "pageSize",defaultValue = "6")int pageSize){
model.addAttribute("user",user);
PageInfo<ProductVo> page = productService.listProcuctVo(pageNo,pageSize);
model.addAttribute("pageInfo",page);
//取缓存
String html = (String) redisService.get("product_list");
System.out.println(html);
if(!StringUtils.isEmpty(html)){
return html;
}
//手动渲染
IWebContext ctx = new WebContext(request,response,request.getServletContext(),
request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("product_list",ctx);
if(!StringUtils.isEmpty(html)){
redisService.set_Time("product_list",html,60);
}
return html;
}
二、url缓存
url缓存是一种特殊的页面缓存,原因在于他有特殊的参数信息,对应不同的页面,比如一个商品的详情页,就需要url缓存,因为不同的商品有不同的信息,使用页面缓存并不能实现这一功能。
/* 商品详情页
* 做url缓存
* */
@RequestMapping(value = "/product_detail/{productId}",produces = "text/html")
@ResponseBody
public String product_detail(Model model, User user,
@PathVariable("productId") long productId,
HttpServletRequest request,
HttpServletResponse response){
//取缓存
String html = (String) redisService.get("product_detail"+productId);
if(!StringUtils.isEmpty(html)){
return html;
}
model.addAttribute("user",user);
ProductVo productVo = productService.selectProductById(productId);
model.addAttribute("product",productVo);
long startTime = productVo.getStart_date().getTime();
long endTime = productVo.getEnd_date().getTime();
long nowTime = System.currentTimeMillis();
int miaoshaStatus = 0;
int remainSeconds = 0;
if( nowTime < startTime){//秒杀未开始
miaoshaStatus = 0;
remainSeconds = (int)((startTime-nowTime)/1000);
}else if(nowTime > endTime){//秒杀结束
miaoshaStatus = 2;
remainSeconds = -1;
}else {//正在进行
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus",miaoshaStatus);
model.addAttribute("remainSeconds",remainSeconds);
//手动渲染
IWebContext ctx = new WebContext(request,response,request.getServletContext(),
request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("product_detail",ctx);
if(!StringUtils.isEmpty(html)){
redisService.set_Time("product_detail"+productId,html,60);
}
return html;
}
三、对象缓存
对象缓存在所有缓存中是一个比较小的缓存单位,最常用的是对用户常用信息的缓存,加快系统对常用用户信息的读取速度从而加快系统的反应速度。
四、页面静态化
页面静态化也是前后端分离的一大优势所在,就是利用浏览器缓存数据从而减少与服务器的交互。一些前端的框架VUE.JS之类的都是很好解决这种问题的框架,但需要认真的学习,为了简单,这里使用JQuery的ajax来实现。
后端controller层:
@RestController
public class MiaoshaController {
@Autowired
ProductService productService;
@Autowired
OrderService orderService;
@Autowired
MiaoshaService miaoshaService;
private static Logger logger = Logger.getLogger("MiaoshaController.class");
@PostMapping(value = "/do_miaosha")
public ResponseResult domiaosha(Model model, User user,
@RequestParam("productId") long productId){
if(user == null){
return ResponseResult.error(ResponseCode.NO_LOGIN);
}
//判断库存
ProductVo productVo = productService.selectProductById(productId);
if(productVo.getStock_count()<=0){
return ResponseResult.error(ResponseCode.PRODUCT_MIAOSHA_OVER);
}
//判断是否已经秒杀
MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdAndProductId(user.getId(),productId);
if(miaoshaOrder!=null){
return ResponseResult.error(ResponseCode.MIAOSHA_NO_AGAIN);
}
//秒杀开始 减库存-》下订单 -》写入秒杀订单
Order order = miaoshaService.miaosha(user,productVo);
return ResponseResult.success(order);
}
}
js:使用JQuery的ajax来处理数据,实现前后端分离
function domiaosha() {
var productId = $("#productId").val();
$.ajax({
url: "/do_miaosha",
type: "POST",
data:{productId:productId},
dataType:"json",
success:function (data) {
if(data.data != null){
window.location.href="/product_miaosha_detail.htm?orderId="+data.data.id;
}else {
alert(data.msg);
}
},
error:function () {
alert("客户端请求错误!");
}
});
}
五、静态资源优化
(1)JS/CSS压缩,减少流量
(2)多个JS/CSS组合,减少连接数
(3)CDN就近访问