Spring 启动应用程序可以处理大量请求

Spring Boot application can handle tons of requests

我正在使用 Spring-boot 或 Spring-Cloud Framework 开发 Web 应用程序。 该系统将主要用于处理来自客户端的 HTTP Restful 请求,然后将它们保存到 MySQL 数据库中。

但我打算让它更具可扩展性。它应该能够启动每个服务的更多实例并使系统可以处理更多传入请求。

但是我不确定我这样做是对的,有没有人可以来帮我检查一下我现在的做法是否合理,或者提出我做法中的任何潜在风险。

我正在做的是:

  1. 服务A在控制器中接收请求,然后异步写入RocketMQ。 RocketMQ用于削峰

  2. 服务B订阅服务A写入的RocketMQ主题,并将消息以列表的形式缓存到Redis中。

  3. 服务C启动了一个守护线程来检查Redis中的消息号。如果缓存列表大小达到一定值,它会拉取所有消息并保存到MySQL,然后刷新Redis中的缓存。

你说你想

make the system can handle more incoming requests.

这不是看机器吗?

我认为在你的情况下,你应该考虑让你的应用程序具有所有服务的可扩展性。

在云端或自己构建。

喜欢 Kubernetes。 https://kubernetes.io/

或者基于 Kubernetes 构建的 KNative https://cloud.google.com/knative/

Amazon Web Services 还提供可扩展性。

高缩放与您要处理的负载密切相关:

但是您可以使用此事件总线模式处理多个请求:

1)服务A:将消息发布到事件总线(Topic/Exchange)
2) Broker(ActiveMq/RabbitMq/etc..): 将这些消息转发到队列中。
3)服务B:从队列中监听并更新MySQL.

中的记录

下游服务(服务 B)的多个实例将按需提供可伸缩性(如果负载较多,则部署更多实例,如果负载较少,则部署较少实例)。

简单地说,我可以把你的问题分成两个子主题。

But I plan to make it more expandable. It should be able to start more instance of each service and make the system can handle more incoming requests.

为了使您的应用程序对传入请求的响应更快,您需要

  • 减少请求处理时间
  • 垂直或水平扩展您的系统

如果您考虑第一种方法,您可以简单地引入更强大的硬件,优化传输层协议的使用或简单地删除不必要的处理步骤(例如:而不是使用步骤 B 和 C,您可以简单地引入 Kafka,如消息代理和可靠地在其中持久保存消息。这样你就可以删除 Redis 依赖项)

为了在您的系统中优化网络控制和协议使用,请参阅 High Performance Browser Networking 书籍。

为了扩展,考虑到负载,只需使用 Docker swarm 或 Kubernetes。最重要的是,您可以简化应用程序中的依赖关系以获得更好的性能和易于处理。

一如既往,一个问题可以有更多的解决方案。以下建议基于我作为软件架构师的日常工作和经验。

事实

您的系统由三个(微)服务(A、B 和 C)、消息代理 (RocketMQ)、缓存 (Redis) 和数据库 (MySQL) 组成。在评论中,您还提到您计划 运行 在 F5 硬件上 Docker。

建议

服务A暴露在前端处理HTTP请求。异步处理用于管理负载,但效率仍然受限于服务 A 的性能。因此,服务 A 应该是可扩展的,以实现更高的吞吐量。必须评估单个单元的性能(查看性能测试、压力测试...)以确定缩放比例。

要启用 Docker 容器的自动扩展,您需要 编排工具 (例如 Kubernetes),它会根据配置的指标扩展您的系统。还要考虑缩放系统可以使用的系统资源。

服务 B 和 C 也可以轻松扩展。评估服务 B 和服务 C 的功能是否可以加入单个服务。除了 B 只是将新数据放入 Redis 之外,它还可以将其存储在 MySQL 中。这取决于您需要多少碎片以及您将如何管理碎片带来的额外复杂性。 B 已经对发布的内容做出反应,而服务 C 似乎不断地为条目数量汇集 Redis 缓存(这可以通过键空间通知解决)。

从 Redis 读取数据、存储数据 MySQL 并刷新数据时要小心。当或如果您对写入其中的所有服务实例使用一个 Redis 密钥时,您很容易丢失或清除一些未存储在 MySQL 中的数据。

在处理异步处理时,您经常会处理最终一致性,这意味着服务 A 处理的数据不会立即可供可能想要从中读取它的其他服务使用MySQL(只是为了更广泛的考虑,重要性因情况而异)。