1.頁面緩存
想象一下秒殺的場景,僧多粥少绍在,在秒殺將要開始的半分鐘內勺届,用戶可能會不斷刷新秒殺頁面,此時對于頁面訪問的流量將達到頂峰桑滩。
解決方案
- 服務端緩存頁面:
在服務端手動渲染商品詳情頁面,直接返回html給前端
將頁面加入redis緩存允睹,設置合適的运准,較短的有效期,比如60s
每次請求都先從redis中取缭受,取不到再渲染并返回 - 客戶端緩存頁面:
同時可以設置瀏覽器緩存該頁面60s胁澳,這樣在此期間瀏覽器、服務器就沒有數(shù)據交互了
@GetMapping(value="/goods2",produces="text/html")
@ResponseBody
public String findAllGoods2(Model model,HttpServletRequest request, HttpServletResponse response){
//TODO 此處想設置瀏覽器緩存該頁面60s米者,但是好像不管用啊
response.setHeader("Cache-Control", "max-age:60");
//先從緩存中取韭畸,沒有再渲染
String html = redisTemplate.opsForValue().get("goods");
if(!StringUtils.isEmpty(html)) {
return html;
}
List<Goods> goods = goodsService.findAllGoods();
model.addAttribute("goods",goods);
//設置秒殺開始時間 為了使用緩存,當前時間使用客戶端自己的時間
model.addAttribute("targetTime",Constant.BARGAIN_DASH_START_TIME);
//手動渲染
WebContext ctx = new WebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("goods", ctx);
//將結果加入redis蔓搞,設置有效期60s
if(!StringUtils.isEmpty(html)) {
redisTemplate.opsForValue().set("goods", html, 60, TimeUnit.SECONDS);
}
return html;
}
由于商品頁面比較固定胰丁,客戶端對于頁面實時更新要求不會很高,所以可以加入redis緩存起來喂分。
由于redis緩存了頁面锦庸,所以頁面的倒計時效果只能取客戶端的時間作為當前時間了。在真正秒殺的時候蒲祈,服務端會對秒殺是否開始了做一次判斷甘萧。其實,即使采用服務端時間做當前時間讳嘱,倒計時也不可能完全準確幔嗦,最好還是后端再做判斷,所以這里直接采用客戶端的時間做當前時間沥潭,也是合適的邀泉。
我想在服務端指定客戶端緩存該頁面60s,但是實際測試好像沒效果,仍然會每次都發(fā)get請求汇恤,可能是哪里沒有設置對吧庞钢。如果可以在瀏覽器緩存,將會更進一步提高性能因谎。
這里前端頁面倒計時效果基括,使用的是tictac,是從github上搜索來的财岔,這種小組件风皿,直接上github上找,比百度要更快更好匠璧。
壓力測試
可以看到桐款,該優(yōu)化的效果還是極為明顯的。
2.其他優(yōu)化點
目前代碼主要是從后端進行了優(yōu)化夷恍,如果有專業(yè)前端支持魔眨,前后端共同協(xié)作,效果會更好酿雪。
- 這里thymeleaf的渲染畢竟還是在服務端完成的遏暴,如果有前端人員支持的話,可以考慮下最近流行的angular指黎、veu朋凉,實現(xiàn)徹底的前后端分離。前端發(fā)起請求醋安,后端將商品信息緩存到redis侥啤,前端渲染頁面,緩存頁面茬故。將工作量分擔給無數(shù)個客戶端,減輕服務端壓力蚁鳖。
- 靜態(tài)資源壓縮磺芭,js css html等進行壓縮,降低流量消耗
- nginx靜態(tài)資源緩存
附:所有代碼在github上