如何扩展ASP.NET Core微服务和散列式数据库。用JMeter进行负载测试

218 阅读7分钟

用Docker Compose在HAProxy负载平衡器后面运行多个DBMS和C#容器。用不同数量的实例测试扩展性

上一篇文章,你创建了一个微服务架构,并手动实现了应用层数据库分片

现在,你将扩展应用程序运行微服务和数据库的多个容器实例。你将使用Docker Compose和一个HAProxy负载平衡器

然后你运行JMeter负载测试看看在使用 不同数量的实例时,应用程序的扩展情况。最后,您还将发布和接收来自RabbitMQ的消息

1.运行多个数据库和微服务实例

Dockerize微服务

使用 上一篇文章中的代码和环境 作为基础

Visual Studio Project-Explorer中的文件 "Dockerfile "重命名为 "dockerfile"(第一个字符小写)。然后右键单击dockerfile,选择"创建 Docker 镜像”.这也将把图像推送到docker。

在Docker中运行应用程序

创建文件_docker-compose.yml_。

medium.com/media/46c01…

该docker文件配置了3个数据库容器和4个_Post_ 服务的实例。目前,只有2个数据库被_Post_ 服务实例所使用。你以后可以删除注释以使用第三个数据库。一个HAProxy负载平衡器在5001端口暴露_Post_ 服务容器。

每个容器有0.5的CPU限制,以帮助在本地机器上进行实际的负载测试。在我的12核笔记本上,仍有未使用的资源,因此,增加更多的服务和数据库实例可以带来好处。

启动应用程序

C:\dev>docker-compose up -d

启动数据库

http://localhost:5001/swagger/index.html,打开你的浏览器

用至少100个用户和10个类别启动数据库。

你可以创建更多的用户和类别,但由于CPU的限制,这将需要一些时间。

2.用JMeter对扩展的应用程序进行负载测试

创建JMeter测试计划

安装 并打开 JMeter.

创建一个测试计划和一个线程组。

32个线程是一个好的开始数字。在一个线程的每个循环中,它添加一个帖子并读取10个帖子。

添加一个HTTP请求来创建一个帖子。

  • 服务器名称:localhost
  • 端口:5001
  • HTTP-Request:POST
  • 路径。/api/Posts
  • 主体数据。
{

它为一个随机的用户(ID 1-100)和类别(1-10)创建一个帖子。

在请求中添加一个 Content-Type application/json HTTP header到请求中。

读取一个随机类别的10个帖子。

  • 服务器名称:localhost
  • 端口:5001
  • HTTP-Request:GET
  • 路径。/api/Posts
  • 随请求发送参数。
NAME | VALUE | CONTENT-TYPE

运行测试

在测试运行时看一下_总结报告_。

应该没有错误

等待一段时间,直到_平均_ (响应时间)和_吞吐量_ 的值变得稳定。

修改测试参数

在JMeter中停止测试。

你可以改变测试计划中的线程。把它们增加到例如64或128个线程。或者把线程减少到16个,甚至1个。

在编辑_docker-compose.yml_之前,关闭应用程序

C:\dev>docker-compose down

你可以通过 "scale"属性改变_后期_ 服务实例的数量。改变数据库数量的 "环境"属性(添加/删除注释)。

在你的改变之后,启动应用程序

C:\dev>docker-compose up -d

需要一些时间,直到数据库服务器运行。并记住要初始化数据库。

3.测试结果示例

**在我的电脑上,两个职位服务和一个数据库的比例可以得到很好的结果。**我可以把它扩展到六个服务和三个数据库,直到我达到硬件的极限。平均时间保持在500ms以下。将线程数增加到64以上会产生错误。

这些结果取决于我的环境和CPU的限制。在你的机器上也会有所不同。

每秒的吞吐量与实例的数量成正比。

在CPU有限的情况下,每秒305个请求,每天大约有2500万个请求。这将允许100万用户每天写10个帖子和阅读帖子。当然,现实生活中的应用会更复杂,但我希望这个例子能说明基本的想法。

4.微服务间的通信和复制用户的变化

Post 服务通过Rabbitmq消息接收来自_User_微服务的用户变更。

您也将用JMeter来模拟这一点。

创建 RabbitMQ 容器

发布以下命令(在控制台窗口中的一行)以启动具有管理 UI 的 RabbitMQ 容器。

C:\dev>docker run -d  -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=test -e RABBITMQ_DEFAULT_PASS=test --hostname my-rabbit --name some-rabbit rabbitmq:3-management

该命令将_"test_"配置为用户和密码,而不是默认的 Guest_凭据_ 。Guest 被限制在 localhost,但在 docker 内,容器在不同的主机上。

修改 Post 微服务

在 Visual Studio 中安装_RabbitMQ.Client_NuGet 包。

添加_IntegrationEventListenerService_ 类。

medium.com/media/6d77b…

后台服务使用_"test_"帐户来访问 RabbitMQ,并使用 host_.docker.internal 和_ localhost 作为 主机。这允许从容器内部和 Visual Studio 调试器进行连接。

单个活动消费者保证只有一个_Post_ 服务实例接收消息。

如果活动实例崩溃了,那么下一个实例将接管。你以后可以通过在docker中停止当前接收实例来尝试。

该代码创建了交换和管道,如果它们还不存在的话。它使用手动确认。

修改_Startup.cs_以运行IntegrationEventListenerService。

medium.com/media/7f3c3…

在Docker中运行改变后的微服务

在docker中关闭应用程序

C:\dev>docker-compose down

构建_Post_ 服务,将其dockerize并发布到docker。

在你的改动之后启动应用程序

C:\dev>docker-compose up -d

这需要一些时间,直到数据库服务器运行。并记住要初始化数据库。

修改JMeter测试

在JMeter测试计划中添加一个只有一个线程的线程组

添加一个恒定的定时器。

恒定的定时器将测试限制在每秒一条消息。

每秒一条消息还是很频繁的。即使在半年内有1,000,000个用户注册,也只是每分钟4个新用户。

添加 HTTP 请求以将消息发布到 RabbitMQ。

  • 服务器名称:localhost
  • 端口:15672
  • HTTP-Request:POST
  • 路径。/api/exchanges/%2F/userloadtest/publish
  • 身体数据。
{

用户实体有一个版本字段来处理失序的消息。为了保持测试的简单性,它只更新一个用户并增加版本字段。性能影响应该保持不变。

为_内容类型_和对 RabbitMQ 的授权添加一个 HTTP 头管理器

Content-Type | application/json

"dGVzdDp0ZXN0 "是base64编码的用户和密码 "test"。

运行测试

吞吐量应该与之前的测试类似。

您还可以通过查看控制台输出来识别 docker 中的活动 RabbitMQ 消费者。您可以停止该容器,另一个实例将接管。

5.最后的思考和展望

创建了一个微服务架构并实现了应用层数据库分片。然后你用多个容器实例扩展了应用程序并对其进行了负载测试。您还处理了来自 RabbitMQ 的用户变更事件

这只是一个示例应用程序。您将不得不调整代码,以便在生产环境中使用它

下一步是什么?获取像拥有最多帖子的前 10 个类别的数据需要查询多个数据库实例。这可能会导致延迟并扼杀性能。Redis可以成为查询聚合数据的一个解决方案。我将在下一篇文章中展示它

你也可以在Kubernetes中运行该应用程序。参见我的其他文章。

如果你有任何问题、想法或建议,请联系我。


如何扩展ASP.NET Core微服务和散列式数据库。用JMeter进行负载测试最初发表在ITNEXT的Medium上,人们在这里通过强调和回应这个故事来继续对话。