第六节:Ocelot之自身负载、网关限流、缓存和熔断机制
一. 自身负载
1. 含义
实现Ocelot转发多个业务服务器,不去Consul中获取,直接在配置文件中配置。
LoadBalancer将决定负载均衡的算法
- LeastConnection – 将请求发往最空闲的那个服务器
- RoundRobin – 轮流发送
- NoLoadBalance – 总是发往第一个请求或者是服务发现
2. 用到的项目
OcelotGateWay:网关
GoodsService:业务服务器
OrderService:业务服务器
3. 测试步骤
(1).启动Consul,【consul.exe agent -dev】,因为业务服务器中进行了服务注册,与Ocelot无关
(2).启动网关:【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020 】
其中GoodsService配置LeastConnection算法,OrderService配置RoundRobin算法。
配置文件
{ "Routes": [ { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7001 }, { "Host": "127.0.0.1", "Port": 7002 }, { "Host": "127.0.0.1", "Port": 7003 } ], "UpstreamPathTemplate": "/GoodsService/{url}", "LoadBalancerOptions": { "Type": "RoundRobin" //轮询 }, "UpstreamHttpMethod": [ "Get", "Post" ] }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7004 }, { "Host": "127.0.0.1", "Port": 7005 }, { "Host": "127.0.0.1", "Port": 7006 } ], "UpstreamPathTemplate": "/OrderService/{url}", "LoadBalancerOptions": { "Type": "LeastConnection" //最少连接数 }, "UpstreamHttpMethod": [ "Get", "Post" ] } ] }
(3).启动业务服务器:GoodsService对应7001、7002、7003端口,OrderService对应7004、7005、7006端口
dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001
dotnet GoodsService.dll --urls="http://*:7002" --ip="127.0.0.1" --port=7002
dotnet GoodsService.dll --urls="http://*:7003" --ip="127.0.0.1" --port=7003
dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004
dotnet OrderService.dll --urls="http://*:7005" --ip="127.0.0.1" --port=7005
dotnet OrderService.dll --urls="http://*:7006" --ip="127.0.0.1" --port=7006
(4). PostMan测试: Get测试: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123,多次请求,如图一
Post请求:http://127.0.0.1:7020/OrderService/Buy/pOrder1 ,多次请求,如图二
图一:
图二:
二. 限流
1. 含义
可以限制一段时间内请求数量,当超过这个数量,则截断请求不进行转发。
2. 核心配置剖析
(1). Routes下的配置
"RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": true, "Period": "10s", "PeriodTimespan": 10, "Limit": 2 }
- ClientWihteList 白名单
- EnableRateLimiting 是否启用限流
- Period 统计时间段:1s, 5m, 1h, 1d
- PeroidTimeSpan 多少秒之后客户端可以重试
- Limit 在统计时间段内允许的最大请求数量
(2).全局配置
"GlobalConfiguration": { "RateLimitOptions": { "DisableRateLimitHeaders": false, "QuotaExceededMessage": "您访问的网站流量处于流量高峰期,您的请求被截断了", "HttpStatusCode": 888, "ClientIdHeader": "xxxxx1" } }
- DisableRateLimitHeaders:Http头 X-Rate-Limit 和 Retry-After是否禁用。
- QuotaExceedMessage 当请求过载被截断时返回的消息。
- HttpStatusCode 当请求过载被截断时返回的http status。
- ClientIdHeader 用来识别客户端的请求头,默认是 ClientId。
核心配置分享:
{ "Routes": [ { //转发下游(业务服务器)的匹配规则 "DownstreamPathTemplate": "/api/{url}", //下游请求类型 "DownstreamScheme": "http", //下游的ip和端口,和上面的DownstreamPathTemplate匹配起来 "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7001 } ], //上游(即Ocelot)接收规则 "UpstreamPathTemplate": "/GoodsService/{url}", //上游接收请求类型 "UpstreamHttpMethod": [ "Get", "Post" ], "RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": true, "Period": "10s", "PeriodTimespan": 10, "Limit": 2 } }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7004 } ], "UpstreamPathTemplate": "/OrderService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ] } ], //全局配置 "GlobalConfiguration": { "RateLimitOptions": { "DisableRateLimitHeaders": false, "QuotaExceededMessage": "您访问的网站流量处于流量高峰期,您的请求被截断了", "HttpStatusCode": 888, "ClientIdHeader": "xxxxx1" } } }
3. 测试
(1). 启动网关:【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020 】
(2). 启动业务服务器:【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001 】
(3). PostMan测试: Get测试: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123, 快速点击到第三次
A.不使用全局配置的情况如下图:
B.使用全服配置的情况如下图:
三. 缓存
1. 含义
Ocelot可以对下游请求结果进行缓存 ,目前缓存的功能还不是很强大。它主要是依赖于[CacheManager](https://github.com/MichaCo/CacheManager) 来实现的。
2. 核心配置
(1).通过Nuget安装 Ocelot.Cache.CacheManager.【16.0.1】
(2).在Routes中配置:
"FileCacheOptions": { "TtlSeconds": 15, //过期时间(秒) "Region": "00001" //缓存分区名称 }
(3).ConfiguereSevice中配置:AddCacheManager(x =>{ x.WithDictionaryHandle();});
核心配置:
{ "Routes": [ { //转发下游(业务服务器)的匹配规则 "DownstreamPathTemplate": "/api/{url}", //下游请求类型 "DownstreamScheme": "http", //下游的ip和端口,和上面的DownstreamPathTemplate匹配起来 "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7001 } ], //上游(即Ocelot)接收规则 "UpstreamPathTemplate": "/GoodsService/{url}", //上游接收请求类型 "UpstreamHttpMethod": [ "Get", "Post" ], //缓存 "FileCacheOptions": { "TtlSeconds": 15, "Region": "00001" } }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7004 } ], "UpstreamPathTemplate": "/OrderService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ] } ] }
Startup:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //1.注册Ocelot var ocelot = services.AddOcelot(); //2. 给Ocelot注册Consul支持 (或者和上面写一起:services.AddOcelot().AddConsul();) ocelot.AddConsul(); //3.给Ocelot添加缓存支持 ocelot.AddCacheManager(x => { x.WithDictionaryHandle(); }); services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //1.使用Ocelot app.UseOcelot().Wait(); //这里不写异步用法了 app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
Api方法:
/// <summary> /// 测试Ocelot的缓存机制 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet] public string TestCache() { Random r = new Random(); var d1 = r.Next(1, 100000); var d2 = Guid.NewGuid().ToString("N"); return $"返回值为:d1={d1},d2={d2}"; }
3. 测试
(1). 启动网关:【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020 】
(2). 启动业务服务器:【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001 】
并在其中增加一个新的测试方法:TestCache,每次返回不同的随机数
(3). PostMan测试: Get测试: http://127.0.0.1:7020/GoodsService/Catalog/TestCache, 快速点击,发现返回值不变,15s后,产生了新的返回。
相关截图如下:
四. 熔断机制
1. 含义
熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且会增加下游服务器和API网关的负担。
2. 核心配置
(1). 通过Nuget安装 Ocelot.Provider.Polly. 【16.0.1】
(2). 在Routes配置:
"QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, //允许异常请求的个数 "DurationOfBreak": 10000, //熔断时间(毫秒) "TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自动将请求设置为超时 }
(3).ConfiguereSevice中配置:ocelot.AddPolly();
核心配置:
{ "Routes": [ { //转发下游(业务服务器)的匹配规则 "DownstreamPathTemplate": "/api/{url}", //下游请求类型 "DownstreamScheme": "http", //下游的ip和端口,和上面的DownstreamPathTemplate匹配起来 "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7001 } ], //上游(即Ocelot)接收规则 "UpstreamPathTemplate": "/GoodsService/{url}", //上游接收请求类型 "UpstreamHttpMethod": [ "Get", "Post" ], //熔断机制 "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, //允许异常请求的个数 "DurationOfBreak": 10000, //熔断时间(毫秒) "TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自动将请求设置为超时 } }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7004 } ], "UpstreamPathTemplate": "/OrderService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ] } ] }
Startup类:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //1.注册Ocelot var ocelot = services.AddOcelot(); //2. 给Ocelot注册Consul支持 (或者和上面写一起:services.AddOcelot().AddConsul();) ocelot.AddConsul(); //4.给Ocelot添加熔断机制 ocelot.AddPolly(); services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //1.使用Ocelot app.UseOcelot().Wait(); //这里不写异步用法了 app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
3. 测试
(1).启动网关:【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020 】
(2).不启动业务服务,也就是模拟业务服务器宕机的情况
(3).PostMan测试: Get测试: http://127.0.0.1:7020/GoodsService/Catalog/TestCache
A.快速点击3次,返回状态码为502 Bad Gateway
B.接着点击,返回状态码为503Service Unavailable,且是瞬间返回,说明已经熔断了
C.10秒后,再次点击,接着又是502 Bad Gateway
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。