高并发架构实战(一) 电商系统设计

转载请标注原文地址:https://blog.csdn.net/lilyssh/article/details/82753318

电商平台微服务架构设计

按照孢子框架要义对电商平台进行微服务架构设计。假设我们设计的目标是简易版淘宝。

项目源码地址

1. 需求分析

由于主要是学习技术,所以没对业务规划得过于详细和全面。大的功能分为三个,用户、商品、订单。主要需求如下:

分类 功能 质量
前端首页 注册 及时响应、安全性
  商品展示 及时响应、搜索引擎优化
  商品搜索 及时响应、搜索引擎优化
  秒杀购买商品 及时响应、安全性、可靠性
用户中心 我的订单 及时响应、安全性

2. 系统分析

要将需求进行系统分析,还需要有企业的运营目标做支持。假设我们运营目标是:

  • 用户量:3000万
  • 网站日访问量:3000万PV
  • 商品购买并发:1000 QPS
    我们按照上面的需求进行系统分析,首先按大的职责将职责相同的划分为一个服务。并且有了上面这个运营目标,所有功能需求都需要增加一项“质量”特性,那就是“高并发”,高并发会影响到所有设计。安全性和可靠性也会直接影响功能的技术实现,但并没有并发性影响性大。深入分析职责后把每一种功能的实现关键技术列出,如下:
分类 需求 实现子系统及服务 实现技术(软硬件结合)
前端首页 商品展示、商品搜索 商品系统 集群部署、高速缓存、分布式缓存、搜索引擎技术、静态化
  秒杀购买商品 订单系统 集群部署、消息队列、实时计算
用户中心 我的订单 订单系统 集群部署

如上所述,要支持运营目标的电商平台,可以分为大小几个服务和子系统。系统划分的依据一方面是职责,一方面跟实现技术有关,同一职责下实现技术不同会被划分为两个服务,比如购买商品和商品展示原本属于同一个大的领域,但其因为实现技术和质量要求不同需要划分为两个模块。这是因为微服务和传统SOA最大的区别就是技术实现的个性化,只有个性化才能做好做专,并节省成本。用户购买产品产生订单相关数据,订单数据关系到商品和用户两方面,如果是超高并发的系统,用户购买行为需要单独的服务。

3. 逻辑架构

逻辑视图采用以下方法建立。

按照职责、通用性、技能及工作量综合考虑和计量,平台逻辑架构设计如下图:

用户通过终端层发起请求,请求经由网关层nginx,路由到业务层,业务层通过业务逻辑判断,再访问数据访问层,数据访问层再通过数据库层获取到想要的内容。

  • 使用kafka,可优化下单性能,可以处理秒抢,或者异步处理一些事情,如送下单后优惠券。
  • 使用Elasticsearch,可优化商品查询,商品一般数据量比较大,用户经常模糊查询,近义词要能查出来,且要求及时响应,Elasticsearch正好能解决这种难题,所以非它莫属啦!
  • 使用mongoDB,可优化订单列表。后台订单经常按照时间查询订单列表。
  • 使用redis,可优化库存管理,以免在秒抢时,出现多用户同时抢到同一商品的情况。

    4. 开发架构

    系统所需的工程:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    ~/workspace/gitee/high-concurrency on master ⌚ 9:54:01
    $ tree -I target
    .
    ├── common //公共模块 [cn.lilyssh.common]
    ├── config-server //分布式配置中心服务 [cn.lilyssh.config]
    ├── goods //商品服务
    │   ├── goods-api //实体类和接口定义层 [cn.lilyssh.goods.api]
    │   ├── goods-consumer //接口访问层 [cn.lilyssh.goods.consumer]
    │   └── goods-provider //数据访问层 [cn.lilyssh.goods.provider]
    ├── order //订单服务
    │   ├── order-api //实体类和接口定义层 [cn.lilyssh.order.api]
    │   ├── order-consumer //接口访问层 [cn.lilyssh.order.consumer]
    │   └── order-provider //数据访问层 [cn.lilyssh.order.provider]
    └── user //用户服务
    ├── user-api //实体类和接口定义层 [cn.lilyssh.user.api]
    ├── user-consumer //接口访问层 [cn.lilyssh.user.consumer]
    └── user-provider //数据访问层 [cn.lilyssh.user.provider]

开发环境:

编码 工具 版本控制 JDK 开发环境
UTF-8 IDEA Git JDK1.8 Maven 3

开发技术选型:

分类 实现 分类 实现
MVC框架: Spring Boot 2.0.4 Rest接口实现: Spring MVC Rest
持久层: mybatisplus-spring-boot 1.0.5 数据库连接池: druid 1.1.10
分库分表: mycat 数据库: MySql 5.6
缓存框架: Redis、mongoDB 搜索引擎: Elasticsearch
网关: Nginx、Kong(纯属学习使用) API 开发: swagger
RPC框架: dubbo-spring-boot 2.0.0 注册中心: zookeeper
日志管理: SLF4J 消息队列: Kafka
分布式配置中心: spring cloud config 部署: Jenkins

1).微服务的架构

每个微服务的架构基本上是一致的。拿order来说,分为 order-api、order-consumer、order-provider。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
~/workspace/gitee/high-concurrency/order on master ⌚ 11:18:53
$ tree -I target
.
├── order-api
│   ├── pom.xml
│   └── src
│   └── main
│   └── java
│   └── cn.lilyssh.order.api
│   ├── model
│   │   ├── request
│   │   │   ├── OrderInsertReq.java
│   │   │   └── OrderQueryReq.java
│   │   └── response
│   │   └── OrderQueryResp.java
│   └── service
│   └── OrderServiceApi.java
├── order-consumer
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── cn
│   │   └── lilyssh
│   │   └── order
│   │   └── consumer
│   │   ├── OrderConsumerApplication.java
│   │   ├── controller
│   │   │   └── OrderController.java
│   │   └── service
│   │   └── OrderService.java
│   └── resources
│   ├── application.yml
│   └── bootstrap.yml
├── order-provider
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── cn
│   │   └── lilyssh
│   │   └── order
│   │   └── provider
│   │   ├── OrderProviderApplication.java
│   │   ├── dao
│   │   │   ├── entity
│   │   │   │   └── OrderEntity.java
│   │   │   ├── mapper
│   │   │   │   └── OrderMapper.java
│   │   │   └── repository
│   │   │   └── OrderRepository.java
│   │   └── service
│   │   └── OrderService.java
│   └── resources
│   ├── application.yml
│   └── bootstrap.yml
└── pom.xml

  • api项目 提供 前端与consumer层 以及 consumer层与provider层 进行数据传递的实体类和接口xxServiceApi,实体类分为请求类和响应类,这两个包中又根据不同的业务需求分为不同的实体类。实体和接口访问层虽然属于“层”,但它们并不单独发布,而是使用Jar包类库的方式提供给其它服务调用,是逻辑上的层。其他任意项目可dependency此api模块,并调用此api模块提供的接口。
  • consumer 项目中包含controller层和service层,controller给前端提供rest接口,它调用service的方法,service中写业务逻辑,且调用api模块的接口ServiceApi。
  • provider 项目的主要任务是为api项目的接口xxServiceApi提供实现,即xxService,进行数据访问,分为entity,mapper,repository,entity中存放与数据库表字段一一映射的实体类,用于与数据库进行数据传递的交互。mapper由于继承了mybatisplus的BaseMapper,所以本身提供了增删改查等基本方法,如需自定义方法,可自行添加。repository可对业务逻辑进行进一步的拆解。
  • 配置文件application.yml中存放与其他项目不可公用的配置,如端口,其他公用的配置放在分布式配置中心,bootstrap.yml文件中设置分布式配置中心服务地址,和需要下载的配置文件。由于consumer和provider中都用到了配置文件,所以把这点拿出来单独说。

    2).分布式配置中心

    我们来看一下配置服务config-server项目的目录结构:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ~/workspace/gitee/high-concurrency/config-server on master ⌚ 16:10:35
    $ tree -I target
    ├── pom.xml
    └── src
    └── main
    ├── java
    │   └── cn
    │   └── lilyssh
    │   └── config
    │   └── ConfigApplication.java
    └── resources
    └── application.yml

application.yml中用来设置配置仓库地址。

3).公用的项目

即common项目的目录结构。common项目主要是放一些工具类、异常的统一捕获处理,还有consumer对前端返回结果的统一封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
~/workspace/gitee/high-concurrency/common on master ⌚ 16:20:17
$ tree -I target
.
├── pom.xml
└── src
└── main
├── java
│   └── cn
│   └── lilyssh
│   └── common
│   ├── date
│   │   └──DateUtil.java
│   ├── exception
│   │   └── ExceptionAdviceHandler.java
│   ├── result
│   │   ├── Result.java
│   │   ├── ReturnCode.java
│   │   └── ReturnCodeInterFace.java
│   └── validate
│   └── ValidateGroup.java
└── resources
└── META-INF
└── spring.factories

5. 表结构

用户表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`uuid` varchar(45) DEFAULT NULL,
`user_name` varchar(20) DEFAULT NULL,
`password` varchar(45) DEFAULT NULL,
`real_name` varchar(20) DEFAULT NULL,
`sex` bit(1) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`phone` int(11) DEFAULT NULL,
`email` varchar(45) DEFAULT NULL,
`status` tinyint(1) DEFAULT NULL,
`last_login_ip` varchar(45) DEFAULT NULL,
`last_login_time` datetime DEFAULT NULL,
`id_type` int(11) DEFAULT NULL,
`id_number` varchar(45) DEFAULT NULL,
`address` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

订单表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TABLE `order` (
`id` int(11) NOT NULL,
`user_id` int(11) DEFAULT NULL,
`user_uuid` varchar(45) DEFAULT NULL,
`goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
`payment` decimal(14,2) DEFAULT NULL COMMENT '实付金额',
`pay_type` tinyint(1) DEFAULT NULL COMMENT '支付类型:1 在线支付 2 货到付款',
`post_fee` decimal(6,2) DEFAULT NULL,
`status` tinyint(2) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`pay_time` datetime DEFAULT NULL,
`cosign_time` datetime DEFAULT NULL COMMENT '发货时间',
`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
`shipping_name` varchar(20) DEFAULT NULL COMMENT '物流名称',
`shipping_code` varchar(45) DEFAULT NULL COMMENT '物流单号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

商品表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE `goods` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
`goods_name` varchar(45) NOT NULL COMMENT '商品名称',
`stock` int(11) NOT NULL,
`logo` varchar(150) NOT NULL DEFAULT '' COMMENT '商品logo',
`sm_logo` varchar(150) NOT NULL DEFAULT '' COMMENT '商品缩略图logo',
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格',
`goods_desc` longtext COMMENT '商品描述',
`is_on_sale` tinyint(3) NOT NULL DEFAULT '1' COMMENT '是否上架:1:上架,0:下架',
`is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否已经删除,1:已经删除 0:未删除',
`create_time` int(10) NOT NULL COMMENT '添加时间',
`update_time` int(10) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

本文由 lilyssh创作。可自由转载、引用,但需署名作者且注明文章出处。


当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器