1. 负载均衡
分布式架构中,当后端同一个应用的实例较多,负载均衡是非常必要的,否则前端对后端 API 的请求,可能只命中其中的几个应用实例,这几个实例压力会很大,而其他实例一直处于空闲状态,达不到分布式架构中利用服务器资源换取性能的效果。
Ocelot 网关提供了负载均衡功能,通过配置文件即可实现,下面是 Ocelot 负载均衡功能的 demo。
-
启动 CustomerService 的两个实例,修改以下之前的演示 api 让其返回不同的结果
启动实例1:
启动实例2:
在 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" }
2. 请求缓存
有些时候,为了提升 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之限流熔断