9. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Ocelot 网关--请求聚合

发布于:2025-02-27 ⋅ 阅读:(30) ⋅ 点赞:(0)

在微服务架构中,请求聚合的核心意义在于优化客户端与后端服务的交互效率,解决多服务协同的复杂性。通过将多个微服务的调用合并为单一请求,聚合层(如BFF或网关)可显著减少网络传输次数、降低延迟,同时统一数据格式以适配不同客户端(如移动端、Web端)的差异化需求。例如,移动端展示订单详情时,聚合层可并行调取用户、商品和物流服务的数据,整合后返回精简结果,避免客户端频繁发起请求。此外,聚合层还能处理数据裁剪(如过滤冗余字段)、事务边界管理(确保跨服务操作的一致性)及错误熔断(部分失败时降级响应),从而提升系统整体性能和容错能力。这种设计也强化了服务解耦,使各微服务专注核心功能,而聚合层承担业务编排职责,最终实现开发效率与用户体验的双重优化。

一、Ocelot请求聚合配置

  1. 静态聚合配置

    {
      "Aggregates": [
        {
          "RouteKeys": ["user-service", "product-service"],  // 需聚合的路由标识
          "UpstreamPathTemplate": "/composite/{id}",         // 客户端请求路径
          "Aggregator": "DefaultAggregator"                  // 默认聚合器
        }
      ],
      "Routes": [
        {
          "Key": "user-service",                             // 路由唯一标识(需与Aggregates关联)
          "UpstreamPathTemplate": "/users/{id}",            // 客户端请求匹配路径
          "DownstreamPathTemplate": "/api/users/{id}",      // 下游服务路径
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [                       // 静态指定下游地址
            { "Host": "localhost", "Port": 5001 }
          ],
          "UpstreamHttpMethod": [ "GET" ]                    // 允许的HTTP方法
        },
        {
          "Key": "product-service",
          "UpstreamPathTemplate": "/products/{id}",
          "DownstreamPathTemplate": "/api/products/{id}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            { "Host": "localhost", "Port": 5002 }
          ],
          "UpstreamHttpMethod": [ "GET" ]
        }
      ],
      "GlobalConfiguration": {
        "BaseUrl": "http://localhost:5000"                   // 网关对外暴露地址
      }
    }
    

    在上面配置中,Aggregates定义了聚合入口,RouteKeys关联下游路由的Key字段,Aggregator指定聚合器类型。 Routes中的每个路由都配置了Key,这个key必须全局唯一。

  2. 动态聚合配置
    如果自定义响应合并逻辑(如数据过滤、错误处理),就需要结合代码实现,首先调整配置:

    {
      "Aggregates": [
        {
          "RouteKeys": ["user-service", "product-service"],
          "UpstreamPathTemplate": "/composite/{id}",
          "Aggregator": "CustomAggregator"  // 自定义聚合器名称
        }
      ],
      "Routes": [
        // more routes
      ]
    }
    

    然后,新建继承自IDefinedAggregator接口的类CustomAggregator

    public class CustomAggregator : IDefinedAggregator
    {
        public async Task<DownstreamResponse> Aggregate(List<DownstreamResponse> responses)
        {
            // 解析用户服务响应
            var userJson = await responses[0].Content.ReadAsStringAsync();
            var user = JsonConvert.DeserializeObject<User>(userJson);
            
            // 解析商品服务响应
            var productJson = await responses[1].Content.ReadAsStringAsync();
            var product = JsonConvert.DeserializeObject<Product>(productJson);
            
            // 自定义合并逻辑(例如过滤敏感字段)
            var mergedData = new {
                UserName = user.Name,
                ProductPrice = product.Price,
                ProductStock = product.Stock
            };
            
            // 返回统一响应
            return new DownstreamResponse(
                new StringContent(JsonConvert.SerializeObject(mergedData)),
                HttpStatusCode.OK,
                new List<KeyValuePair<string, string>>()
            );
        }
    }
    

    最后,将自定义的响应合并逻辑代码注入到项目中:

    services.AddOcelot()
            .AddSingletonDefinedAggregator<CustomAggregator>();
    

Tip:注意事项:每个路由的Key需全局唯一,避免聚合冲突;聚合请求不保证事务性,需业务层处理跨服务数据同步问题;建议开启Ocelot日志或结合APM工具监控聚合请求耗时;对高频聚合请求启用FileCacheOptions缓存,降低下游负载;使用聚合功能时应充分考

二、总结

请求聚合是微服务架构中优化客户端交互的核心技术,通过网关(如Ocelot)合并多服务调用为单一请求,减少网络开销与延迟,适配多端数据需求。Ocelot支持静态聚合(通过JSON配置默认拼接响应)与动态聚合(自定义代码实现复杂逻辑),需配置Aggregates节点关联路由,并确保路由Key唯一。静态聚合适用于简单场景,动态聚合支持数据裁剪、错误熔断等高级功能,但需权衡性能与维护成本。实践中需注意事务一致性、监控聚合耗时,并通过缓存优化高频请求,最终实现服务解耦与性能提升的平衡。