RateLimitMng.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Linq;
  4. using System.Runtime.CompilerServices;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Linq;
  7. using Sers.Core.Module.Message;
  8. using Sers.Core.Module.Rpc;
  9. using Sers.ServiceCenter.Entity;
  10. using Vit.Core.Util.ComponentModel.SsError;
  11. using Vit.Extensions;
  12. namespace Sers.Gover.RateLimit
  13. {
  14. public class RateLimitMng
  15. {
  16. /// <summary>
  17. /// rateLimitType -> RateLimitType 限制
  18. /// </summary>
  19. [JsonIgnore]
  20. ConcurrentDictionary<string, Type> limitType_Map = new ConcurrentDictionary<string, Type>();
  21. /// <summary>
  22. /// rateLimitKey -> IRateLimit 映射
  23. /// </summary>
  24. [JsonProperty]
  25. ConcurrentDictionary<string, IRateLimit> limit_Map = new ConcurrentDictionary<string, IRateLimit>();
  26. private IRateLimit[] limits=new IRateLimit[0];
  27. public RateLimitMng()
  28. {
  29. LimitType_Add("FixedWindow", typeof(FixedWindow));
  30. }
  31. #region 服务限流规则 管理
  32. public void LimitType_Add(string rateLimitType, Type type)
  33. {
  34. limitType_Map[rateLimitType] = type;
  35. }
  36. public void LimitType_Remove(string rateLimitType)
  37. {
  38. limitType_Map.TryRemove(rateLimitType, out _);
  39. }
  40. #endregion
  41. #region 服务限流项管理
  42. /// <summary>
  43. /// 获取所有限流项目
  44. /// </summary>
  45. /// <returns></returns>
  46. public IRateLimit[] RateLimit_GetAll()
  47. {
  48. return limits;
  49. }
  50. public void RateLimit_Remove(string rateLimitKey)
  51. {
  52. if (limit_Map.TryRemove(rateLimitKey, out _))
  53. {
  54. limits = limit_Map.Values.ToArray();
  55. }
  56. }
  57. public bool RateLimit_Add(JObject rateLimit)
  58. {
  59. if (!limitType_Map.TryGetValue(rateLimit["rateLimitType"].Value<string>(),out var type)) return false;
  60. var limitItem=rateLimit.Deserialize(type) as IRateLimit;
  61. if (null == limitItem) return false;
  62. limit_Map[limitItem.rateLimitKey] = limitItem;
  63. limits = limit_Map.Values.ToArray();
  64. return true;
  65. }
  66. #endregion
  67. #region 接口调用时触发的事件
  68. /// <summary>
  69. /// 若返回不为null,则对应服务被限流(服务直接返回对应错误)
  70. /// </summary>
  71. /// <param name="rpcData"></param>
  72. /// <param name="requestMessage"></param>
  73. /// <returns></returns>
  74. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  75. public SsError BeforeLoadBalancing(RpcContextData rpcData, ApiMessage requestMessage)
  76. {
  77. foreach (var rateLimit in limits)
  78. {
  79. var error = rateLimit.BeforeLoadBalancing(rpcData, requestMessage);
  80. if (null != error)
  81. return error;
  82. }
  83. return null;
  84. }
  85. /// <summary>
  86. /// 若返回不为null,则对应服务被限流(服务直接返回对应错误)
  87. /// </summary>
  88. /// <param name="rpcData"></param>
  89. /// <param name="requestMessage"></param>
  90. /// <param name="apiNode"></param>
  91. /// <returns></returns>
  92. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  93. public SsError BeforeCallRemoteApi(RpcContextData rpcData, ApiMessage requestMessage,ApiNode apiNode)
  94. {
  95. foreach (var rateLimit in limits)
  96. {
  97. var error = rateLimit.BeforeCallRemoteApi(rpcData, requestMessage, apiNode);
  98. if (null != error)
  99. return error;
  100. }
  101. return null;
  102. }
  103. #endregion
  104. }
  105. }