Ocelot(五)- 流量限制、服务质量

作者:markjiang7m2

原文地址:https://www.cnblogs.com/markjiang7m2/p/10965300.html

源码地址:https://gitee.com/Sevenm2/OcelotDemo

本文是我关于Ocelot系列文章的第五篇,流量限制、服务质量。Ocelot允许针对具体的服务接口进行流量限制,以便下游服务不会过载而影响响应速度。服务质量则是Ocelot根据下游服务响应的结果做出判断,当超过一定次数的响应失败时,Ocelot认为该服务不可用,自动产生熔断,在一定的时间范围内不再向该服务转发请求,同时Ocelot也支持自定义的请求超时时间,当下游响应超过设定的时间,会认为该服务响应失败。

关于更多的Ocelot功能介绍,可以查看我的系列文章

本文中涉及案例的完整代码都可以从我的代码仓库进行下载。

案例六 流量限制

Ocelot支持流量限制,只要在路由中添加RateLimitOptions配置即可

"RateLimitOptions": {
"ClientWhiteList": [
"markadmin"
],
"EnableRateLimiting": true,
"Period": "1m",
"PeriodTimespan": 30,
"Limit": 5
}
  • ClientWhiteList:数组,在请求头中包含ClientId=xxx的请求不受限流控制,其中ClientId这个key可以修改,xxx表示配置的白名单。
  • EnableRateLimiting:是否启用限流
  • Period:限流控制的时间周期,输入单位支持s(秒), m(分), h(时), d(天)
  • PeriodTimespan:恢复等待时间,当访问超过限流限制的次数后,需要等待的时间,单位为s,如当一分钟内访问超过5次,就需要等待30秒后,访问才会重新有效
  • Limit:一个时间周期内允许访问的最大次数。

下面来看案例,在ReRoutes中添加一组路由

{
"DownstreamPathTemplate": "/api/ocelot/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8001
}
],
"UpstreamPathTemplate": "/ocelot/ratelimit/{postId}",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 2,
"RateLimitOptions": {
"ClientWhiteList": [
"markadmin"
],
"EnableRateLimiting": true,
"Period": "1m",
"PeriodTimespan": 30,
"Limit": 5
}
}

在这里我只是添加多了一组路由,但下游服务接口是重用了之前使用过的接口,流量限制部分配置上面已经介绍过了。下面运行来看结果。

当我第一次访问http://localhost:4727/ocelot/ratelimit/5的时候,得到了正常的返回结果

而且,在请求头可以看到流量限制的相关信息

然后,我又很快地继续发出请求,可以看到,当我第六次发出请求的时候,得到了429 To Many Requests的状态

而此时的请求头信息也会不一样,这里可以看到Retry-After →28,意思是在28秒后可以恢复请求

这证明,我们的Ocelot网关流量限制的作用起效了,而且与我们的配置一致。

在等待30秒之后,我重新发出请求,又得到了正常的返回结果

当我在请求头中加上[ClientId]=markadmin后,清空Postman的请求记录,重新开始发出请求,无论请求多少次,Ocelot也不会对我的访问进行限流

这里对于PeriodTimespan(恢复等待时间)的算法,我倒是有点疑问的。我一开始的理解是,基于上面案例的配置,当一分钟内访问超过5次时,就需要等待Period + PeriodTimespan,也就是从第一个有效请求开始算起,一分半钟之后Ocelot才会重新正常转发请求,但是我做了几次重复实验,得到的结果都是:当一分钟内访问到第1次时,Ocelot开始进入PeriodTimespan时间内的倒计时,也就是实际的重置时间为PeriodTimespan

为了更加明确地验证这个问题,我使用OcelotConsole项目进行测试。

首先,修改路由配置如下:

{
"DownstreamPathTemplate": "/api/ocelot/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8001
}
],
"UpstreamPathTemplate": "/ocelot/ratelimit/{postId}",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 2,
"RateLimitOptions": {
"ClientWhiteList": [
"markadmin"
],
"EnableRateLimiting": true,
"Period": "1m",
"PeriodTimespan": 10,
"Limit": 5
}
}

然后,在OcelotConsole项目中添加代码如下:

public static async Task Main(string[] args)
{
using (var client = new HttpClient())
{
for (var i = 0; i < 100; i++)
{
Console.WriteLine(DateTime.Now); var result = await client.GetAsync("http://localhost:4727/ocelot/ratelimit/5");
Console.WriteLine($"{result.StatusCode}, {result.Content.ReadAsStringAsync().Result}");
System.Threading.Thread.Sleep(1000);
}
Console.Read();
}
}

每隔1s就发出一次请求,运行,在命令窗口得到以下输出:

2019/6/3 13:33:31
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:32
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:33
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:34
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:35
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:36
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:37
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:38
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:39
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:40
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:41
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:43
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:44
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:45
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:46
OK, This is from localhost:8001, path: /api/ocelot/5
2019/6/3 13:33:47
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:48
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:49
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:50
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.
2019/6/3 13:33:51
TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

然后,我又通过修改参数,得出如下结果:

  • PeriodTimespan=10, Limit=5:5个成功,5个失败
  • PeriodTimespan=10, Limit=6:6个成功,4个失败
  • PeriodTimespan=20, Limit=5:5个成功,15个失败
  • PeriodTimespan=30, Limit=5:5个成功,25个失败

似乎都是与我前面得到的结论相同,与官方文档不一致。

我在GitHub上提了一个issue:https://github.com/ThreeMammals/Ocelot/issues/910,期待能得到答复。

流量限制的全局配置

"RateLimitOptions": {
"DisableRateLimitHeaders": true,
"QuotaExceededMessage": "Customize Tips!",
"HttpStatusCode": 999,
"ClientIdHeader": "Test"
}
  • DisableRateLimitHeaders:当设为true时,请求头中就不会输出流量限制的相关信息,默认值:"false"
  • QuotaExceededMessage:当请求数量超出流量限制时,输出的信息,默认值:"API calls quota exceeded! maximum admitted {Limit} per {Period}."
  • HttpStatusCode:当请求数量超出流量限制时,输出的状态码,默认值:"429"
  • ClientIdHeader:标识为白名单中的客户端的请求头key,默认值:"ClientId"

案例七 服务质量

Ocelot支持服务质量与熔断,意味着当下游服务不可用时,Ocelot会进行自动熔断,不再将请求转发给该下游服务。来看看配置

"QoSOptions": {
"ExceptionsAllowedBeforeBreaking":3,
"DurationOfBreak":3000,
"TimeoutValue":5000
}
  • ExceptionsAllowedBeforeBreaking:允许异常次数,当Ocelot转发给该下游服务连续出现异常次数达到该数字时,Ocelot会进行自动熔断,一段时间内不再向该下游服务转发请求
  • DurationOfBreak:熔断时间,单位为ms(毫秒),持续多长时间不向该下游服务转发请求
  • TimeoutValue:服务质量配置项,超时时间,单位为ms(毫秒),当Ocelot向下游服务转发请求多长时间后,自动认为该请求超时

ExceptionsAllowedBeforeBreaking 必须跟 DurationOfBreak一起使用,TimeoutValue可以单独使用。

首先需要安装Polly支持程序,通过Nuget搜索Ocelot.Provider.Polly或者通过以下命令安装

Install-Package Ocelot.Provider.Polly

然后在Startup.cs中的ConfigureServices方法注册该中间件

using Ocelot.Provider.Polly;
public void ConfigureServices(IServiceCollection services)
{
……
services.AddOcelot()
.AddPolly();
……
}

ReRoutes中添加一组路由

{
"DownstreamPathTemplate": "/api/ocelot/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8001
}
],
"UpstreamPathTemplate": "/ocelot/qos/{postId}",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 2,
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 3000,
"TimeoutValue": 5000
}
}

为了看出熔断效果,我将8001端口的下游服务停止了,然后运行OcelotDemo项目

当第一次向网关发出请求时,得到500的状态码

连续3次请求过后,就会得到503的状态码,证明Ocelot已经产生熔断

总结

在这篇文章中就跟大家介绍了Ocelot的两个基础功能,在路由中进行配置即可使用,不需要依赖于第三方的服务。当然在我实践的过程中产生的一个疑问暂时还没得到答案,如果有知道原因的朋友也可以给我留言,感激不尽。

结合前面的几篇文章,大家在设计项目API网关的时候就可以综合地考虑到底哪些功能应该配置使用,如何适当地建立路由表。例外,我在这几个案例中为了突出要介绍的功能,基本上都是一组路由单独配置一个功能,而在实际项目中通常都是需要在一组路由当中同时配置多个功能的,希望大家在实际项目中能够灵活运用。今天就先跟大家介绍到这里,希望大家能持续关注我们。

Ocelot(五)- 流量限制、服务质量的更多相关文章

  1. .net core使用ocelot---第五篇 服务质量

    简介 .net core使用ocelot---第一篇 简单使用  .net core使用ocelot---第二篇 身份验证使用 .net core使用ocelot---第三篇 日志记录  .net c ...

  2. Ocelot中文文档-Websockets

    Ocelot额外支持代理websockets.这个功能在问题 212中被提出. 为了是Ocelot代理websocket,你需要做如下事情. 在你的Configure方法中,你要告知应用程序使用Web ...

  3. Ocelot网关+IdentityServer4实现API权限认证

    Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由.请求聚合.服务发现.认证.鉴权.限流熔断.并内置了负载均衡器与Service Fabric.Butterfly ...

  4. 庐山真面目之六微服务架构Consul集群、Ocelot网关集群和Nginx版本实现

    庐山真面目之六微服务架构Consul集群.Ocelot网关集群和Nginx版本实现 一.简介      在上一篇文章<庐山真面目之五微服务架构Consul集群.Ocelot网关和Nginx版本实 ...

  5. ITU-T Technical Paper: QoS的构建模块与机制

    本文翻译自ITU-T的Technical Paper:<How to increase QoS/QoE of IP-based platform(s) to regionally agreed ...

  6. QoS的构建模块与机制

    本文翻译自ITU-T的Technical Paper:<How to increase QoS/QoE of IP-based platform(s) to regionally agreed ...

  7. SDN三种模型解析

    数十年前,计算机科学家兼网络作家Andrew S. Tanenbaum讽刺标准过多难以选择,当然现在也是如此,比如软件定义网络模型的数量也很多.但是在考虑部署软件定义网络(SDN)或者试点之前,首先需 ...

  8. ovs-qos配置

    QoS配置 在许多网络场景中,都需要根据需求对网络流量部署服务质量(QoS)保障策略,比如限制指定主机的最大接入带宽等需求.本节将介绍如何在OVS上添加队列,并完成数据的入队操作,从而完成QoS策略部 ...

  9. Java生鲜电商平台-B2B生鲜的互联网思维

    Java生鲜电商平台-B2B生鲜的互联网思维 在互联网高速发展的今天,为我们的生活带来了众多便利.然而互联网从早期的萌芽状态到现在妇孺皆知,它的崛起速度远远超乎世人的想象.人们开始关注互联网并且研究它 ...

随机推荐

  1. Saiku_学习_02_Schema Workbench 开发mdx和模式文件

    一.前言 saiku的查询都是通过cube来进行的.因此每当我们要进行一次多维度查询时,都要先修改xml.上传.重启才能生效,不仅效率低,还不利于学习和理解MDX和模式文件. 通过 workbench ...

  2. 我对java的理解(一)——注解就是贴标签

    在现实生活中,贴标签这种现象比比皆是.去超市,去商场,每个或者每类物品都会有它的标签,甚至在我们自己身上也会有标签,比如,程序猿.逗逼.单身狗.80/90后.屌丝……呵呵,太多了.有时候,我们也会戏谑 ...

  3. 【python2/3坑】从gensim的Word2Vec.load()的中文vector模型输出时显示unicode码

    服务器上python2.7 打印出的e[0]对应的是 unicode码 于是分别尝试了用e[0].encode('utf-8')转码 和 e[0].decode('unicode-escape')依然 ...

  4. bzoj 4540: [Hnoi2016]序列 莫队

    题目: 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称a[s:t]是a ...

  5. MySQL读取各个my.cnf配置文件的先后顺序是:

    /etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf 其他自定义路径下的my.cnf,例如:/data/mysql/y ...

  6. Qt安装与配置

    安装Qt 安装Qt Creator,打开终端执行如下命令: sudo apt-get install qt5-default qtcreator -y 安装Qt示例和文档: sudo apt-get ...

  7. 利用SharedRegion实现核间共享

    导入SharedRegion模块 SharedRegion模块是一个共享区域,特别是对于多处理器环境下,SharedRegion模块就是用于让一个内存区域能被不同处理器共享并操作.这个模块会给每个处理 ...

  8. 人物-IT-张志东:张志东

    ylbtech-人物-IT-张志东:张志东 张志东,广东东莞人,腾讯创办人之一,腾讯高级副总裁兼科技总裁,于1993年取得深圳大学理学学士学位,并于1996年取得华南理工大学计算机应用及系统架构硕士学 ...

  9. lua 函数调用 -- 闭包详解和C调用

    转自:http://www.cnblogs.com/ringofthec/archive/2010/11/05/luaClosure.html 这里, 简单的记录一下lua中闭包的知识和C闭包调用 前 ...

  10. error: converting to execution character set: Invalid or incomplete multibyte or wide character

    交叉编译.c文件,遇到如下问题 arm-linux-gcc -o show_lines show_lines.c -lfreetype -lm show_lines.c:199:19: error: ...