使用Docker+springboot+springcloud+axon 构建CQRS/ES的微服务架构_quguang65265的博客-CSDN博客

标签: | 发表时间:2021-08-02 11:46 | 作者:
出处:https://blog.csdn.net

原文地址: https://benwilcock.wordpress.com/2016/06/20/microservices-with-spring-boot-axon-cqrses-and-docker/

在过去几年中,软件架构的变化步伐迅速发展。 DevOps,Microservices和Containerisation等新方法已成为热门话题,采用率迅速提高。 在这篇文章中,我想向您介绍一个我一直在研究的微服务项目,它结合了过去几年中两个突出的架构进步:命令和查询责任分离(CQRS)和容器化。

在第一部分中,我将向您展示使用容器分发和运行多服务器微服务应用程序是多么容易。

为了做到这一点,我使用Docker创建了一个包含运行演示所需的所有微服务的容器套件。 在撰写本文时,该套件中有七个微服务; 他们是:-
这里写图片描述

该演示的源代码可在 Github上获得,并演示如何实现和集成“云原生”Java所需的一些功能,包括: -
- 使用Java和Spring Boot的微服务;
- 使用Docker容器在任何地方构建,发送和运行;
- 使用Axon Framework v2,MongoDB和RabbitMQ进行命令和查询责任分离(CQRS)和事件源(ES);
- 使用Spring Cloud进行集中配置,服务注册和API网关;

How it works

这里介绍的微服务示例项目围绕着一个虚构的“product”主数据应用程序,类似于您在大多数零售或制造公司中找到的应用程序。可以使用简单的RESTful服务API从此主数据中添加,存储,搜索和检索产品。随着更改的发生,通过使用消息发送通知给感兴趣的各方。

Product Data应用程序使用CQRS架构风格构建。在诸如 ADD之类的CQRS命令中,物理上与诸如’VIEW(其中id = 1)`之类的查询分开。实际上,在这个特定的例子中,Product域的代码库已经完全分为两个独立的组件 - 命令端微服务和查询端微服务。

像大多数 12 factor apps一样,每个微服务都有一个单一的责任;拥有自己的数据存储区;并且可以独立于另一个进行部署和扩展。这是CQRS和微服务中最直译的解释。 CQRS或微服务都不能以这种方式实现,但为了本演示的目的,我选择创建一个非常明确的读写问题分离。
逻辑架构如下所示: -
这里写图片描述

命令端和查询端微服务都是使用Spring Boot框架开发的。 命令和查询微服务之间的所有通信纯粹是“事件驱动的”。 使用RabbitMQ消息传递在微服务组件之间传递事件。 消息传递提供了一种可扩展的方法,以松散耦合的方式在进程,微服务,遗留系统和其他方之间传递事件。

请注意,这两个服务的数据库与另一个服务器的数据库不同。
这很重要,因为它为每项服务提供了高度自治,这反过来又有助于各项服务独立于系统中的其他服务进行扩展。
有关CQRS架构的更多信息,请查看我的幻灯片共享CQRS微服务上面的幻灯片。

CQRS架构模式中存在的高度自治和隔离为我们提供了一个有趣的问题 - 我们应该如何分配和运行如此松散耦合的组件? 在我看来,容器化提供了最好的机制,并且Docker被广泛使用,它的格式已成为容器映像的事实标准,大多数流行的云平台提供直接支持。 它也很容易使用,这肯定有帮助。

命令端微服务

命令是“actions which change state”。 命令端微服务包含所有域逻辑和业务规则。 命令用于添加新产品或更改其状态。 在特定产品上执行这些命令会导致生成“事件event”,这些事件由Axon框架持久保存到MongoDB中,并通过RabbitMQ消息传递到其他进程(尽可能多的进程)。

在event-soursing中,事件是系统的唯一状态记录。 它们被系统用于描述和重建任何实体的当前状态(通过一次一个地重放它的过去事件,直到重新应用所有先前的事件)。 这听起来很慢,但实际上因为事件很简单,它非常快,可以使用名为“快照”的汇总进一步调整。

在领域驱动设计(DDD)中,实体通常被称为“Aggregate”或“AggregateRoot”。

查询端微服务

查询端微服务充当事件监听器和视图。 它监听命令端发出的“事件”,并将它们处理成最有意义的形状(例如表格视图)。

在这个特定的例子中,查询端只是构建和维护一个“物化视图”或“投影”,它保存了各个产品的最新状态(就其ID和描述以及它们是否可销售而言)。 可以多次复制查询端以实现可伸缩性,并且可以使RabbitMQ队列保存的消息持久,因此如果消息发生故障,它们甚至可以代表查询端临时存储消息。

命令端和查询端都有REST API,可用于访问其功能。

有关更多信息,请参阅 Axon文档,该文档描述了Axon如何为您的Java应用程序带来CQRS和事件源,以及有关如何配置和使用它的大量详细信息。

运行例子

运行演示代码很简单,但您需要先在计算机上安装以下软件。 作为参考,我使用 Ubuntu 16.04作为我的操作系统,但我也成功测试了新的 Docker for Windows Beta上的应用程序。

  • Docker (I’m using v1.8.2)
  • Docker-compose (I’m using v1.7.1)

如果您已经拥有MongoDB或RabbitMQ,请在继续之前关闭这些服务以避免端口冲突。

第1步:获取Docker-compose配置文件

在新的空文件夹中,在终端执行以下命令以下载此演示的最新docker-compose配置文件。

      $wgethttps://raw.githubusercontent.com/benwilcock/microservice-sampler/master/docker-compose.yml

尽量不要更改文件名 - Docker默认寻找名为“docker-compose.yml”的文件。 如果更改了名称,请在以下步骤中使用参数 -f 切换。

第2步:启动微服务

因为我们正在使用docker-compose,所以启动微服务现在只是执行以下命令的情况。

      docker-composeup

在下载并运行docker镜像时,您会在终端窗口中看到大量下载和记录输出。

共有七个docker镜像,分别是mongodb,rabbitmq,config-service,discovery-service,gateway-service,product-cmd-side和product-qry-side。
如果要查看正在运行的docker实例(并获取其本地IP地址),请打开一个单独的终端窗口并执行以下命令: -

      docker ps

一旦实例启动并运行(这可能需要一些时间),您可以立即使用浏览器环顾四周。您应该能够访问: -

  • 端口“15672”上的Rabbit Management Console
  • 端口“8761”上的Eureka Discovery Server控制台
  • 端口“8888”上的配置服务器映射
  • 端口’8080’上的API网关路由

第3步:使用产品

到现在为止还挺好。现在我们要测试产品的添加。

在这个手动系统测试中,我们将向命令端REST API发出 add命令。

当命令端处理完命令时,引发’ProductAddedEvent’,存储在MongoDB中,并通过RabbitMQ转发到查询端。然后查询端处理此事件并将产品的记录添加到其物化视图(实际上是这个简单演示的H2内存数据库)。事件处理完毕后,我们可以使用查询端微服务查找有关已添加新产品的信息。在执行这些任务时,您应该在docker-compose终端窗口中观察一些日志记录输出。

步骤3.1:添加新产品

为了执行测试,我们首先需要打开第二个终端窗口,我们可以在这里发出一些CURL命令而不停止我们在第一个窗口中运行的docker组合实例。

出于本次测试的目的,我们将在产品目录中添加一个名为“Everything is Awesome”的MP3产品。为此,我们可以使用命令端REST API并使用POST请求发出它,如下所示……

      $ curl-XPOST-v--header"Content-Type: application/json"--header"Accept: */*""http://localhost:8080/commands/products/add/01?name=Everything%20Is%20Awesome"

如果您没有“CURL”,则可以使用自己喜欢的REST API测试工具(例如Postman,SoapUI,RESTeasy等)。

如果您正在使用Docker for Mac或Windows的公共测试版(强烈推荐),则需要将“localhost”替换为在终端窗口运行docker ps时显示的IP地址。

您应该看到类似于以下响应的内容。

      * Trying127.0.0.1...* Connected to localhost (127.0.0.1) port8080(#0)> POST /commands/products/add/01?name=Everything%20Is%20Awesome HTTP/1.1> Host: localhost:9000> User-Agent: curl/7.47.0> Content-Type: application/json
> Accept: */*$ http://localhost:8080/commands/products/01< HTTP/1.1201Created
< Date: Thu,02Jun201613:37:07GMTThis
< X-Application-Context: product-command-side:9000< Content-Length:0< Server: Jetty(9.2.16.v20160414)

响应代码应为“HTTP / 1.1 201 Created”。这意味着MP3产品“Everything is Awesome”已成功添加到命令端事件源存储库中。

步骤3.2:查询新产品

现在让我们检查一下,我们可以查看刚刚添加的产品。为此,我们发出一个简单的’GET’请求。

      $curlhttp://localhost:8080/queries/products/1

您应该看到以下输出。这表明查询端微服务有我们新添加的MP3产品的记录。该产品列为不可销售(salable = false)。

      {name:"Everything Is Awesome",
  saleable: false,
  _links: {
    self: {
    href:"http://localhost:8080/queries/products/1"},product:{href:"http://localhost:8080/queries/products/1"}
  }
}

ok!如果您愿意,可以继续重复测试以添加更多产品,请注意不要在POST时尝试重复使用相同的产品ID,否则您将看到错误。

如果您熟悉MongoDB,则可以检查数据库以查看您创建的所有事件。同样,如果您了解RabbitMQ管理控制台的方法,您可以在命令端和查询端微服务之间看到消息。

关于作者
Ben Wilcock是一名自由软件架构师兼技术主管,对微服务,云和移动应用程序充满热情。 Ben帮助几家富时100指数公司提高了响应能力,创新能力和敏捷性。 Ben也是一位受人尊敬的技术博主,他的文章在Java Code Geeks,InfoQ,Android Weekly等中都有所体现。您可以通过LinkedIn,Twitter和Github与他联系。

相关 [docker springboot springcloud] 推荐:

使用Docker+springboot+springcloud+axon 构建CQRS/ES的微服务架构_quguang65265的博客-CSDN博客

- -
在过去几年中,软件架构的变化步伐迅速发展. DevOps,Microservices和Containerisation等新方法已成为热门话题,采用率迅速提高. 在这篇文章中,我想向您介绍一个我一直在研究的微服务项目,它结合了过去几年中两个突出的架构进步:命令和查询责任分离(CQRS)和容器化. 在第一部分中,我将向您展示使用容器分发和运行多服务器微服务应用程序是多么容易.

SpringBoot-Metrics监控

- -
Metrics基本上是成熟公司里面必须做的一件事情,简单点来说就是对应用的监控,之前在一些技术不成熟的公司其实是不了解这种概念,因为业务跟技术是相关的. 当业务庞大起来,技术也会相对复杂起来,对这些复杂的系统进行监控就存在必要性了,特别是在soa化的系统中,完整一个软件的功能分布在各个系统中,针对这些功能进行监控就更必要了.

Docker & Flatpak

- - IT瘾-dev
目前最流行的技术莫过于Docker,Docker和Docker衍生的东西用到了很多很酷的技术,目前deepin应用软件发布转变成flatpak,这些看似风牛马不相及的技术方案,实际都使用了一个共同的底层技术——Namespace,假如没有namespace支持,这些技术实现都将成为空中楼阁. 一句话总结,无论是Docker、sysmted-nspawn还是flatpak,都是在namespace基础上,针对不同的场景,生出的不同的解决方案.

docker初体验之docker-tomcat

- - BlogJava-首页技术区
docker已经是现在最热的容器技术,最近也去体验了一下,在daocloud注册了一个账号,并开始本机实战docker. daocloud免费有两个容器可用,体验送T恤,邀请送书,这里我分享一个daocloud的邀请码 https://account.daocloud.io/signup?invite_code=mxeq2jkmcur37vz6ven8,daocloud是非常棒的容器云平台,使用体验好,问题响应也及时,绑定微信还送一个额外容器.

基于springcloud实现的灰度发布

- -
基于springcloud实现的灰度发布. gray-config-server 配置中心. 端口:6007,方便起见直接读取配置文件,生产环境可以读取git. 先启动配置中心,所有服务的配置(包括注册中心的地址)均从配置中心读取. gray-xxx-service 服务消费者. 调用服务提供者和服务提供者,验证是否进入灰度服务.

SpringCloud项目接入Jaeger(下) - 掘金

- -
spring-cloud-sleuth这个组件时,会面临两个问题. 首先是日志中无法显示traceId和spanId这些链路信息,其次是不能在用. spring-cloud-sleuth所提供的方式进行链路传值. spring-cloud-sleuth是将traceId等链路信息保存在. slf4j的MDC(Mapped Diagnostic Contexts)中,然后通过%X{traceId}这种方式将traceId提取出来,比如打印到控制台的默认格式是:.

Springcloud + RocketMQ 解决分布式事务

- - 掘金架构
分布式事务有哪些实现方式. 随着互联网时代的高速发展,分布式成了大型系统的标配,这是时代发展的选择. 大型分布式系统不是每个公司和开发人员都能够涉及的领域,因为大型系统后面都 隐藏着众多代名词:复杂,昂贵,高科技,人才云集,大战略. 大部分领头互联网公司甚至依托自己的分布式经验逐步建立自己的体系,并使用这套体系搭建自己的平台对内,甚至对外提供服务, 就像现在众多的云平台提供的服务,甚至有些大战略提出促进发展:大中台小前台、大炮台支援单兵作战等等.

SpringCloud Gateway与k8s_zhangjunli的博客-CSDN博客

- -
接下来的内容由以下几部分组成:. 什么是SpringCloud Gateway. SpringCloud Gateway实战参考. kubernetes上的SpringCloud Gateway. 开发k8sgatewaydemo. 什么是SpringCloud Gateway. SpringCloud Gateway是SpringCloud技术栈下的网关服务框架,在基于SpringCloud的微服务环境中,外部请求会到达SpringCloud Gateway应用,该应用对请求做转发、过滤、鉴权、熔断等前置操作,一个典型的请求响应流程如下所示:.

kubernetes移除Docker?

- -
两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时. 这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用. 看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定.

SpringBoot的事务管理

- - ImportNew
Springboot内部提供的事务管理器是根据autoconfigure来进行决定的. 比如当使用jpa的时候,也就是pom中加入了spring-boot-starter-data-jpa这个starter之后(之前我们分析过 springboot的自动化配置原理). Springboot会构造一个JpaTransactionManager这个事务管理器.