Java生鲜电商系统设计(小程序/APP)

2024-05-09
来源:网络整理

Java生鲜电商平台-微服务生鲜电商系统设计(小程序/APP)

Java生鲜电商平台-微服务生鲜电商系统设计(小程序/APP)

注:本文主要讲解微服务生鲜电商系统的设计和架构。 希望对大家有所帮助。

实际业务场景下如何设计电子商务系统?

我们简单想象一下,既然是一个电商系统,有用户去购买,那么就必须有一个用户模块。 买东西不是西北风。 购买的必须是产品。 如果保存购物车,则必须有产品模块。 酒吧。 该产品必须有库存。 库存暂时应与产品存放在一起。 暂时不用担心仓储物流。 就当它是一个虚拟产品吧。 反正标题并没有说它不能是虚拟产品。 _如果购买成功,那么一定有订单。 添加订单模块。 下订单后您必须付款。 如果你不付钱,为什么有人会给你东西? 那么一定要有支付模块。

简单粗暴,四个模块,如上图:

好了,几个模块就做好了,加上订单流程图:

等等,标题好像说是微服务。 既然是微服务,就涉及到服务拆分的问题。

DDD 领域驱动设计

我刚刚整理了模块。 既然是微服务,就需要对服务进行拆分。 服务如何拆分?

好像按照我刚刚整理的模块来划分是可以的,但是又显得我很不专业。 听说现在很多人用DDD(领域驱动设计)来指导微服务的拆分。

参考DDD的设计以及DDD官方的架构草图,整体架构分为四层:

微服务与DDD相结合

然而,对于领域设计来说,代码层其实并不是最重要的。 最重要的是如何划分领域、界定边界。

对于微服务来说,从业务角度来划分各个业务是非常合适的,划分各个业务板块,微服务+DDD。 个人感觉,首先考虑从微服务的角度来划分大的业务模块。 每个微服务应该是一个可以独立部署、各司其职的。

简单来说,就是在微服务实际开发中,结合DDD的思想,划分出所有属于你的区域。

实施 DDD 的关键

第一点是使用传递语言构建所有聚合、实体和值对象。

第二点是最关键的“建模”:

构建电子商务系统的上下文图

首先,我们来确定我们战略的核心领域是什么? 我们的目的是什么?

作为一个电子商务系统,我们的核心一定是卖出更多的商品,获得更多的订单,赚取更多的利润,所以销售可以是我们的核心领域之一。

这是一个明确的核心领域:

确定核心子领域后,根据对该领域的理解来划分各个上下文,然后根据上下文确定其他相关领域。

初步可以看到围绕核心销售领域有几大块内容,包括价格、销售方式、购买方式、已购买。

然后我们还划分了支撑核心域的子域。 核心域由产品域和用户域支撑。 一般域包括订单域、物流域、支付域。

回到我们的正题,我们这次没有购物车,也没有个人会员销售价格。 让我们去掉一些上下文并创建一个映射。

领域驱动设计看似简单,但实际上实现起来却很困难,因为每个环节都需要相应领域专家的参与或指导,才能设计出最真实的上下文映射图。

而且我们可能会比未来的数据驱动的开发模式花费更多的精力,但从整体项目控制表现来看,领域比数据驱动更抽象、更顶层设计,这一点从项目的变化情况就可以看出。互联网。 更远。

我们将微服务分为5个领域,即:

完美,接下来就可以开始开发了。 ^?_?^

等等,兵马未动,粮草先行;兵马未动,粮草先行;兵马未动,粮草先行。 在移动代码之前,先走图片,先绘制时序。

时序图

一个简单的订单流程涵盖多个领域:

完美,现在您可以开发微服务了。 ^?_?^

等等,微服务的技术栈还没有选定。

微服务技术栈选择

服务已经拆分,时序图也已经画好了。 我们可以开始我们的微服务之旅了。 目前主流的微服务有阿里巴巴的名优和全家,还有新浪的。

我比较熟悉的还是这两个,我都用过。 我应该选择哪一个?

因为之前用过,所以简单粗暴的总结一下。 它很久以前就开始使用了。 当时微服务还没有现在这么流行,很多理论体系也并不完善。 它更像是一套RPC集成框架,更倾向于微服务架构的生态。

与之相比,可以说是一套完整的微服务解决方案,功能超强。

打个比方,微服务架构就像组装一台计算机,每个环节都具有很高的自由度。 更像是品牌机。

基于无大惊小怪、简单快捷,更倾向于选择。 好的,我们来决定技术栈并使用它。 这是一个愉快的决定。

等等,如果你这么仓促地决定使用微服务,那你不是需要先了解一下微服务的优缺点吗?

微服务的优点和缺点

既然选择了微服务,就必须知道微服务的优缺点,尤其是缺点。 引入微服务就相当于引入一个复杂的系统。 必须提前清楚地了解复杂系统带来的各种挑战。

利润

① 强大的模块化边界

我们知道,模块化是软件架构和软件设计中非常重要的一点。 当我们第一次编写程序来制作软件时,我们使用类来进行模块化。 后来我们开始使用组件或者类库来做模块化。 您可以在项目中进行复用,并与其他团队共享使用。

微服务比组件级别高一级。 它们以服务的形式模块化。 每个团队独立启动和维护自己的服务,并且有明确的边界。

开发出一个服务后,其他团队可以直接调用该服务。 不需要通过Jar或源代码来共享组件,因此微服务的边界相对清晰。

② 可独立部署 ③ 技术多样性

缺点(或挑战)

①分布式复杂性

过去,单体应用程序只是一个应用程序。 熟悉单体应用程序架构的人可以很好地控制整个单体应用程序。

但对于分布式系统来说,微服务实现后,可能涉及到几十个服务,有些大公司可能涉及到上百个服务。 服务通过相互沟通实现业务。

那么这个时候整个系统就变得非常复杂,普通的开发者或者团队无法理解整个系统是如何工作的。 这就是分布式带来的复杂性。

②最终一致性

微服务的数据采用去中心化的方式管理。 每个团队都有自己的数据源和数据副本。 例如,A队有订单数据,B队也有订单数据。 如果A团队修改了订单数据,是否应该同步到B团队? 数据呢?

这就涉及到数据一致性的问题。 如果一致性问题解决不好,可能会导致数据不一致,这在业务上是不可接受的。

③运维复杂度

过去运维需要管理机器+单块应用。 分布式系统和单块应用的区别在于,分布式系统需要很多服务,并且服务之间是相互协作的。

那么分布式系统的资源、容量规划、监控都是非常具有挑战性的,还有整个系统的可靠性和稳定性。

只有清楚地认识微服务带来的挑战,知道山有猛虎、山有猛虎,才能真正有资格应对挑战。 最重要的是清楚地了解陷阱以及如何避免它们。

完美,既然您了解了微服务带来的好处和挑战,就可以开始开发了。 ^?_?^

等等,微服务还没有逻辑分层。

如何在微服务中实现逻辑分层

目前我们的微服务中有几个服务,分别是订单、产品、用户。

如果客户想查看“我的订单”界面; 如果假设客户端是PC,则需要请求三次接口,分别连接订单、产品、用户三个服务。 分别拿到这三个调用数据后,就会进行这三个调用。 数据被整合并输出以进行显示。

要知道PC通过外部网络调用后端服务,这无疑大大增加了网络开销,也让PC端变得更加复杂。

假设中间增加一层作为聚合服务层,这样可以减少网络开销。 由于数据是通过微服务的内网进行内部传输的,也让PC端的业务变得更加简单。

图中的“PC聚合服务”也是一个微服务,但属于聚合服务的中间层。 我们在逻辑上将微服务分为2层:

①微服务基础服务层

基础服务一般属于互联网平台的基础支撑服务。 例如,电子商务网站的基础服务包括订单服务、产品服务、用户服务等。

这些是相对基本和原子的。 它们下沉到企业基础设施的底层,向下承担存储,向上提供业务能力。 有的企业把它们称为基础服务、中间层服务、公共服务,就成了中间层服务。 我们暂时将它们称为基本服务。

②微服务聚合服务层

已经有了可以提供业务能力的基础服务。 为什么我们需要聚合服务? 因为我们的接入终端不同,比如App、H5、PC等,他们看似调用的数据大致相同,但实际上有很多差异。

比如PC端需要展示更多的信息,App端需要对信息进行修剪等等。一般来说,底层服务比较常见,基础服务应该向外界输出相对统一的服务,并且做好抽象工作。

但为了访问不同的外部应用程序和PC,我们需要做出不同的适配。 这时候我们就需要一个层来做聚合和裁剪的工作。

例如,如果在PC端和App端显示一个产品详细信息,则PC端可能会显示更多信息,而App则需要对信息进行裁剪。

如果基础服务直接向PC和App开放接口,那么基础服务还需要进行各种配置,不利于基础服务的抽象。

因此,我们在基础层之上添加聚合服务层。 该层可以针对 PC 和应用程序进行适当配置并进行相应定制。

然后,我们的微服务中又添加了另一个服务,它是聚合服务。

好了,现在你可以玩得开心了……

等等,这似乎不对。 如果是单块应用并且添加交易的话应该没问题。 但这是分布式的,所以我可能不得不考虑添加分布式事务。

分布式交易

我们先理清楚创建订单和紧固件库存模块的关系:

可以发现,因为有了微服务,我们有了分布式服务。 随着每个数据库变得分布式,每个数据库不一定存在于同一台物理机中。

这时单个数据库的ACID已经不能适应这种情况了。 在这种集群中,几乎很难保证集群的ACID,或者即使能够实现,效率和性能也会大幅下降。 最重要的是,实现起来非常困难。 展开新分区。

这时候如果我们继续追求集群的ACID,我们的系统就会变得很差。 这时候我们就需要引入一个新的理论原理来适应这种集群情况,这就是CAP。

CAP定理

CAP 必须满足以下 3 个属性:

简单来说,在分布式系统中,最多可以支持上述属性中的两个。 但显然既然是分布式的,我们就必然要对其进行分区。 既然是分区的,我们就不能100%避免分区错误。 因此,我们只能在一致性和可用性之间做出选择。

在分布式系统中,我们常常追求的是可用性,可用性比一致性更重要。 那么这里还有一个关于如何实现高可用的理论,就是BASE理论,它进一步扩展了CAP理论。

基础理论

BASE 理论指出:

BASE理论是CAP中一致性和可用性之间权衡的结果。 该理论的核心思想是:我们无法做到强一致性,但每个应用程序可以根据自身业务特点采取适当的方法,使系统达到最终一致性。

好吧,讲了一大堆理论,程序员们已经不耐烦了。 快来看看分布式事务有哪些解决方案,以便您继续...

过来讨论一下技术方案:

生鲜小程序开发功能解决方案_生鲜行业解决方案_生鲜方案怎么写

已经提出了几种解决方案,因为我们在这里并不是专门解释分布式事务的机制和原理,而主要是选择分布式事务的技术。

我们首先排除掉不应该选择的选项。 一是XA两阶段提交。 这个在很多传统公司都有使用,但是不太适合互联网微服务的分布式系统。 锁定资源耗时较长,对性能影响较大,因此排除。

另一种是阿里巴巴的GTS,它不是开源的。 现在它是开源的。 但目前仍缺乏研究。 下一阶段研究后可能会用到,所以暂时排除。

剩下的两种是TCC和MQ消息事务。

MQ消息事务:

先说MQ的分布式事务。 4.3版本已经正式宣布支持分布式事务。 选择做分布式事务时,一定要选择4.3以上版本。

作为异步保证事务,事务消息通过MQ异步解耦两个事务分支。 事务消息的设计过程也借鉴了两阶段提交理论。 整体交互流程如下图所示:

这时候我们基本上可以认为,只要MQ发送方自己的本地事务完成,那么MQ订阅方就100%能够收到消息,然后我们就会修改订单减少和库存减少的步骤。

这涉及到异步转换。 我们来看看同步过程中的各个步骤:

订单创建后,会发布一个事件“”到消息队列,然后由MQ转发到订阅该消息的服务。 因为是基于消息交易的,所以我们可以认为订阅消息的产品模块可以100%收到消息。 的。

产品服务收到消息后,将进行库存扣减操作。 请注意,可能存在一些不可抗力因素导致库存扣除失败。

无论成功还是失败,商品服务都会向消息队列发送一条库存扣减结果的消息“”,订单服务会订阅库存扣减结果。

订单服务收到消息后有两种可能:

这种模式使得订单确认过程异步,非常适合高并发使用。 但是,请记住,这需要前端用户体验发生一些变化,并且该过程必须与产品相协调。

完美,使用MQ分布式事务可以解决一致性问题。

等等,我们来了解一下MQ消息事务方案的风险。

上述使用MQ的方法确实可以完成操作A和B,但是A和B并不是严格一致的,而是最终一致的。

我们牺牲严格一致性来换取性能的提升,非常适合在高并发场景下使用。

但如果B继续执行失败,一致性也会被破坏。 未来应考虑更多的后备计划。 计划越详细,系统就越复杂。

TCC方案

TCC是服务化的两阶段转型模型。 每个业务服务必须实现三个方法:Try 和 Try。

这三个方法可以对应SQL事务中的Lock:

接下来我们看看如何在我们的扣单库存流程中添加TCC:

Try期间,库存服务会为这个订单预留n个库存,订单服务会生成一个“未确认”订单,同时生成这两个预留资源。

到时候,Try中预留的资源就会被使用。 在TCC事务机制中,认为如果Try阶段能够正常预留资源,那么就会完全提交:

Try过程中,如果其中一个任务执行失败,则会执行接口操作,释放Try阶段预留的资源。

完美,我们可以将我们的系统引入TCC。 ^?_?^

等等,有同学问:

建议TCC开源框架使用TCC,其他也可以使用,无所谓。

完美,订单流程已开发完毕,可供 QA 访问。 ^?_?^

等等,微服务的保护措施做好了吗?

熔断电流限制隔离退化

微服务的分布式依赖关系很复杂。 比如前端的一个请求,会转化为后端的很多请求。

此时,后端服务会变得不稳定或延迟。 如果没有良好的限流和断路器措施,用户体验可能会下降。 严重时可能会出现雪崩效应,导致整个网站瘫痪。

双11这样的活动,如果阿里巴巴没有一套很好的限流、熔断措施,那是不可想象的,可能无法支撑这么大的并发能力。

2012年之前,没有设计良好的限流和容错功能。 当时还受到系统稳定性问题的困扰。 由于缺乏良好的断路器措施,该网站多次被关闭。

弹性工程项目是2012年启动的,有一个产品叫,主要是用来解决微服务的可靠性。

有了这个系统后,系统的稳定性达到了一个很大的水平,此后没有发生过大规模的雪崩事故。

下面以限流熔断器为例进行说明。

几个概念:熔断、隔离、限流、降级是分布式容错最重要的概念和模式。

①保险丝:如果家里安装了电路保险丝,当你使用超强电路时,就会有保险丝装置来帮助你保护,以免在出现问题时加剧问题。 ②隔离性:我们知道计算资源是有限的。 CPU、内存、队列、线程池都是资源。 他们的资源都是有限的。 如果不进行隔离,一个服务的调用可能会消耗大量的线程资源,并占用其他服务的资源。 那么可能一项服务出现问题,导致其他服务无法进行。 使用权。 ③限流:当大流量访问涌入我们的服务时,我们需要一定的限流措施。 例如,我们的规则只允许在一定时间内一定数量的访问通过我们的资源。 如果太大,系统就会出现问题,这时就需要限流保护。 ④ 降级:如果系统后台无法提供足够的支持,那么就需要有降级能力,以保护系统不被进一步恶化,为用户提供更加人性化的灵活解决方案,比如通知用户暂时不可用,请等待持续一段时间然后再尝试等等。

只需将上述的熔断、隔离、限流、降级封装在这样一个组件中即可。 下图展示了内部设计和调用流程:

一般工作流程如下:

完美,将其添加到我们的系统中,这样如果突然出现流量高峰,我们的系统不会立即不堪重负。 ^?_?^

等等,我们需要配置的限流值、错误次数断路器、超时断路器和尝试恢复比例应该如何确定呢?

这取决于你的系统压力测试的指标和你的部署规模。 它还涉及到一个容量设计的问题,这个问题我们稍后在线部署系统的时候会详细讨论。

刚才提到的一个问题是,这些限流值和错误号熔断器现在都写在配置文件中了。

比如如果是用YML写的,如果有一天突然需要降低限流(可能是系统承受了某种压力),那么我们就只能把代码拉下来改一下。

然后重新上传、打包、发布、重启。 整个过程不仅需要一个小时,而且需要十分钟。

想办法让我们把这些配置项放到一个集中的配置中心。

集中配置中心

自己写配置中心还是挺麻烦的。 去菜市场。 菜市场有一些,比如百度的、阿里巴巴的、携程的。

基本上,他们的原理是相似的。 配置中心可以简单理解为一个服务模块。 开发人员或运维人员可以通过界面对配置中心进行配置。

以下相关微服务可以接入配置中心,实时获取配置中心修改的参数。

更新方式一般有两种:

Pull 和 Push 模式各有优缺点:

携程的

携程比较有特色的是,它结合了Pull和Push两种模式,结合了两者的优点。 开发或运维人员在配置中心进行修改,配置中心服务会将修改实时推送到客户端。

但考虑到可能会因为一些网络抖动导致推送不成功,所以客户端还具有定时从服务器拉取Pull数据的功能。

即使推送失败,只要一定时间,客户端仍然会主动拉取同步数据,以确保最终的配置能够同步到服务。 这在高可用性方面也是一个非常有特色的设计。

高可用性也得到了保证。 当客户端获取数据时,会将数据缓存在内存中并同步到本地磁盘。

即使服务器挂了,即使客户端服务重启,也可以从本地磁盘检索数据,继续对外提供服务。 从这一点来看,配置中心在高可用方面考虑得还是比较周到的。

配置中心配置完成后,我们可以放入用户密码、业务开关等其他配置参数。

完美,开发基本完成。 其实就是几个模块,一个简单的订购和购物流程。 当我们把系统交给运维的时候,运维喊道,日志在哪里? 不调用链日志如何做微服务?

调用链监控和日志

事实上,微服务是一个分布式且非常复杂的系统。 如果没有一套调用链监控,就很难定位服务之间依赖关系的问题。

下图展示了阿里巴巴提供的微服务在鹰眼系统中的“熵”:

目前各大互联网公司中,阿里巴巴拥有优秀的鹰眼系统,大众点评也拥有知名的调用链监控系统CAT。

调用链监控实际上是最早提出的。 2010年发表了一篇关于调用链的论文,该论文因其内部的调用链系统而得名。

本文阐述了使用调用链的经验和原理。 总体原理如下:

这里我们可以使用ELK来记录并展示调用链监控日志。 当我们拨打电话时,我们将其存储为一行记录。

通过and,可以将它们串联起来,形成一个完整的链路,从这个链路上可以分析出错误或呼叫延迟和呼叫次数。

目前市场上主流的调用链选择有,,Cat,,各有各的侧重点。

值得一提的是,它是国人新出品的调用链工具。 它采用开源的基于字节码注入的调用链分析,访问段没有代码入侵。

而且开源支持多种插件。 UI是几款工具中比较强大的,UI也比较顺眼。 目前已加入孵化器。

采用作为调用链工具

为什么会被采纳呢? 从底层原理的实现来看,这些产品是相似的,但实现和使用的细节还是有很大不同的:

完美,只需将微服务打包上传到服务器即可运行。 ^?_?^

等等,微服务包都准备好了,剩下的就是将Jar包或者War包一一上传到服务器,然后使用脚本了。 以前单块应用还可以,现在微服务应用有几十上百个。 请告诉我。 ,运营商害怕吗?

听说+更适合微服务。

+

只需几个服务,不需要容器化部署...乍一看似乎无穷无尽,还有CICD、灰度发布...易于编排...

下次再说,先部署服务吧。

部署到生产,估计容量

是时候在线部署该服务了。 当一项服务上线时,需要评估或估计会有多少用户、有多少访问量。 这就涉及到应该配置多少机器资源。 这应该如何估计呢? 反正程序员都在家。 不管你怎么计算,你都算不出来。

评估流量

①询问操作。 如果是已经上线的产品,一定有现有的用户数和访问数据。 即使有偏差,也在可控范围之内。

②询问产品并确定它是什么类型的产品。 例如,这是团购或限时抢购。 不同的加工方法是不同的。

评估平均访问 QPS

每天秒数,一般认为大部分请求发生在白天,所以根据计算,日平均访问次数=每日访问总数/。

评估峰值 QPS

你可以把之前的每日访问曲线图拿出来看看。 峰值取决于业务。 比如有的商家白天上午10点客流量较多,有的商家晚上休闲客流量较多。

简而言之,日均峰值是根据业务估算出来的。 与电商服务类似,一般峰值约为日均流量的5倍左右。

比如一些重大促销活动可能费用较高,必须提前与运营人员沟通。 还有一些活动,例如闪购,并不是基于预估的。 闪购是另一个考虑因素并被采用。 响应策略与普通订单完全不同。

评估系统,单机限制QPS

上线之前需要和测试人员一起做压力测试,对每个服务、每台机器都要做。 一般而言,每台服务和一台机器都将被推到极限,并且将逐步进行优化。

考虑一个问题,假设一台机器的最大QPS是1000,而我们的峰值QP是5000,需要多少个机器才能抵抗? 答案大于或等于6个单位,最小容错不得小于1单位。

看来非常简单的微服务几乎足够了,但似乎仍然更糟。 我们数一下:

分享