go-ecommerce-microservices:Golang电子商务微服务案例


这是一个实用的电子商务微服务,它使用CQRS、事件源、垂直切片架构和事件驱动架构构建。点击标题

一个实际的电子商务示例,使用Golang和不同的软件架构和技术构建,如微服务架构,垂直切片架构,CQRS模式,域驱动设计(DDD),事件源,事件驱动架构和依赖注入。对于独立服务之间的通信,我们使用RabbitMQ进行异步消息传递,有时我们使用REST和gRPC调用进行实时通信。

您可以使用此项目作为模板,在此项目之上使用Go语言构建后端项目。

这个应用程序不是“面向业务”的,我的重点主要是技术部分,我只是想使用不同的技术,软件架构设计,原则和创建微服务应用程序所需的所有内容来实现一个示例。

特色功能

  • 使用Vertical Slice Architecture作为高级架构
  • 在RabbitMQ Message Broker之上使用Event Driven Architecture和自定义事件总线
  • 目录读取服务中使用基于CRUD的Data Centeric Architecture
  • 在Event Sourcing服务中使用Audit Based,如订单服务
  • 在Go-MediatR库上使用CQRS Pattern和Mediator Pattern
  • 在uber-go/fx库上使用Dependency Injection和Inversion of Control
  • 使用RESTFul API Echo  框架和使用swagger与  swaggo/swag  图书馆
  • 使用gRpc进行内部服务通信
  • 使用go-playground/validator验证REST和gRpc中的输入数据
  • 使用Postgres和EventStoreDB用于完全支持事务的写数据库(ACID)
  • 使用MongoDB和Elastic Search读取数据库(NOSQL)
  • 使用OpenTelemetry用于集合Distributed Tracing,使用Jaeger和Zipkin
  • 将OpenTelemetry用于集合Metrics,使用Prometheus和Grafana
  • 使用Unit Test测试带有mocking依赖类的小单元,使用Mockery测试mocking依赖项
  • 使用End2End Test和Integration Test来测试功能,并使用Docker容器(清理测试)和testcontainers-go库来测试它们的所有真实的依赖项
  • 使用Zap和结构化日志
  • 使用Viper进行配置管理
  • 使用docker和docker-compose进行部署
  • 在一些服务中使用Domain Driven Design,如目录写入服务订单服务
  • 使用Helm和Kubernetes进行部署
  • 对所有微服务使用Outbox Pattern以保证交付至少一次交付
  • 使用Inbox Pattern处理接收方的幂等性和精确一次交付


技术 - 库

应用程序结构
在本项目中,我使用了垂直切片架构或重组为垂直切片架构,还在本项目中使用了功能文件夹结构。

  • 我们将每个请求视为一个不同的用例或切片,封装并分组了从前端到后端的所有关注点。
  • 当我们在 n-tire 架构中添加或更改应用程序中的某个功能时,我们通常会接触到应用程序中的许多不同 "层"。我们不是跨层耦合,而是沿切片垂直耦合,每次更改只影响一个切片。
  • 我们将切片之间的耦合最小化,将切片内的耦合最大化。
  • 通过这种方法,我们的每个垂直切片都能自行决定如何以最佳方式满足请求。新功能只会增加代码,我们不会改变共享代码,也不用担心副作用。使用 cqrs 模式来实现垂直切片架构是一个很好的选择。

在这里,我还使用 CQRS 将我的功能分解成非常小的部分,从而使我们的应用程序变得更小:

  • 最大限度地提高性能、可扩展性和简易性。
  • 在这种机制中添加新功能非常简单,无需对其他部分的代码进行任何破坏性修改。新功能只需添加代码,无需更改共享代码,也无需担心副作用。
  • 易于维护,任何改动只影响一个命令或查询(或片段),避免对其他部分造成任何破坏性改动
  • 在我们的代码中,它能更好地分离关注点和交叉关注点(在 MediatR 行为管道的帮助下),而不是用一个大的服务类来做很多事情。

使用 CQRS 后,我们的代码将更符合 SOLID 原则,尤其是在以下方面:
  • 单一责任规则--因为负责特定操作的逻辑被封装在自己的类型中。
  • 开放-封闭规则--因为要添加新的操作,不需要编辑任何现有类型,而是需要添加一个新文件,用一个新类型来代表该操作。

在这里,我们将每个业务功能切割成若干垂直切片,在每个切片内部,我们都有专门针对该功能的技术文件夹结构(命令、处理程序、基础架构、存储库、控制器、数据模型......),而不是一些技术拆分,例如为我们的服务、控制器和数据模型创建文件夹或层。

通常情况下,当我们开发某个功能时,我们需要一些技术方面的东西,例如

  • 应用程序接口端点(控制器)
  • 请求输入(Dto)
  • 请求输出(Dto)
  • 处理请求的类,例如命令和命令处理程序或查询和查询处理程序
  • 数据模型

现在,我们可以把所有这些东西放在一起,这样就可以减少一些层或文件夹之间的跳转和依赖。

在 CQRS 中保持这种分割非常有效。它隔离了我们的操作,并将应用程序代码垂直切分,而不是水平切分。在我们的 CQRS 模式中,每个命令/查询处理程序都是一个单独的片段。这样可以减少层与层之间的耦合。每个处理程序都可以是一个独立的代码单元,甚至可以复制/粘贴。因此,我们可以调整具体方法,使其不遵循一般惯例(例如,使用自定义 SQL 查询或甚至不同的存储)。在传统的分层架构中,当我们改变一层的核心通用机制时,会影响到所有方法。

详细点击标题