负载均衡
分布式架构中,当后端同一个应用的实例较多,负载均衡是非常必要的,否则前端对后端API的请求,可能只命中其中的几个应用实例,这几个实例压力会很大,而其他实例一直处于空闲状态,达不到分布式架构中利用服务器资源换取性能的效果。
Ocelot网关提供了负载均衡功能,通过配置文件即可实现,下面是Ocelot负载均衡功能的demo。
-
启动CustomerService的两个实例,修改以下之前的演示api让其放回不同的结果
启动实例1:
启动实例2:
在nacos也可以看到注册上了CustomerService的两个实例
在nacos也可以看到注册上了CustomerService的两个实例 -
修改Ocelot网关配置
负载均衡主要配置LoadBalancerOptions节点,可以配置在Routes节点各个服务路由中,这将对单个服务起作用,也可以配置在GlobalConfiguration中,官方文档中说明GlobalConfiguration中的配置,将会覆盖Routes中各个路由的配置,但是17.0.1版本下经过测试发现并不起作用,在Routes节点有配置的情况下,必须针对每个服务进行配置,无法通过全局配置作用于所有的服务。
这里我依旧沿用上一节的动态路由,在Routes节点没有内容的情况下,在GlobalConfiguration中配置LoadBalancerOptions是可以的。
"GlobalConfiguration": { "RequestIdKey": null, "ServiceDiscoveryProvider": { "Type": "Nacos", // 为了使用动态路由必须配置Host和Port,查看DownstreamRouteFinderMiddleware中的IDownstreamRouteProviderFactory获取时, // 只有存在Host和Port的时候,才会获取到DownstreamRouteCreator,才能从url中解析出ServiceName "Host": "0.0.0.0", "Port": 8500 }, "DownstreamScheme": "http", "LoadBalancerOptions": { "Type": "RoundRobin" } }
Ocelot负载均衡策略提供四种默认的方式
○ RoundRobin
○ LeastConnection
○ NoLoadBalance
○ CookieStickySessions -
通过网关访问CustomerService的API
启动Ocelot网关,测试负载均衡
-
扩展负载均衡策略
如果觉得Ocelot提供的负载均衡策略不足以满足自己在工作的实际需求,Ocelot也支持自定义负载均衡策略。(1) 实现ILoadBalancer接口,实现自己的负载均衡策略逻辑
/// <summary> /// 自定义负载均衡策略 /// </summary> public class CustomerBalancer : ILoadBalancer { private readonly Func<Task<List<Service>>> _services; private readonly object _lock = new object(); private int _last; public CustomerBalancer(Func<Task<List<Service>>> services) { _services = services; } public async Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext) { var services = await _services(); lock (_lock) { if (_last >= services.Count) { _last = 0; } var next = services[_last]; _last++; return new OkResponse<ServiceHostAndPort>(next.HostAndPort); } } public void Release(ServiceHostAndPort hostAndPort) { } }
这里是轮询策略的实现的实现,只是一个演示。
(2) 将自定义负载均衡策略加入Ocelot依赖中
Func<IServiceProvider, DownstreamRoute, IServiceDiscoveryProvider, CustomerBalancer> loadBalancerFactoryFunc = (serviceProvider, Route, serviceDiscoveryProvider) => new CustomerBalancer(serviceDiscoveryProvider.Get); services.AddOcelot(Configuration) .AddNacosDiscovery() .AddCustomLoadBalancer(loadBalancerFactoryFunc);
(3) 配置文件中负载均衡策略改为我们自己的类型
"LoadBalancerOptions": { "Type": "CustomerBalancer" }
请求缓存
有些时候,为了提供API接口的访问速度,我们可能会将某些API接口的结果进行缓存,Ocelot网关也提供了这样的功能,通过FileCacheOptions配置对下游服务的URL进行缓存,目前只支持get方式,只要请求的URL不变,就会缓存。FileCacheOptions需要配置在Routes中的某个节点,在动态路由的情况下是不支持的。
"Routes": [
{
"UpstreamPathTemplate": "/Customer/{url}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"UseServiceDiscovery": true,
"ServiceName": "customerService",
"LoadBalancerOptions": {
"Type": "RoundRobin"
},
"FileCacheOptions": {
"TtlSeconds": 5,
"Region": "somename"
}
}
]
TtlSeconds是缓存时间,单位是秒,Region是缓存域,可以通过调用Ocelot的管理API来清除某个Region的缓存。
微服务系列文章:
上一篇:API网关—Ocelot之服务发现
下一篇:API网关—Ocelot之限流熔断