Skip to content

Commit

Permalink
Merge pull request #4 from 239573049/feature/rate-limit
Browse files Browse the repository at this point in the history
Feature/rate limit
  • Loading branch information
239573049 authored Apr 11, 2024
2 parents fecd609 + 4aab755 commit a3f10ca
Show file tree
Hide file tree
Showing 22 changed files with 1,140 additions and 12 deletions.
24 changes: 24 additions & 0 deletions src/FastGateway.Core/RateLimitType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace FastGateway.Core;

public enum RateLimitType : byte
{
/// <summary>
/// 并发策略
/// </summary>
Concurrent = 1,

/// <summary>
/// 令牌桶
/// </summary>
TokenBucket = 2,

/// <summary>
/// 滑动窗口
/// </summary>
SlidingWindow = 3,

/// <summary>
/// 固定窗口
/// </summary>
FixedWindow = 4
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public sealed class StatisticsBackgroundService(IServiceProvider serviceProvider
Channel.CreateUnbounded<StatisticRequestCountDto>();

private static readonly ConcurrentDictionary<string, StatisticRequestCountDto> RequestCountDic = new(-1, 5);
private static readonly ConcurrentDictionary<string, StatisticIpDto> IpDic = new();
private static readonly ConcurrentDictionary<string, StatisticIpDto> IpDic = new(-1,5);

private static readonly Channel<StatisticIpDto> StatisticIpChannel = Channel.CreateUnbounded<StatisticIpDto>();

Expand Down
3 changes: 2 additions & 1 deletion src/FastGateway/Domain/Location.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// 服务节点管理
/// </summary>
[Table(Name = "location")]
[Index("location_serviceid", "ServiceId")]
public class Location
{
public string Id { get; set; }
Expand Down Expand Up @@ -35,7 +36,7 @@ public sealed class LocationService
/// </summary>
[Column(MapType = typeof(string), StringLength = -1)]
public Dictionary<string, string> AddHeader { get; set; } = new();

/// <summary>
/// 静态文件或目录
/// </summary>
Expand Down
91 changes: 91 additions & 0 deletions src/FastGateway/Domain/RateLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
namespace FastGateway.Domain;

public sealed class RateLimit
{
/// <summary>
/// 限流策略名称
/// </summary>
[Column(IsIdentity = true)]
public string Name { get; set; }

/// <summary>
/// 是否启用
/// </summary>
public bool Enable { get; set; }

/// <summary>
/// 通用规则列表
/// </summary>
[Column(MapType = typeof(string), StringLength = -1)]
public List<GeneralRules> GeneralRules { get; set; }

/// <summary>
/// 端点白名单
/// </summary>
[Column(MapType = typeof(string), StringLength = -1)]
public List<string> EndpointWhitelist { get; set; }

/// <summary>
/// 客户端ID头部
/// </summary>
public string ClientIdHeader { get; set; } = "X-ClientId";

/// <summary>
/// 客户端白名单
/// </summary>
[Column(MapType = typeof(string), StringLength = -1)]
public List<string> ClientWhitelist { get; set; }

/// <summary>
/// 真实IP头部
/// </summary>
public string RealIpHeader { get; set; } = "X-Real-IP";

/// <summary>
/// IP白名单
/// </summary>
[Column(MapType = typeof(string), StringLength = -1)]
public List<string> IpWhitelist { get; set; }

/// <summary>
/// HTTP状态码
/// </summary>
public int HttpStatusCode { get; set; } = 429;

/// <summary>
/// 超出配额消息
/// </summary>
public string QuotaExceededMessage { get; set; }

/// <summary>
/// 错误内容类型
/// </summary>
public string RateLimitContentType { get; set; } = "text/html";

/// <summary>
/// 速率限制计数器前缀
/// </summary>
public string RateLimitCounterPrefix { get; set; } = "crlc";

/// <summary>
/// 启用端点速率限制
/// </summary>
public bool EnableEndpointRateLimiting { get; set; }

/// <summary>
/// 禁用速率限制头部
/// </summary>
public bool DisableRateLimitHeaders { get; set; }

/// <summary>
/// 启用正则规则匹配
/// </summary>
public bool EnableRegexRuleMatching { get; set; }
}

public class GeneralRules
{
public string Endpoint { get; set; }
public string Period { get; set; }
public int Limit { get; set; }
}
8 changes: 7 additions & 1 deletion src/FastGateway/Domain/Service.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FreeSql.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using FreeSql.DataAnnotations;

namespace FastGateway.Domain;

Expand Down Expand Up @@ -56,4 +57,9 @@ public class Service
/// </summary>
[Navigate(nameof(Location.ServiceId))]
public virtual List<Location> Locations { get; set; }

public string? RateLimitName { get; set; }

[Column(IsIgnore = true)]
public virtual RateLimit? RateLimit { get; set; }
}
3 changes: 3 additions & 0 deletions src/FastGateway/Domain/StatisticIp.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace FastGateway.Domain;

[Table(Name = "statistic_ip")]
[Index("statistic_ip_year", "Year")]
[Index("statistic_ip_month", "Month")]
[Index("statistic_ip_day", "Day")]
public sealed class StatisticIp
{
[Column(IsIdentity = true)]
Expand Down
3 changes: 3 additions & 0 deletions src/FastGateway/Domain/StatisticRequestCount.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace FastGateway.Domain;

[Table(Name = "statistic_request_count")]
[Index("statistic_request_count_year", "Year")]
[Index("statistic_request_count_month", "Month")]
[Index("statistic_request_count_day", "Day")]
public sealed class StatisticRequestCount
{
[Column(IsIdentity = true)]
Expand Down
2 changes: 2 additions & 0 deletions src/FastGateway/Dto/ServiceInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class ServiceInput
/// </summary>
public bool EnableTunnel { get; set; }

public string RateLimitName { get; set; }

/// <summary>
/// 服务配置
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/FastGateway/FastGateway.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Certes" Version="3.0.4" />
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.2.820" />
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
Expand Down
36 changes: 32 additions & 4 deletions src/FastGateway/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@
}
var freeSql = new FreeSqlBuilder()
.UseConnectionString(DataType.Sqlite, @default)
.UseConnectionString(DataType.Sqlite, @default)
#if DEBUG
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}"))
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}"))
#endif
.UseAutoSyncStructure(true)
.Build();
.UseAutoSyncStructure(true)
.Build();
return freeSql;
});
Expand Down Expand Up @@ -92,6 +92,9 @@
Utils.TypeHandlers.TryAdd(typeof(List<LocationService>),
new LocationServiceHandler());

Utils.TypeHandlers.TryAdd(typeof(List<GeneralRules>)
, new StringJsonHandler<List<GeneralRules>>());

#endregion

freeSql.CodeFirst.SyncStructure<Service>();
Expand All @@ -100,6 +103,7 @@
freeSql.CodeFirst.SyncStructure<StatisticRequestCount>();
freeSql.CodeFirst.SyncStructure<StatisticIp>();
freeSql.CodeFirst.SyncStructure<Location>();
freeSql.CodeFirst.SyncStructure<RateLimit>();

await ProtectionService.LoadBlacklistAndWhitelistAsync(freeSql);

Expand Down Expand Up @@ -264,6 +268,30 @@

#endregion


#region RateLimit

var rateLimitService = app.MapGroup("/api/v1/RateLimit")
.RequireAuthorization()
.AddEndpointFilter<ExceptionFilter>();

rateLimitService.MapPost(string.Empty,
RateLimitService.CreateAsync);

rateLimitService.MapPut("{name}",
RateLimitService.UpdateAsync);

rateLimitService.MapDelete("{name}",
RateLimitService.DeleteAsync);

rateLimitService.MapGet("/List",
RateLimitService.GetListAsync);

rateLimitService.MapGet("/Names",
RateLimitService.GetNamesAsync);

#endregion

FastContext.SetQpsService(app.Services.GetRequiredService<IQpsService>(),
app.Services.GetRequiredService<IMemoryCache>());

Expand Down
Loading

0 comments on commit a3f10ca

Please sign in to comment.