转载请标注原文地址: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
18
19 1~/workspace/gitee/high-concurrency on master ⌚ 9:54:01
2$ tree -I target
3.
4├── common //公共模块 [cn.lilyssh.common]
5├── config-server //分布式配置中心服务 [cn.lilyssh.config]
6├── goods //商品服务
7│ ├── goods-api //实体类和接口定义层 [cn.lilyssh.goods.api]
8│ ├── goods-consumer //接口访问层 [cn.lilyssh.goods.consumer]
9│ └── goods-provider //数据访问层 [cn.lilyssh.goods.provider]
10├── order //订单服务
11│ ├── order-api //实体类和接口定义层 [cn.lilyssh.order.api]
12│ ├── order-consumer //接口访问层 [cn.lilyssh.order.consumer]
13│ └── order-provider //数据访问层 [cn.lilyssh.order.provider]
14└── user //用户服务
15 ├── user-api //实体类和接口定义层 [cn.lilyssh.user.api]
16 ├── user-consumer //接口访问层 [cn.lilyssh.user.consumer]
17 └── user-provider //数据访问层 [cn.lilyssh.user.provider]
18
19
开发环境:
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
58
59 1~/workspace/gitee/high-concurrency/order on master ⌚ 11:18:53
2$ tree -I target
3.
4├── order-api
5│ ├── pom.xml
6│ └── src
7│ └── main
8│ └── java
9│ └── cn.lilyssh.order.api
10│ ├── model
11│ │ ├── request
12│ │ │ ├── OrderInsertReq.java
13│ │ │ └── OrderQueryReq.java
14│ │ └── response
15│ │ └── OrderQueryResp.java
16│ └── service
17│ └── OrderServiceApi.java
18├── order-consumer
19│ ├── pom.xml
20│ └── src
21│ └── main
22│ ├── java
23│ │ └── cn
24│ │ └── lilyssh
25│ │ └── order
26│ │ └── consumer
27│ │ ├── OrderConsumerApplication.java
28│ │ ├── controller
29│ │ │ └── OrderController.java
30│ │ └── service
31│ │ └── OrderService.java
32│ └── resources
33│ ├── application.yml
34│ └── bootstrap.yml
35├── order-provider
36│ ├── pom.xml
37│ └── src
38│ └── main
39│ ├── java
40│ │ └── cn
41│ │ └── lilyssh
42│ │ └── order
43│ │ └── provider
44│ │ ├── OrderProviderApplication.java
45│ │ ├── dao
46│ │ │ ├── entity
47│ │ │ │ └── OrderEntity.java
48│ │ │ ├── mapper
49│ │ │ │ └── OrderMapper.java
50│ │ │ └── repository
51│ │ │ └── OrderRepository.java
52│ │ └── service
53│ │ └── OrderService.java
54│ └── resources
55│ ├── application.yml
56│ └── bootstrap.yml
57└── pom.xml
58
59
- 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
13
14 1~/workspace/gitee/high-concurrency/config-server on master ⌚ 16:10:35
2$ tree -I target
3├── pom.xml
4└── src
5 └── main
6 ├── java
7 │ └── cn
8 │ └── lilyssh
9 │ └── config
10 │ └── ConfigApplication.java
11 └── resources
12 └── application.yml
13
14
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
24
25 1~/workspace/gitee/high-concurrency/common on master ⌚ 16:20:17
2$ tree -I target
3.
4├── pom.xml
5└── src
6 └── main
7 ├── java
8 │ └── cn
9 │ └── lilyssh
10 │ └── common
11 │ ├── date
12 │ │ └──DateUtil.java
13 │ ├── exception
14 │ │ └── ExceptionAdviceHandler.java
15 │ ├── result
16 │ │ ├── Result.java
17 │ │ ├── ReturnCode.java
18 │ │ └── ReturnCodeInterFace.java
19 │ └── validate
20 │ └── ValidateGroup.java
21 └── resources
22 └── META-INF
23 └── spring.factories
24
25
5. 表结构
用户表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 1CREATE TABLE `user` (
2 `id` int(11) NOT NULL,
3 `uuid` varchar(45) DEFAULT NULL,
4 `user_name` varchar(20) DEFAULT NULL,
5 `password` varchar(45) DEFAULT NULL,
6 `real_name` varchar(20) DEFAULT NULL,
7 `sex` bit(1) DEFAULT NULL,
8 `age` int(11) DEFAULT NULL,
9 `phone` int(11) DEFAULT NULL,
10 `email` varchar(45) DEFAULT NULL,
11 `status` tinyint(1) DEFAULT NULL,
12 `last_login_ip` varchar(45) DEFAULT NULL,
13 `last_login_time` datetime DEFAULT NULL,
14 `id_type` int(11) DEFAULT NULL,
15 `id_number` varchar(45) DEFAULT NULL,
16 `address` varchar(45) DEFAULT NULL,
17 PRIMARY KEY (`id`)
18) ENGINE=InnoDB DEFAULT CHARSET=utf8;
19
20
订单表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 1CREATE TABLE `order` (
2 `id` int(11) NOT NULL,
3 `user_id` int(11) DEFAULT NULL,
4 `user_uuid` varchar(45) DEFAULT NULL,
5 `goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
6 `payment` decimal(14,2) DEFAULT NULL COMMENT '实付金额',
7 `pay_type` tinyint(1) DEFAULT NULL COMMENT '支付类型:1 在线支付 2 货到付款',
8 `post_fee` decimal(6,2) DEFAULT NULL,
9 `status` tinyint(2) DEFAULT NULL,
10 `create_time` datetime DEFAULT NULL,
11 `update_time` datetime DEFAULT NULL,
12 `pay_time` datetime DEFAULT NULL,
13 `cosign_time` datetime DEFAULT NULL COMMENT '发货时间',
14 `end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
15 `close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
16 `shipping_name` varchar(20) DEFAULT NULL COMMENT '物流名称',
17 `shipping_code` varchar(45) DEFAULT NULL COMMENT '物流单号',
18 PRIMARY KEY (`id`)
19) ENGINE=InnoDB DEFAULT CHARSET=utf8;
20
21
商品表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1CREATE TABLE `goods` (
2 `id` mediumint(8) NOT NULL AUTO_INCREMENT,
3 `goods_name` varchar(45) NOT NULL COMMENT '商品名称',
4 `stock` int(11) NOT NULL,
5 `logo` varchar(150) NOT NULL DEFAULT '' COMMENT '商品logo',
6 `sm_logo` varchar(150) NOT NULL DEFAULT '' COMMENT '商品缩略图logo',
7 `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格',
8 `goods_desc` longtext COMMENT '商品描述',
9 `is_on_sale` tinyint(3) NOT NULL DEFAULT '1' COMMENT '是否上架:1:上架,0:下架',
10 `is_delete` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否已经删除,1:已经删除 0:未删除',
11 `create_time` int(10) NOT NULL COMMENT '添加时间',
12 `update_time` int(10) NOT NULL COMMENT '修改时间',
13 PRIMARY KEY (`id`)
14) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15
16