数据实体联系
基于需求分析得到的具体业务,按领域划分为七个小模块,每个模块中划分出相应的实体、事件,如下是关键数据实体-联系图:
- 会员,车辆,月卡(绑定手机号,录入车辆,开月卡)
- 车位,闸机(车辆停靠、车辆离开)
- 积分(签到、兑换)
- 计费规则(入场、出场)
- 交易流水(支付、充值)
- 消息(推送)
- 洗车
业务模块设计
按照前面的需求分析,数据实体联系图,设计的微服务模块如下:
- 会员服务,包括会员信息、车辆信息、会员月卡
- 基础资源服务,包括车位、闸机,车辆停靠记录
- 计费服务,车辆出入场记录,计费规则
- 积分服务,积分兑换,会员积分,会员签到得积分
- 财务服务,支付流水,充值流水,财务统计
- 消息服务,记录通知内容
- 洗车服务,积分兑换的洗车券去场内洗车
存储设计
微服务架构风格的一个好处,是持久性的封装。我们可以根据每个服务的需要,去选择不同的持久化技术。根据每种数据类型的特点而去选择数据存储的方法,也就是混合持久化,结构化存储与非结构化存储混合使用。不同服务间使用不同的存储模型,单一服务中也可以使用混合存储。既然要采用微服务化结构,从独立开发、运行、部署和运维都是单独的小应用。每个小应用内部业务逻辑处理,到数据库访问,以及数据库都是独立的。
依据本案例的业务场景,我们拆分为七个子存储库,分别为:
- park_member——会员服务库
- park_resource——停车场资源服务库
- park_charging——计费服务库
- park_card——积分服务库
- park_finance——财务服务库
- park_message——消息服务库
- park-carwash——洗车服务库
数据库文件见项目目录
初始化数据
有了初步数据库的模型,需要初始化一部分数据进去,比如计费规则、闸机信息,车位信息。
闸机数据
1
2
3
4
INSERT INTO `brake` VALUES ('4edb0820241041e5a0f08d01992de4c0', 'ct1', '入场口', 'admin', '2019-12-27 11:37:22', NULL, '2019-12-27 11:37:22', NULL, 0, 1);
INSERT INTO `brake` VALUES ('989170c529a348b3b93bf2a4653e8ea9', 'ct2', '入场口', 'admin', '2019-12-27 11:37:45', NULL, '2019-12-27 11:37:45', NULL, 0, 1);
INSERT INTO `brake` VALUES ('e489029055654bccb3cd601f0be71c41', 'ct3', '出场口', 'admin', '2019-12-27 11:37:36', NULL, '2019-12-27 11:37:36', NULL, 0, 1);
INSERT INTO `brake` VALUES ('f726873ed17441ea8dfbf78381bcde78', 'ct4', '出场口', 'admin', '2019-12-27 11:37:41', NULL, '2019-12-27 11:37:41', NULL, 0, 1);
车位数据
1
2
3
4
5
INSERT INTO `stall` VALUES ('004ac347b94e42bb8f0f6febd3265e35', 'P336', 0, 'admin', '2019-12-27 11:42:03', NULL, '2019-12-27 11:42:03', NULL, 0, 1);
INSERT INTO `stall` VALUES ('008773e089664ce49607c86b89dd8c0f', 'P250', 0, 'admin', '2019-12-27 11:42:03', NULL, '2019-12-27 11:42:03', NULL, 0, 1);
INSERT INTO `stall` VALUES ('0110ef02554f46ce91a3eeec6ecf2f95', 'P224', 0, 'admin', '2019-12-27 11:42:03', NULL, '2019-12-27 11:42:03', NULL, 0, 1);
INSERT INTO `stall` VALUES ('014f1f2b972e4e0092d749a7437f824d', 'P577', 0, 'admin', '2019-12-27 11:42:04', NULL, '2019-12-27 11:42:04', NULL, 0, 1);
INSERT INTO `stall` VALUES ('019f4aa0c22849e1a5758aaa33b855df', 'P229', 0, 'admin', '2019-12-27 11:42:03', NULL, '2019-12-27 11:42:03', NULL, 0, 1);
计费规则
1
2
3
4
INSERT INTO `charging_rule` VALUES ('41ed927623cf4a0bb5354b10100da992', 0, 30, 0, 'admin', '2019-12-27 11:26:08', NULL, '2019-12-27 11:26:08', '30 分钟内免费', 0, 1);
INSERT INTO `charging_rule` VALUES ('41ed927623cf4a0bb5354b10100da993', 31, 120, 5, 'admin', '2019-12-27 11:26:12', NULL, '2019-12-27 11:26:12', '2 小时内,5 元', 0, 1);
INSERT INTO `charging_rule` VALUES ('4edb0820241041e5a0f08d01992de4c0', 121, 720, 10, 'admin', '2019-12-27 11:34:06', NULL, '2019-12-27 11:34:06', '2 小时以上 12 小时以内,10 元', 0, 1);
INSERT INTO `charging_rule` VALUES ('7616fb412e824dcda41ed9367feadfda', 721, 1440, 20, 'admin', '2019-12-27 13:35:37', NULL, '2019-12-27 13:35:37', '12 时至 24 时,20 元', 0, 1);
非结构化存储
主要使用 Redis 中间件来存储可用车位的实时性信息,计费规则信息等热数据。
架构设计
没有最优的架构,只有最合适的架构,一切系统设计原则都要以解决业务问题为最终目标,并随着业务的发展,不断进行迭代演进。经过上面业务模块、存储模型的划分,基本的代码架构已经清晰可见。综合业务模块、微服务架构特性,输出功能架构设计图。
基于总体功能架构图,使用特定的功能组件即可实现相应的功能。前期也提到,Spring Cloud 全家桶中囊括了很多组件,开箱即用,这对快速上手微服务开发提供了极大的便利。同时,再融入时常开发实践一些常用的高效工具来提升编码效率如 Lombok,MBG 等。