我在自己家里用近10台树莓派搭建了一个集群,平时在这个集群上学习一些技术知识。虽然这些机器性能不太好,但用起来比虚拟机和Docker要方便一些,应为虚拟机要装在自己电脑上,每次都要重启。
这个源代码是基于这个树莓派集群搭建的微服务的框架,采用Spring Cloud框架,包括了服务网关(Spring Cloud Gateway),服务器注册与发现(Spring Cloud Eureka),配置中心(Spring Cloud Config),服务调用(Spring Cloud OpenFeign),Redis数据库集群,MySQL数据库集群,RabbitMQ消息队列集群。
希望对想学习Spring Cloud微服务的同学有所帮助。
业务场景说明
整个系统模拟了一个十分简单的业务场景:会员购买产品生成订单。
业务提供三个微服务,产品服务、会员服务、订单服务。产品提供了产品新增、更新、列表、详情四个接口;会员提供了创建、详情、会员订单查询三个接口;订单提供了创建、支付、取消三个接口。
数据库采用三个独立的库:会员库、产品库、订单库。每个微服务访问自己的数据库,彼此独立。创建订单的时候,订单微服务会通过Rest调用产品和会员的接口,以检查产品和会员是否存在。
查询产品详情的时候,会使用Redis缓存。
订单支付了之后,会向消息队列发送一条消息,可以模拟消费端收到消息后发送邮件或短信的动作(暂未实现)。
当然,这只是做了一个十分简单的模拟场景,显示中的情况比上述场景要复杂得多。
产品微服务
数据库定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for prct_product
-- ----------------------------
DROP TABLE IF EXISTS `prct_product`;
CREATE TABLE `prct_product` (
`prct_id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`prct_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品名称',
`prct_desc` varchar(1023) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品描述',
`prct_price` decimal(10, 2) NOT NULL COMMENT '产品单价',
`stock` int NOT NULL COMMENT '库存',
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`created_by` varchar(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '创建人',
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`updated_by` varchar(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '更新人',
PRIMARY KEY (`prct_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
|
创建产品
1
|
POST http://xx.xx.xx.xx:port/product/
|
1
2
3
4
5
6
7
8
|
{
"prctName": "iphone 12",
"prctDesc": "<p class='comment-con'>描述信息</p>",
"prctPrice": 7999,
"stock": 9999,
"created_by": "liwenbo",
"updated_by": "liwenbo"
}
|
查询产品
1
|
GET http://liwenbo.net:59000/product?pageNo=1
|
其中pageNo是分页的参数。
产品详情
1
|
GET http://liwenbo.net:59000/product/{id}
|
其中{id}为产品的id。
更新产品
1
|
PUT http://liwenbo.net:59000/product/{id}
|
1
2
3
4
5
6
7
8
|
{
"prctId": 4,
"prctName": "iphone 12",
"prctDesc": "<p class='comment-con'>描述信息</p>",
"prctPrice": 7999,
"stock": 9999,
"updated_by": "liwenbo"
}
|
会员微服务
数据库定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for mbr_member
-- ----------------------------
DROP TABLE IF EXISTS `mbr_member`;
CREATE TABLE `mbr_member` (
`mbr_id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '会员ID',
`mbr_account` char(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '会员账号',
`mbr_mobile` char(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号',
`mbr_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
`mbr_gender` tinyint NOT NULL COMMENT '性`',
`balance` decimal(10, 2) NOT NULL COMMENT '账户余额',
`last_login_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后登录时间',
`last_login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最后登录IP',
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
PRIMARY KEY (`mbr_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
|
创建会员
1
|
POST http://liwenbo.net:59000/member/
|
示例数据
1
2
3
4
5
6
|
{
"mbrAccount":"liwenbo",
"mbrMobile": "18502788888",
"mbrName": "Liwenbo",
"mbrGender": 1
}
|
会员详情
返回示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
{
"timestamp": 1631361994718,
"message": "ok",
"code": 200,
"server": "127.0.1.1",
"data": {
"mbrId": 4,
"mbrAccount": "user_1631328296",
"mbrMobile": "804-576-4600",
"mbrName": "Israel Stamm xx",
"mbrGender": 1,
"balance": 0.0
}
}
|
会员订单
返回示例:
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
|
{
"timestamp": 1631362022699,
"message": "ok",
"code": 200,
"server": "127.0.1.1",
"data": [
{
"ordId": 24,
"ordCode": "1631347760954",
"mbrId": 3,
"prctId": 4,
"prctName": "iphone 402",
"ordQuantity": 1,
"ordPrice": 7999.0,
"ordStatus": "PAYED"
},
{
"ordId": 25,
"ordCode": "1631347767405",
"mbrId": 3,
"prctId": 4,
"prctName": "iphone 402",
"ordQuantity": 1,
"ordPrice": 7999.0,
"ordStatus": "NEW"
}
]
}
|
更新会员
示例数据:
1
2
3
4
5
6
7
|
{
"mbrId": 4,
"mbrAccount": "user_1631328296",
"mbrMobile": "{{$randomPhoneNumber}}",
"mbrName": "Israel Stamm xx",
"mbrGender": 1
}
|
订单服务
数据库定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for ord_order
-- ----------------------------
DROP TABLE IF EXISTS `ord_order`;
CREATE TABLE `ord_order` (
`ord_id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '订单ID',
`ord_code` char(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单编码,形如202106051147001',
`mbr_id` int NOT NULL COMMENT '会员ID',
`prct_id` int NOT NULL COMMENT '产品ID',
`prct_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '[冗余] 产品名称',
`ord_quantity` int NOT NULL COMMENT '购买数量',
`ord_price` decimal(10, 2) NOT NULL COMMENT '订单总价格',
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单创建时间',
`ord_status` tinyint NOT NULL COMMENT '订单状态, 0 - 未支付, 1 - 已支付, 2 - 已取消',
PRIMARY KEY (`ord_id`) USING BTREE,
UNIQUE INDEX `ord_code`(`ord_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
|
创建订单
示例数据:
1
2
3
4
5
6
7
|
{
"mbrId": 3,
"prctId": 4,
"prctName": "小米11",
"ordQuantity": 1,
"ordPrice": 3799
}
|
订单支付
1
|
GET /order/pay/?orderCode={code}
|
{code} 为订单的编号(不是id)
订单取消
1
|
GET /order/cancel/?orderCode={code}
|
{code} 为订单的编号(不是id)