我们在不添加任何API接口的情况下,声明一组下游服务不存在的路由,并将它添加到聚合路由当中。
"ReRoutes": [ ..., { "DownstreamPathTemplate": "/api/ocelot/aggrError/1", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 8001 } ], "UpstreamPathTemplate": "/ocelot/aggrError/1", "UpstreamHttpMethod": [ "Get" ], "Key": "aggr_error", "Priority": 2 } ], "Aggregates": [ { "ReRouteKeys": [ "aggr_willing", "aggr_jack", "aggr_error" ], "UpstreamPathTemplate": "/aggrLeader" } ]测试结果如下:
直接请求aggr_error
直接通过聚合路由访问
前面我说到返回结果好像有哪里不太对,那到底是哪里出错了呢?我来将返回的json串进行格式化一下。
{ "aggr_willing":我是Willing,还是多加工资最实际, path: /api/ocelot/aggrWilling, "aggr_jack":我是Jack,我非常珍惜现在的工作机会, path: /api/ocelot/aggrJack, "aggr_error": }我们会发现这并不是一个正确的json串,那到底为什么会这样呢?既然Ocelot是开源的,那我们就来深挖一下源码到底是怎么处理聚合请求返回结果的。
Ocelot Github:https://github.com/ThreeMammals/Ocelot
找到位于Ocelot.Middleware.Multiplexer中的一个类SimpleJsonResponseAggregator,静态方法MapAggregateContent。
因为我的下游服务返回结果是一个字符串,然后被Ocelot直接拼接到返回结果中,从而得到我们上面看到的结果。
因此,在我看来,当我们使用Ocelot的聚合路由功能时,下游服务的返回结果必须要保证是一个json串,这样才能最终被正确识别。
我把下游服务改一改,添加一个类,然后将API返回结果格式更改为这个类型。
public class ResponseResult { public string Comment { get; set; } } // GET api/ocelot/aggrWilling [HttpGet("aggrWilling")] public async Task<IActionResult> AggrWilling(int id) { var result = await Task.Run(() => { ResponseResult response = new ResponseResult() { Comment = $"我是Willing,还是多加工资最实际, path: {HttpContext.Request.Path}" }; return response; //return $"我是Willing,还是多加工资最实际, path: {HttpContext.Request.Path}"; }); return Ok(result); } // GET api/ocelot/aggrJack [HttpGet("aggrJack")] public async Task<IActionResult> AggrJack(int id) { var result = await Task.Run(() => { ResponseResult response = new ResponseResult() { Comment = $"我是Jack,我非常珍惜现在的工作机会, path: {HttpContext.Request.Path}" }; return response; //return $"我是Jack,我非常珍惜现在的工作机会, path: {HttpContext.Request.Path}"; }); return Ok(result); }运行看执行结果
简单总结为以下三点注意:
仅支持GET方式
下游服务返回类型要求为application/json
返回内容类型为application/json,不会返回404请求
进阶请求聚合在上一个案例中,我已经可以通过Willing和Jack的领导得到我想要的结果,但在这个过程中,他们的领导(聚合)都只是在帮我获得结果,没有对得到的结果做任何的干预。那如果领导想着,既然老板想要了解情况,自己当然也要干点活,让老板知道在这个过程中自己也是有出力的,这就涉及到进阶的请求聚合了。
在网上搜了一下关于进阶请求聚合的资料,好像没有怎么见到有相关实例的Demo,最全面的资料来自于官网文档说明,也许是在实际应用中这个功能不怎么被运用?或是我打开的方式不对?原因暂时未知,知道的朋友们可以在留言区给我说一下。那么我在这里就用实例给大家介绍一下。
Ocelot支持在获得下游服务返回结果后,通过一个聚合器对返回结果进行再一步的加工处理,目前支持内容,头和状态代码的修改。我们来看配置文件
"Aggregates": [ { "ReRouteKeys": [ "aggr_willing", "aggr_jack", "aggr_error" ], "UpstreamPathTemplate": "/aggrLeaderAdvanced", "Aggregator": "LeaderAdvancedAggregator" } ]因为是请求聚合的进阶,所以ReRoutes路由不需要任何更改。Aggregates中一组配置增加了属性Aggregator,表示当获得返回结果,由聚合器LeaderAdvancedAggregator进行处理。