FixedWindow.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Threading;
  4. using Sers.Core.Module.Message;
  5. using Sers.Core.Module.Rpc;
  6. using Sers.ServiceCenter.Entity;
  7. using Vit.Core.Util.ComponentModel.SsError;
  8. namespace Sers.Gover.RateLimit
  9. {
  10. /// <summary>
  11. /// 固定时间窗口限流
  12. /// </summary>
  13. public class FixedWindow: IRateLimit
  14. {
  15. /// <summary>
  16. /// 限流规则名称,一般对应一个类
  17. /// </summary>
  18. public string rateLimitType { get; set; }
  19. /// <summary>
  20. /// 限流项名称,必须唯一
  21. /// </summary>
  22. public string rateLimitKey { get; set; }
  23. /// <summary>
  24. /// 时间窗口内最大请求数
  25. /// </summary>
  26. public int reqLimit = 1000;
  27. /// <summary>
  28. /// 时间窗口ms
  29. /// </summary>
  30. public long msInterval = 1000;
  31. public SsError error = SsError.Err_RateLimit_Refuse;
  32. private int reqCount = 0;
  33. private long timeStampStart=0;
  34. private long timeStampEnd=0;
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. public SsError BeforeLoadBalancing(RpcContextData rpcData, ApiMessage requestMessage)
  37. {
  38. //以_开始的系统节点不限流
  39. var route = rpcData.route??"";
  40. if (route.Length>1&& '_' == route[1])
  41. {
  42. return null;
  43. }
  44. //TODO: don't use lock !!!
  45. lock (this)
  46. {
  47. DateTime dtNow = DateTime.Now;
  48. long now = dtNow.Ticks;
  49. if (now < timeStampEnd)
  50. {
  51. // 在时间窗口内
  52. // 判断当前时间窗口内是否超过最大请求控制数
  53. if (Interlocked.Increment(ref reqCount) > reqLimit)
  54. return error;
  55. else
  56. {
  57. return null;
  58. }
  59. }
  60. else
  61. {
  62. timeStampStart = now;
  63. //timeStampEnd = timeStampStart + msInterval;
  64. timeStampEnd = dtNow.AddMilliseconds(msInterval).Ticks;
  65. // 超时后重置
  66. reqCount = 1;
  67. return null;
  68. }
  69. }
  70. }
  71. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  72. public SsError BeforeCallRemoteApi(RpcContextData rpcData, ApiMessage requestMessage, ApiNode apiNode)
  73. {
  74. return null;
  75. }
  76. }
  77. }