在微服务架构下,若大量请求超过微服务的处理能力时,可能会将服务打跨,甚至产生雪崩效应、影响系统的整体稳定性。比如说你的用户服务处理能力是1w/s,现在因为异常流量或其他原因,有10w的并发请求访问你的服务,那服务肯定扛不住啊。这种情况下,我们可以在流量超出承受阈值时,直接进行”限流”、拒绝部分请求,从而保证系统的整体稳定性。
Ocelot提供限流功能,这个功能是由张善友大大贡献的,只要通过配置就可以实现,我们可以将以下配置放在全局配置中。
"RateLimitOptions": {
"DisableRateLimitHeaders": false, // Http头 X-Rate-Limit 和 Retry-After 是否禁用
"QuotaExceededMessage": "too may required, please wait and retry", // 当请求过载被截断时返回的消息
"HttpStatusCode": 999, // 当请求过载被截断时返回的http status
"ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId
}
其他的一些配置需要针对每个服务进行配置,我这里因为使用动态路由,所以来需要增加一个DynamicRoutes节点,根据路由名称进行配置。如果是手动配置路由列表,请在Routes节点中配置
"DynamicRoutes": [
{
"ServiceName": "customerService",
"RateLimitRule": {
"ClientWhitelist": [ "admin" ], // 白名单
"EnableRateLimiting": true, // 是否启用限流
"Period": "1m", // 统计时间段:1s, 5m, 1h, 1d
"PeriodTimespan": 15, // 多少秒之后客户端可以重试
"Limit": 5 // 在统计时间段内允许的最大请求数量
}
}
]
在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与发现的方式互相依赖。
由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。
为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。一般在微服架构中,有一个组件角色叫熔断器,就像电路中的保险丝一样。顾名思义,熔断器起的作用就是在特定的场景下关掉当前的通路,从而起到保护整个系统的效果。
Ocelot中提供了熔断功能,这个功能是使用Polly实现的,使用熔断功能示例如下:
(1)安装Ocelot.Provider.Polly包
Install-package Ocelot.Provider.Polly
(2)添加依赖注入
public virtual void ConfigureServices(IServiceCollection services)
{
services.AddOcelot()
.AddPolly();
}
(3)修改配置文件
熔断功能无法在动态路由的情况下使用,QoSOptions必须配置在Routes节点中。
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 2, // 允许多少个异常请求
"DurationOfBreak": 3000, // 熔断的时间,单位为毫秒
"TimeoutValue": 2000 // 如果下游请求的处理时间超过多少则视如该请求超时
}
(4)修改一下API接口,使接口在2次请求之后需要进入3秒等待,用于测试
private static int _count = 0;
[HttpGet]
public IEnumerable<string> Get()
{
if(_count++ > 2)
{
Task.Delay(System.TimeSpan.FromSeconds(3)).GetAwaiter().GetResult();
}
return new[] { "cutsomer service2" };
}
参考文献:
.NET Core微服务之基于Ocelot实现API网关服务(续)
微服务系列文章:
上一篇:API网关—Ocelot之负载均衡
下一篇:分布式跟踪—SkyWalking