高并发优化之页面缓存与URL缓存
Posted 慕课训练营
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高并发优化之页面缓存与URL缓存相关的知识,希望对你有一定的参考价值。
在同一时间内有大量用户访问同一页面时,会对服务器造成很大的压力,为了应对这种压力,我们需要对项目进行一些优化,这种优化可以分为页面级优化,服务级优化以及Tomcat服务端优化。
这里我先记录页面优化的页面缓存与URL缓存。
一、页面缓存
商品列表页面由于所有的商品都可以在同一列表展现,所以这里可以做一个页面的缓存。
原本在控制层负责商品列表的方法如下:
@RequestMapping(value = "/to_list")
public String list(HttpServletResponse response, Model model, MiaoshaUser user) {
model.addAttribute("user", user);
List<GoodsVo> goodsList = goodsService.listGoodsVos();
model.addAttribute("goodsList", goodsList);
return "goods_list";
}
页面缓存的思路如下:
客户端在访问一个页面时,先从缓存中查找是否有对应的页面的缓存
如果没有缓存,则重新手动渲染界面。
思路很简单,接下来我们来实现它:
@RequestMapping(value = "/to_list",produces = "text/html")
@ResponseBody
public String list(HttpServletRequest request,HttpServletResponse response, Model model, MiaoshaUser user) {
model.addAttribute("user", user);
List<GoodsVo> goodsList = goodsService.listGoodsVos();
model.addAttribute("goodsList", goodsList);
//取缓存
String html = redisService.get(GoodsKey.goodsList, "", String.class);
if (!StringUtils.isEmpty(html)) {
return html;
}
//如果缓存中没有就要手动渲染
WebContext webContext = new WebContext(request, response, request.getServletContext(),request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", webContext);
//存入缓存
if (!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.goodsList, "", html);
}
return html;
}
上面代码中的我在@RequestMapping注解中加了produces属性,设置返回的数据类型为html类型。
我这个项目属于Spring Boot项目,前端所采用的是Thymeleaf,所以在手动渲染页面时,我可以注入框架自带的ThymeleafViewResolver进行手动渲染页面。
重新访问商品列表页面,发现可以成功显示原本界面,同时远程连接Linux上的Redis,查看是否已经写入了对应的缓存数据:
如上图所示,对应的值为我之前写过的html代码,至此,页面缓存成功实现。
二、URL缓存
URL缓存其实和页面缓存思路相同,二者的不同在于缓存中加入了URL。
其实到这里URL缓存已经很好理解了,只需要在缓存的key中加上URL携带的参数就可以。
代码如下:
@RequestMapping(value = "/to_detail/{goodsId}", produces = "text/html")
@ResponseBody
public String detail(HttpServletRequest request, HttpServletResponse response,
@PathVariable(value = "goodsId") long goodsId, Model model, MiaoshaUser user) {
model.addAttribute("user", user);
// 取缓存
String html = redisService.get(GoodsKey.goodsDetail, ""+goodsId, String.class);
if (!StringUtils.isEmpty(html)) {
return html;
}
GoodsVo goods = goodsService.getGoodsVoById(goodsId);
model.addAttribute("goods", goods);
// 秒杀是否开始
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();// 现在的时间
// 设置一个秒杀的状态
int miaoshaStatus = 0;
// 秒杀还有多久开始
int remainSeconds = 0;
if (now < startAt) {
// 秒杀还没开始,倒计时
miaoshaStatus = 0;
remainSeconds = (int) ((startAt - now) / 1000);
} else if (now > endAt) {
// 秒杀已经结束
miaoshaStatus = 2;
remainSeconds = -1;
} else {
// 秒杀进行中
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus", miaoshaStatus);
model.addAttribute("remainSeconds", remainSeconds);
// 如果缓存中没有就要手动渲染
WebContext webContext = new WebContext(request, response, request.getServletContext(), request.getLocale(),
model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", webContext);
// 存入缓存
if (!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.goodsDetail, ""+goodsId, html);
}
return html;
}
上面的代码中,我使用@PathVariable注解在URL中加上了商品Id这个参数,同时在Redis的key中加上了这个参数,这样就实现了URL的缓存。
内容来自博主:墨肃
博客主页:http://www.gzwshop.xyz/
(如果觉得原创内容不错,记得点个在看哟~)
以上是关于高并发优化之页面缓存与URL缓存的主要内容,如果未能解决你的问题,请参考以下文章