NetCore Ocelot 之 Aggregator
Ocelot允许声明聚合路由,把多个Routes请求batch一个对象来对客户端的请求进行响应。
1、ocelot configuration
{
"DownstreamPathTemplate": "/api/service1",
"DownstreamScheme": "https",
"DownstreamHttpMethod": "Get",
"UpstreamHttpMethod": [ "Options", "Get", "Post", "Put", "Delete" ],
"UpstreamPathTemplate": "/Ocelot/service1",
//"UpstreamHost": "localhost",//404 Not found
"UseServiceDiscovery": true,
"ServiceName": "serviceA",
/*
LeastConnection
RoundRobin
NoLoadBalance
*/
"LoadBalancerOptions": {
"Type": "CustomRandomLoadBalancer"
},
"authenticationoptions": {
"authenticationproviderkey": "authenticationkey",
"allowedscopes": []
},
"Key": "service1",
"Priority": 11
},
{
"DownstreamPathTemplate": "/api/service2",
"DownstreamScheme": "https",
"DownstreamHttpMethod": "Get",
"UpstreamHttpMethod": [ "Options", "Get", "Post", "Put", "Delete" ],
"UpstreamPathTemplate": "/Ocelot/service2",
//"UpstreamHost": "localhost",//404 Not found
"UseServiceDiscovery": true,
"ServiceName": "serviceA",
/*
LeastConnection
RoundRobin
NoLoadBalance
*/
"LoadBalancerOptions": {
"Type": "CustomRandomLoadBalancer"
},
"authenticationoptions": {
"authenticationproviderkey": "authenticationkey",
"allowedscopes": []
},
"Key": "service2",
"Priority": 12
}
],
"Aggregates": [
{
"RouteKeys": [
"service1",
"service2"
],
"UpstreamPathTemplate": "/aggreate"
}
2、创建demo NetCore API controller, service1 & service2 类似
[Route("api/[controller]")] [ApiController] public class Service2Controller : Controller { [HttpGet] public IActionResult Index([FromServices] IConfiguration configuration) { var result = new { msg = $"This is service2, current date: {DateTime.Now:G}", ip = configuration["ip"], port = configuration["port"] }; return new JsonResult(result); } }
3、执行结果
如何自定义聚合,在Aggregate节点添加Aggregator配置
"Aggregates": [
{
"RouteKeys": [
"service1",
"service2"
],
"UpstreamPathTemplate": "/aggreate",
"Aggregator": "CustomAdvancedAggregator"
}
]
builder.Services.AddOcelot() .AddSingletonDefinedAggregator<CustomAdvancedAggregator>() .AddCustomLoadBalancer((serviceProvider, route, serviceDiscoveryProvider) => new CustomRandomLoadBalancer(serviceDiscoveryProvider.Get)) .AddConsul() .AddPolly();
public class CustomAdvancedAggregator : IDefinedAggregator { public CustomAdvancedAggregator() { } public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses) { var stringContent = new List<string>(); foreach (var response in responses) { byte[] bytes = new byte[response.Response.Body.Length]; await response.Response.Body.ReadAsync(bytes, 0, bytes.Length); var content = Encoding.UTF8.GetString(bytes); stringContent.Add(content); } var headers = responses.SelectMany(r => r.Response.Headers.Select(h => new Header(h.Key, h.Value))).Distinct().ToList(); var downstreamResponse = new DownstreamResponse(new StringContent(String.Join(";",stringContent)), System.Net.HttpStatusCode.OK, headers, "custom aggregate"); return downstreamResponse; } }
OK, 搞定!