avatar

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】01_电商秒杀商品回顾

项目环境及技术

学习环境:

  • Intellij IDEA 2018.1.3
  • 阿里云ECS或本地Linux虚拟机,操作系统centos 7.4
  • MySQL5.6数据库,Redis4.0.1缓存,消息队列rocketmq4.5,phantomjs无头浏览器

技术储备:

  • 了解SSM、SpringBoot等框架
  • 熟悉Linux基本命令
  • 了解MySQL常用命令
  • 了解Redis常用命令

项目框架设计

数据层:

  • 事务@Transcantional注解的处理方式—表示处于一个事务当中,若一个事务中有任何一个步骤失败,事务就会回滚
  • 数据接入层数据Dao
  • 本地缓存、集中式缓存在商品详情页的应用,提高流式读取的效率

整个流程是:

整个页面基于HTML、CSS,然后基于JavaScript的jQuery库发送了一个动态交互的请求,给接入层controller进行通用处理,然后我们基于SpringMVC的controller层会向业务层调用相应的服务,

业务层会调用数据层的Dao,通过事务管理数据DaoMapper的方式将数据的增删改查落入到数据库中,最后到本地电脑中

数据模型(Data Object):借助于Mybatis的ORM操作将关系型数据库的表结构,通过XML的方式,定义成Java的Object结构

领域模型(Domain Model):具有一个对象的生命周期(创建、更新、删除、消亡),它可以和数据模型组合,比如用户对象是一个领域模型,它是由用户基本信息+用户密码信息两个数据模型共同组成的。

贫血模型:项目里的用户对象就设计成贫血模型:指的是拥有各种属性信息和get、set方法,但是不包含有登陆、注册等功能

ViewObject:与前端对接的模型,供展示的聚合模型

项目详细设计


几个问题

问题1. 为什么要将商品的库存表item_stock与商品表item分开?

1) 库存操作非常耗时、性能,在商品交易过程中库存减,如果合并到item表中,每次会对对应行加行锁如果分开库存表,虽然每次减库存过程还是会加行锁,但是可以将这张表拆到另一个数据库当中,分库分表,做效果的优化

问题2. 跨域请求问题

在存在跨域请求问题的类前都加上一句支持跨域操作(服务端解决方式):

1
@CrossOrigin(origins = {"*"},allowCredentials = "true")

问题出现在:由于我们是做前后端分离的设计,jQuery会有跨域限制,用ajax请求对应网页的url文件位置时,静态资源文件和jQuery动态请求是分离状态,所以在ajax请求要加上一句:

xhrFields:{withCredentials:true},因为要解决客户端上session共享的问题(客户端session共享

跨域感知session

跨域感知session需要解决两个问题,第一个是解决跨域问题,第二个是解决跨域cookie传输问题

跨域问题

解决跨域问题就如上面问题2所示,使用了springboot自带的crossOrigin注解

@CrossOrigin(origins = {"*"},allowCredentials = "true")

注解加上后,所有的http response头上都会加上Access-Control-Allow-Origin * 以及 Access-Control-Allow-Headers * 两个头部,这样可以满足CORS的跨域定义,我们的ajax看到这两个头部就认定对应的域名接收任何来自或不来自于本域的请求

跨域传递cookie问题

跨域和跨域传递cookie是两个不同纬度的问题,我们依靠上述的方式解决了跨域问题,但要做到跨域感知seesion需要解决在跨域的前提下将cookie也能传上去,这时候就需要设置另外一个头部,我们的cross origin变成

1
@CrossOrigin(origins = {"*"},allowCredentials = "true",allowedHeaders = "*")

使用了allowCredentials后Access-Control-Allow-Credentials头被设置成true,同时前端设置xhrField:{withCredential:true}后,浏览器在ajax请求内带上对应的cookie头部和后端的allowCredentials配合在一起解决跨域传递cookie的问题。由于课程中仅仅使用了get和post的方法,而这两个方法在跨域请求中都是可以用的,因此allowedHeaders可以不加。

问题3.404、405问题

404问题就是页面URL访问不到,之前异常处理的方式是定义BaseController层捕获,但是对于没有进入Controller层就无法处理。

405问题就是比如该传的url参数没有传,url绑定路由问题

解决方法:

定义GlobalExceptionHandler,类前添加注释@ControllerAdvice 面向切面编程,在配置文件application.properties中添加spring.mvc.throw-exception-if-no-handler-found=truespring.resources.add-mappings=false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@ControllerAdvice 
public class GlobalExceptionHandler{
@ExceptionHandler(Exception.class)
@ResponseBody
public CommonReturnType doError(...Excetion e)
{
if(ex instanceof BusinessException) {
//BusinessExcetion打印errCode和errMsg
}
if(ex instanceof ServletRequestBindingException){
//ServletRequestBindingException打印url绑定路由问题(405)
}
if(ex instanceof NoHandlerFoundException) {
//没有找到对应的访问路径(404)
}
}
}
文章作者: SkironYong
文章链接: https://skironyong.github.io/SkironYong.github.io/posts/7a689866.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SkironYong
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论