然后我在Ocelot项目中添加聚合器LeaderAdvancedAggregator,要实现这个聚合器,就必须实现来自Ocelot.Middleware.Multiplexer提供的接口IDefinedAggregator。
public class LeaderAdvancedAggregator : IDefinedAggregator { public async Task<DownstreamResponse> Aggregate(List<DownstreamResponse> responses) { List<string> results = new List<string>(); var contentBuilder = new StringBuilder(); contentBuilder.Append("{"); foreach (var down in responses) { string content = await down.Content.ReadAsStringAsync(); results.Add($"\"{Guid.NewGuid()}\":{content}"); } //来自leader的声音 results.Add($"\"{Guid.NewGuid()}\":{{comment:\"我是leader,我组织了他们两个进行调查\"}}"); contentBuilder.Append(string.Join(",", results)); contentBuilder.Append("}"); var stringContent = new StringContent(contentBuilder.ToString()) { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }; var headers = responses.SelectMany(x => x.Headers).ToList(); return new DownstreamResponse(stringContent, HttpStatusCode.OK, headers, "some reason"); } }当下游服务返回结果后,Ocelot就会调用聚合器的Aggregate方法,因此,我们的处理代码就写在这个方法中。
之后,我们就需要将聚合器在容器中进行注册
Startup.cs
运行,访问进阶请求聚合的Url:4727/aggrLeaderAdvanced,得到如下结果:
也许大家已经留意到,我在处理返回结果是,并没有像Ocelot内部返回结果一样使用路由的Key作为属性,而是使用了Guid。其实这也是我在做Demo时候的一处疑惑,我似乎无法像Ocelot内部一样处理。
在这个Aggregate方法中提供的参数类型只有List<DownstreamResponse>,但DownstreamResponse中并没有关于ReRouteKeys的信息。我查看了Ocelot的源码,ReRouteKeys只存在于DownstreamReRoute中,但我无法通过DownstreamResponse获取到DownstreamReRoute。
希望有知道的朋友能在留言区告诉我一下,感谢。
另外,这个聚合器也能像一般服务一样,可以使用依赖注入的方式添加依赖。我也尝试在案例中添加了一个依赖LeaderAdvancedDependency。如何使用依赖注入,我这里就不细说了,大家可以搜索 .net core依赖注入的相关资料。
LeaderAdvancedAggregator.cs
Startup.cs
services.AddSingleton<LeaderAdvancedDependency>();这样,我们就可以在聚合器中使用依赖了。
Ocelot除了支持Singleton的聚合器以外,还支持Transient的聚合器,大家可以按需使用。
Startup.cs
在前面的案例中,我们全部的路由配置中都是一组路由配置一个下游服务地址,也就意味着,当上游服务请求一个Url,Ocelot就必定转发给某一个固定的下游服务,但这样对于一个系统来说,这是不安全的,因为有可能某一个下游服务阻塞,甚至挂掉了,那就可能导致整个服务瘫痪了,对于当前快速运转的互联网时代,这是不允许的。
Ocelot能够通过可用的下游服务对每个路由进行负载平衡。我们来看看具体的路由配置
{ "DownstreamPathTemplate": "/api/ocelot/{postId}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 8001 }, { "Host": "localhost", "Port": 8002 } ], "UpstreamPathTemplate": "/ocelot/{postId}", "UpstreamHttpMethod": [ "Get" ], "LoadBalancerOptions": { "Type": "RoundRobin" } }LeadConnection负载均衡器算法共有4种:
LeastConnection 把新请求发送到现有请求最少的服务上
RoundRobin 轮询可用的服务并发送请求
NoLoadBalancer 不负载均衡,总是发往第一个可用的下游服务
CookieStickySessions 使用cookie关联所有相关的请求到制定的服务
为了能快速验证负载均衡器的有效性,我们这个案例中采用了RoundRobin轮询算法。然后下游服务还是用了案例一中建立的基本服务,在IIS中部署两套同样的下游服务,分别占用端口8001和8002。
当我们第一次请求:4727/ocelot/5,得到的是端口8001的返回结果
而当我们再次请求:4727/ocelot/5,得到的是端口8002的返回结果
再次请求则又是8001的返回结果,如此轮询下去。
但需要注意的是,当我尝试将8002端口服务停止时
我得到了这样的结果:第一次请求得到8001的返回结果,第二次请求得到的则是500的状态码
根据官网文档的说明
RoundRobin - loops through available services and sends requests. The algorythm state is not distributed across a cluster of Ocelot’s.