打不死的小強(qiáng) .net core 微服務(wù) 快速開發(fā)框架 Viper 限流
來源
https://www.cnblogs.com/duyanming/p/13846451.html
1、Viper是什么?
Viper 是.NET平臺下的Anno微服務(wù)框架的一個示例項目。入門簡單、安全、穩(wěn)定、高可用、全平臺可監(jiān)控。底層通訊可以隨意切換thrift?grpc。?自帶服務(wù)發(fā)現(xiàn)、調(diào)用鏈追蹤、Cron 調(diào)度、限流、事件總線、CQRS 、DDD、類似MVC的開發(fā)體驗,插件化開發(fā)
一個不可監(jiān)控的微服務(wù)平臺是可怕的,出了問題?難以準(zhǔn)確定位問題的根源, Anno則提供了一套完整的監(jiān)控體系,包括鏈路追蹤、服務(wù)占用的系統(tǒng)資源、系統(tǒng)自身?CPU、內(nèi)存、硬盤使用率實(shí)時可監(jiān)控等等。
今天要說的是.netcore 微服務(wù)Viper的限流,防止惡意攻擊,做一個打不死的小強(qiáng)。

github:
https://github.com/duyanming/Viper
文檔地址:
https://duyanming.github.io/
體驗地址:(體驗用戶為anno 密碼123456 同一時間一個用戶只能在一個終端登錄用戶多的時候可能發(fā)生強(qiáng)制退出的情況,稍后登錄體驗)
http://140.143.207.244/
?
2、限流Anno.RateLimit
限流用到兩個庫 Anno.RateLimit、IPAddressRange。Anno.RateLimit為限流組件,IPAddressRange為IP匹配組件。
IPAddressRange地址:https://github.com/jsakamoto/ipaddressrange
using NetTools;...// rangeA.Begin is "192.168.0.0", and rangeA.End is "192.168.0.255".var rangeA = IPAddressRange.Parse("192.168.0.0/255.255.255.0");rangeA.Contains(IPAddress.Parse("192.168.0.34")); // is True.rangeA.Contains(IPAddress.Parse("192.168.10.1")); // is False.rangeA.ToCidrString(); // is 192.168.0.0/24// rangeB.Begin is "192.168.0.10", and rangeB.End is "192.168.10.20".var rangeB1 = IPAddressRange.Parse("192.168.0.10 - 192.168.10.20");rangeB1.Contains(IPAddress.Parse("192.168.3.45")); // is True.rangeB1.Contains(IPAddress.Parse("192.168.0.9")); // is False.// Support shortcut range description.// ("192.168.10.10-20" means range of begin:192.168.10.10 to end:192.168.10.20.)var rangeB2 = IPAddressRange.Parse("192.168.10.10-20");// Support CIDR expression and IPv6.var rangeC = IPAddressRange.Parse("fe80::/10");rangeC.Contains(IPAddress.Parse("fe80::d503:4ee:3882:c586%3")); // is True.rangeC.Contains(IPAddress.Parse("::1")); // is False.// "Contains()" method also support IPAddressRange argument.var rangeD1 = IPAddressRange.Parse("192.168.0.0/16");var rangeD2 = IPAddressRange.Parse("192.168.10.0/24");rangeD1.Contains(rangeD2); // is True.// IEnumerablesupport, it's lazy evaluation. foreach (var ip in IPAddressRange.Parse("192.168.0.1/23")){Console.WriteLine(ip);}// You can use LINQ via "AsEnumerable()" method.var longValues = IPAddressRange.Parse("192.168.0.1/23").AsEnumerable().Select(ip => BitConvert.ToInt32(ip.GetAddressBytes(), 0)).Select(adr => adr.ToString("X8"));Console.WriteLine(string.Join(",", longValues);// Constructors from IPAddress objects.var ipBegin = IPAddress.Parse("192.168.0.1");var ipEnd = IPAddress.Parse("192.168.0.128");var ipSubnet = IPAddress.Parse("255.255.255.0");var rangeE = new IPAddressRange(); // This means "0.0.0.0/0".var rangeF = new IPAddressRange(ipBegin, ipEnd);var rangeG = new IPAddressRange(ipBegin, maskLength: 24);var rangeH = new IPAddressRange(ipBegin, IPAddressRange.SubnetMaskLength(ipSubnet));// Calculates Cidr subnetsvar rangeI = IPAddressRange.Parse("192.168.0.0-192.168.0.254");rangeI.ToCidrString(); // is 192.168.0.0/24
?Anno.RateLimit限流組件的使用
?Anno.RateLimit支持令牌桶和漏桶兩種算法
using System;using System.Collections.Generic;using System.Text;using System.Threading;using System.Threading.Tasks;using Anno.RateLimit;namespace ConsoleTest{////// 限流測試///public class RateLimitTest{////// 限流測試///public void Handle(){var service = LimitingFactory.Build(TimeSpan.FromSeconds(1),LimitingType.TokenBucket, 20, 5);Console.Write("請輸入線程數(shù):");long.TryParse(Console.ReadLine(), out long th);for (int i = 0; i < th; i++){var t = Task.Factory.StartNew(() =>{while (true){var result = service.Request();//如果返回true,說明可以進(jìn)行業(yè)務(wù)處理,否則需要繼續(xù)等待if (result){Console.WriteLine($"{DateTime.Now}--{Task.CurrentId}---ok");//業(yè)務(wù)處理......}elseThread.Sleep(100);}}, TaskCreationOptions.LongRunning);}}}}
3、Viper限流
下圖是用Jmeter測試線上http://140.143.207.244/?的截圖,下圖紅色部分為限流直接返回失敗的記錄,調(diào)用方為?NewApi目標(biāo)服務(wù)為NewApi可以看到范圍的信息為Trigger current limiting,
通過限流保證Viper成為一個打不死的小強(qiáng)

配置Viper的限流
{"Target": {"AppName": "ApiGateway","IpAddress": "127.0.0.1","Port": 7010,"TraceOnOff": true},"Limit": {"Enable": true,"TagLimits": [{"channel": "*","router": "*","timeSpan": "1",//限流周期單位秒"rps": 100,//周期內(nèi)通過的請求個數(shù)"limitSize": 100//令牌桶,漏桶池子大小}],"IpLimit": {//ip限流"timeSpan": 1,//限流周期單位秒"rps": 100,//周期內(nèi)通過的請求個數(shù)"limitSize": 100//池子大小},"White": [//白名單 用法可以參考IPAddressRange"0.0.0.1","192.168.1.2","192.168.2.18"],"Black": [//黑名單"0.0.0.2","192.168.3.18"]}}
Limit.Enable:是否啟用限流
Limit.TagLimits:根據(jù)Tag限流
channel: Anno.Plugs.Logic//請求tag 必須參數(shù)router: Platform //模塊名稱(沒有Module) 必須參數(shù)method: GetFunc //模塊方法 必須參數(shù)profile: fSFhFv5d4ZlC/JTz1EvoBDNWTr+sNtAhKWTuykqfZHU2oB8/W7aUayqsXmFJXPlRuname: yrm
Limit.IpLimit:根據(jù)客戶端Ip限流
Limit.White:白名單
Limit.IpLimit:黑名單
?關(guān)于更多的Viper限流細(xì)節(jié)可參考github:https://github.com/duyanming/Viper/blob/master/Viper/Extensions/Middleware/DymWebHostBuilderExtensions.cs
?以上分享了,Viper網(wǎng)關(guān)的限流。后面分享每個微服務(wù)如何通過注解方式限流、以及請求緩存、ViperService的 全局過濾器、模塊過濾器、方法過濾器。
過濾器類型有,授權(quán)過濾器、異常過濾器、Action過濾器。Anno.EngineData.Filters
兩種常用算法
令牌桶(Token Bucket)和漏桶(leaky bucket)是 最常用的兩種限流的算法。
令牌桶主要是控制注入的速度,漏桶則是控制出的速度。
漏桶算法

?
?
令牌桶算法

?
?
關(guān)于更多限流只是可參考:
張善友博客:https://www.cnblogs.com/shanyou/p/4280546.html
凌晨三點(diǎn)半:https://www.cnblogs.com/vveiliang/p/9049393.html
?Viper
github:
https://github.com/duyanming/Viper
文檔地址:
https://duyanming.github.io/
體驗地址:(體驗用戶為anno 密碼123456 同一時間一個用戶只能在一個終端登錄用戶多的時候可能發(fā)生強(qiáng)制退出的情況,稍后登錄體驗)
http://140.143.207.244/
?
關(guān)于Viper的更多內(nèi)容,隨后更新。敬請關(guān)注。開源不易,感謝Star。
