海量订单系统微服务开发:使用MongoDB支持海量数据

admin mongodb 2022-11-11 33 0

海量订单系统微服务开发

订单系统是电商平台中一个非常重要的组成部分,而且它还是一个具有巨大流量和高并发访问的系统,与订单相关的服务涉及库存、支付、物流等。在设计订单系统时,我们选择使用支持海量数据的NoSQL 数据库MongoDB,配合使用反应式的Spring Data MongoDB,实现高并发设计。

本章实例项目代码可从本书源代码中下载,在IDEA 中检出,或通过页面直接下载使用。检出后请获取分支版本V2.1。在这个分支中包含以下几个模块:

order-object:订单公共对象设计。

order-restapi:订单微服务接口应用设计。

order-web:订单后台管理应用设计。

使用MongoDB支持海量数据

MongoDB是一个分布式数据库,对于开发调试,我们只需一个单机版即可。

使用 Mongo插件

如果使用的是IDEA开发工具,则为了方便查询数据库,也可以安装一个Mongo客户端插件。打开 IDEA 设置,在插件上搜索Mongo进行安装即可,安装完成后,如图8-1所示。

安装插件之后,就可以在设置中通过Other Settings连接 MongoDB,使用客户端来查询数据。图8-2是一个本地数据库连接的配置实例。

MongoDB数据源相关配置

我们在模块 order-restapi中进行MongoDB的设计,首先在项目对象模型pom.xml中引入相关依赖引用,代码如下所示:

这里引用的是反应式Spring Data MongoDB组件,它可以支持无事务的高并发非阻塞的异步请求调用。

在模块的配置文件 applicaption.yml 中,设定连接MongoDB服务器的数据源配置,代码如下所示:

这里是开发环境的一个本地连接的简单配置,如果是生产环境,则可以设置用户名和密码,并且指定使用的数据库名称。

这里是开发环境的一个本地连接的简单配置,如果是生产环境,则可以设置用户名和密码,并且指定使用的数据库名称。

因为MongoDB使用了格林尼治时间(GMT),所以为了显示东八区的正确时间,我们在数据查询时做了“GMT+8”的配置。

订单文档建模

订单数据主要由订单及其明细数据组成,由于订单从生成开始到交易结束,会发生一系列状态变化,而这些状态一般可以固定下来,所以可以使用一个枚举类来实现。

订单及其明细数据

订单文档的建模由Order类实现,代码如下所示:

在上面的代码中,各个字段的属性已经有注释说明。注解@Data为各个字段自动生成getter/setter 方法。另外,注解@Id可由数据库自动生成ID,并且是文档的唯一索引;注解@Indexed为订单编号创建了一个索引,从而提高了以订单号进行查询的性能。

订单明细的定义在类 OrderDetail中,代码如下所示:

在订单明细设计中,对于商品名称和图片数据等字段,使用冗余设计的方法,可以减少对库存管理中商品接口的调用。

订单明细虽然是一个独立的类,但它不是一个独立的文档。订单明细将与订单一起组成一个文档。这一点与关系数据库的设计不同,如果是MySQL,则订单明细会使用另一个表结构,在查询时再使用关联关系获取数据,这样一来必将是很耗性能的。

订单状态枚举

订单状态在订单文档中保存时是一个整型字段,它对应订单的一个状态信息。一般来说,这种状态都较为固定,所以我们使用一个枚举定义StatusEnum来实现,这样在订单的查询设计中,就可以对各个订单状态进行转换,同时在订单的编辑中也可以列举出所有状态进行选择。代码如下所示:

反应式 MongoDB编程设计

反应式编程设计是Spring Boot 2.0及以上版本提供的一个新功能,这是一个非阻塞的异步调用设计,可以适应高并发的请求调用。在反应式编程中有两个基本概念:Flux和 Mono。Flux表示的是包含0到N个元素的异步序列,在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。当消息通知产生时,订阅者中对应的方法 onNext()、onComplete()和 onError()会被调用。Mono表示的是包含0或者1个元素的异步序列,在该序列中,包含的消息通知的类型与Flux相同。

基于Spring Data的存储库接口设计

Spring Data MongoDB和Spring Data一样,有一个统一的规范设计。前面我们在Spring DataJPA中使用过这种规范,所以接下来的代码,读者会觉得很熟悉。

订单的存储库接口是 OrderRepository,实现代码如下所示:

动态分页查询设计

在存储库接口设计中,可以使用注解@Query灵活地定义复杂的查询。对于订单的分页查询,我们使用了如下所示的动态查询设计:

这里我们提供了几个查询条件,它们分别是:用户编号(userid) 、商家编号(merchantid)、订单状态(status)和订单创建日期(created)。这些查询条件如果值为空,则忽略不计,否则按提供的数值进行限定查询。其中,对于订单的创建日期的条件查询,使用了大于或等于(Sgte)开始日期和小于或等于($Ite)结束日期的条件限制。最后,还可以对查询结果进行排序。

针对分页的查询接口声明,我们在服务类OrderService中使用了如下所示的设计:

首先对订单创建日期进行倒序排序,然后使用查询对象OrderQo传输查询参数,并对查询结果使用分页方式输出。需要注意的是,这里的输出结果是一个异步序列Flux,它包含了订单的列表数据。如果是单个对象的数据输出,则可以使用异步序列Mono,如上面代码中对订单总数查询的输出使用了Mono序列。

Mongo单元测试

针对前面的纯数据库方面的设计,我们可以使用一个单元测试进行验证。一个生成订单数据的测试用例如下所示:

在这个测试用例设计中生成了一个订单,并为这个订单的明细数据生成了两个记录。如果打开MongoDB的调试日志,就可以从控制台中看到如下输出:

另外,为了更加清晰地看到测试结果,我们还在日志输出中通过“返回结果:0}”将这条生成的订单信息打印出来。

这时,也可以借助MongoDB的客户端查询测试的结果。

因为测试是在线程中执行反应式的数据操作,所以对于异步序列,必须在最后执行类似block()这样的阻塞处理,才能完成反应式的调用过程,否则不可能达到预期的结果。

在接下来的各种增删改查的测试用例设计中,最后都进行了阻塞处理设计。例如,对分页查询的测试,我们使用如下所示的设计:

执行这个测试用例后,可以在控制台日志中看到 MongoDB的日志输出,如下所示:

因为这里没有提供查询参数的数值,所示这是一个没有条件限制的查询,它会按分页结果查出订单的所有记录。

当我们为这些查询参数指定数据时,即可看到如下所示的查询日志输出:

本文给大家讲解的内容

SpringCloud微服务架构实战:海量订单系统微服务开发,使用MongoDB支持海量数据、 订单文档建模、反应式MongoDB编程设计、Mongo单元测试

下篇文章给大家讲解的是SpringCloud微服务架构实战:海量订单系统微服务开发,订单接口微服务开发、订单的分布式事务管理、 订单管理后台微服务开发、集成测试;

觉得文章不错的朋友可以转发此文关注小编;

感谢大家的支持!

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

评论