Ocelot之路由聚合

 

 

 

Ocelot之路由聚合

前言

通过上节介绍Ocelot快速实践”后,了解了Ocelot网关,Ocelot网关还提供了路由集合功能。

例如:在获取订单记录时,也需要查看订单中对应的商品信息,这里的数据就来源于两个微服务:订单服务、商品服务。如果不使用聚合路由时,对于现实一个订单信息时,客户端需要调用两次服务请求,实际上会造成服务端额外的性能消耗。

如果配置了聚合路由,客户端只需要请求一次聚合路由,然后聚合路由会合并订单服务和商品服务的请求结果到一个对象中,并返回给客户端。使用Ocelot的此特性可以让你很容易的实现前后端分离的架构。

环境:

 

VS2022 +.NET5.0 + Ocelot17.0.0.0

 

 

Ocelot路由聚合介绍

Ocelot允许声明路由聚合,这样可以把多个正常的Routes打包并映射到一个对象来对客户端的请求进行响应。

步骤

1. 为每个Route设置一个Key属性:如:"Key": "Catalog"

2. ocelot.json中添加Aggregates节点,并指定RouteKeys中指定1中设置的Key值组成的数组,并设置UpstreamPathTemplate匹配上游用户请求;它的工作方式和正常的Route类似。

 

 

 

 

项目演示

接下来我们就来验证该功能的实现。

在上节Ocelot快速实践”项目基础上进行改造,实现的目标是通过一个接口将多个接口的数据合并一起返回。项目机构如下:

 

 

 

2.1 修改接口服务

Step1 添加订单控制器“OrderController”用于取用户信息。代码如下:

namespace Yak.Ocelot.Api.Controllers

{

    [Produces("application/json")]

    [ApiController]

    [Route("api/[controller]/[action]")]

    public class UserController : ControllerBase

    {

        [HttpGet]

        public IActionResult GetSex(int id)

        {

            dynamic json;

            switch (id)

            {

                case 1:

                    json = new { id = 1, name = "yak" };

                    break;

                case 2:

                    json = new { id = 2, name = "zhang" };

                    break;

                default:

                    json = new { id = 3, name = "li" };

                    break;

            }

            return new JsonResult(json);

 

        }

 

        [HttpGet]

        public IActionResult GetAge(int id)

        {

            dynamic json;

            switch (id)

            {

                case 1:

                    json = new { id = 1, age = 23 };

                    break;

                case 2:

                    json = new { id = 2, age = 24 };

                    break;

                default:

                    json = new { id = 3, age = 25 };

                    break;

            }

            return new JsonResult(json);

        }

    }

}

 

Step2 添加用户控制器“UserController”用于取用户信息。代码如下:

namespace order_api.Controllers

{

    [ApiController]

    public class OrderController : ControllerBase

    {

        private ILogger _logger;

        public OrderController(ILogger<OrderController> logger)

        {

            _logger = logger;

        }

 

        [Route("api/Order/GetOrder")]

        [HttpGet]

        public IActionResult GetOrder(int id)

        {

            dynamic json;

            switch (id)

            {

                case 1:

                    json = new { id = 1, order = "一箱牛奶" };

                    break;

                case 2:

                    json = new { id = 2, order = "一台冰箱" };

                    break;

                default:

                    json = new { id = 3, order = "一台洗衣机" };

                    break;

            }

            return new JsonResult(json);

        }

 

    }

}

 

 

Step3 运行接口服务项目“Yak.Ocelot.Api”。

 

2.2 修改Ocelot网关配置

配置如下:

{

  "Routes": [

    {

      "DownstreamPathTemplate": "/WeatherForecast",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "localhost",

          "Port": 6000

        }

      ],

      "UpstreamPathTemplate": "/Weather",

      "UpstreamHttpMethod": [ "Get" ]

    },

    {

      "DownstreamPathTemplate": "/api/User/GetSex",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "localhost",

          "Port": 6000

        }

      ],

      "UpstreamPathTemplate": "/Sex",

      "UpstreamHttpMethod": [ "Get" ],

      "Key": "Sex"

    }

    ,

    {

      "DownstreamPathTemplate": "/api/User/GetAge",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "localhost",

          "Port": 6000

        }

      ],

      "UpstreamPathTemplate": "/Age",

      "UpstreamHttpMethod": [ "Get" ],

      "Key": "Age"

    }

    ,

    {

      "DownstreamPathTemplate": "/api/Order/GetOrder",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "localhost",

          "Port": 6000

        }

      ],

      "UpstreamPathTemplate": "/Order",

      "UpstreamHttpMethod": [ "Get" ],

      "Key": "Order"

    }

  ],

  "Aggregates": [

    {

      "RouteKeys": [

        "Sex",

        "Age",

        "Order"

      ],

      "UpstreamPathTemplate": "/GetUserOrderInfo"

    }

  ],

  "GlobalConfiguration": {

    "BaseUrl": "https://localhost:5000"

  }

}

 

2.3 验证路由聚合

Step1 运行网关项目“Yak.Ocelot.Gateway”。

 

 

 

 

Step2 通过网关访问聚合路由地址:“http://localhost:5000/GetUserOrderInfo?id=2”获取用户及他的订单。

 

 

 

 

 

 

 

2.4 接口异常

 

如接口异常,网关返回502代码,关闭接口服务,再访问网关。

 

 

 

 

 

2.5 自定义聚合

如果默认的聚合返回的结果数据结构不是我们想要的,想要修改怎么办?答案是使用自定义聚合

Step1 添加一个自动以聚合器MyAggregator, 必须实现IDefinedAggregator接口。这个聚合器的功能很简单,就是将两个聚合请求的结果,用逗号拼接起来返回

namespace Yak.Ocelot.Gateway

{

    public class MyAggregator : IDefinedAggregator

    {

        public MyAggregator()

        {

        }

        public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses)

        {

            List<string> result = new List<string>();

            result.Add($"\"{Guid.NewGuid()}\":{{comment:\"我是自定义聚合器返回内容\"}}");

            var merge = string.Join(";", result.ToArray());

            List<Header> headers = new List<Header>();

            return await Task.FromResult(new DownstreamResponse(new StringContent(merge), HttpStatusCode.OK, headers, "some reason"));

        }

    }

}

 

Step2 修改ocelot.json配置文件

 

  "Aggregates": [

    {

      "RouteKeys": [

        "Sex",

        "Age",

        "Order"

      ],

      "UpstreamPathTemplate": "/GetUserOrderInfo",

      "Aggregator": "MyAggregator"

    }

 

 

 

 

Step3 注册自定义聚合器,修改Startup文件。

 

 public void ConfigureServices(IServiceCollection services)

        {

 

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

        }

 

Step4 运行结果:

 

 

 

 

 

 

总结

通过网关将各个接口的数据合并。

请求聚合需要为每个Route设置一个Key,并设置Aggregates节点指定需要的RouteKeys。
请求聚合支持自定义设置返回结果:实现IDefinedAggregator接口,并注册自定义聚合器

鸣谢

https://www.cnblogs.com/letyouknowdotnet/p/10964529.html

https://www.cnblogs.com/cwsheng/p/13458472.html

https://www.jianshu.com/p/585396dc885a

源码

https://github.com/yandaniugithub/NETCore

 

 

posted @ 2022-04-16 22:07  春光牛牛  阅读(222)  评论(0编辑  收藏  举报