如何在 .NET 中对服务的工作负载进行负载平衡

How to load-balance the workload of a service in .NET

我正在考虑使用面向服务的体系结构 (SOA) 构建应用程序。

这种架构不像微服务解决方案那样复杂和混乱(我认为),但我面临着类似的设计问题。想象一下,我有 ServiceA 类型的服务将工作发送到 ServiceB 类型的服务。我想,如果我使用队列,那么负载平衡将不是问题(因为消费者将从队列中获取他们可以处理的内容)。但是队列往往会在代码中产生一些不良的异步,需要额外的努力来修复。因此,我更倾向于在服务之间使用 HTTP 调用,利用 C# 高效而惊人的 async/await 特性。但这会在共享工作负载和检测饱和或停止的服务方面产生问题。

所以我的问题是:

  1. 是否有支持某种 async/await 功能的队列,其功能类似于 HTTP 调用,returns 在您需要的地方返回结果,而不是在您无法继续原始操作的回调中执行流程?
  2. 如何在使用 HTTP 时对服务之间的流量进行负载平衡并检测不适合新分配的节点?我的意思是,我可能可以自己从头开始设计一些东西,但现在应该有一些标准的方法、库或框架可以做到这一点。我在网上找到的最好的是 this,但它是为微服务构建的,所以我不确定我是否可以毫无问题地使用它。

更新: 我现在发现了这个问题,它也要求等待队列:awaitable Task based queue ...还发现了 Kubernetes、Marathon 等。

关于您的第一个问题,NServiceBus 是 .NET 的商业框架,它抽象消息传输并在其之上添加许多功能,具有您正在寻找的确切功能。他们实际上称它为“callbacks”,用法如下:

假设您有一条要发送到后端服务的消息和一个您希望返回的响应,您会在 ServiceA 中这样做:

var message = new Message();
var response = await endpoint.Request<ResponseMessage>(message);
log.Info($"Callback received with response:{response.Result}");

其中端点是允许您发送消息和接收消息的 NServiceBus 工件。

这个简单语法的作用是将 Message 放入队列中并等待(异步)直到消息已被后端服务处理并回复它。响应是队列中 Response 类型的消息。

在 ServiceB 中,你会做:

public class Handler : IHandleMessages<Message>
{
  public Task Handle(Message message, IMessageHandlerContext context)
  {
    var responseMessage = new ResponseMessage
    {
        Result = "TheResult"
    };
    return context.Reply(responseMessage);
  }
}

这允许您让多个 ServiceA 节点向多个 ServiceB 节点(单个 queueu 上的竞争消费者)发送消息。 NServiceBus 负责将每个给定消息的响应路由到正确的 ServerA。

请注意,这样做的缺点是如果 ServerA 在等待响应时出现故障,您将永远不会收到响应。因此,不建议在大多数情况下使用此模式。

关于您的第 2 个问题,我认为负载均衡器可以完成这项工作。对于更复杂的场景,您可以查看 Service Fabric.