如何在 gRPC 服务中应用速率限制

前言

上次,我们介绍了如何为 ASP.NET Core Web API 下实现速率限制

而作为 .NET 7 中的重要特性,gRPC 服务建立在 ASP.NET Core 之上,因此我们可以使用与 Web API 项目相同的方法来实现 gRPC 服务的速率限制。

实现

在 Program.cs 文件中,我们可以使用以下代码来添加速率限制器:.

builder.Services.AddRateLimiter(p => p  
    .AddFixedWindowLimiter(policyName: "FixedWindow", options =>  
    {  
        options.PermitLimit = 3;  
        options.Window = TimeSpan.FromSeconds(10);  
    }));  

这里我们使用了固定窗口算法,将 PermitLimit 设置为 3,表示每 10 秒内最多允许 3 次请求。

然后,我们将中间件添加到 HTTP 请求管道中:

app.UseRateLimiter();  

现在,我们可以使用 RateLimitAttribute 特性将速率限制器应用于 gRPC 服务实现类上,如下所示:

[EnableRateLimiting("FixedWindow")]
public class GreeterService : Greeter.GreeterBase

也可以将上述特性添加到实际的方法实现上:

public class GreeterService : Greeter.GreeterBase
{
    [EnableRateLimiting("FixedWindow")]
    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

当服务端的速率限制器拒绝请求时,客户端上将收到"503 不可用"的状态代码:

using var channel = GrpcChannel.ForAddress("https://localhost:7289");
var client = new Greeter.GreeterClient(channel);
for (int i = 0; i < 10; i++)
{
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = $"GreeterClient{i}" });
    Console.WriteLine("Greeting: " + reply.Message);
}

如何在 gRPC 服务中应用速率限制

这有助于客户端了解当前的请求状态,并及时进行调整。

总结

我们可以采用与 ASP.NET Core Web API 类似的方法对 gRPC 服务应用速率限制,以提高服务的可靠性和稳定性。