在无服务器上下文中,C#异步/等待有什么好处?

Dav*_*vid 7 c# async-await aws-lambda

对于仅调用外部服务或写入数据存储的微服务功能,是否有必要在C#中使用异步/等待

我们在AWS Lambdas中编写了大量此类代码,很难确定在这种情况下async / await的实际收益是什么或在什么地方真正有用。对于更传统的IIS Web服务,异步释放了OS中的线程,并允许服务器处理更多请求。

但是对于AWS Lambdas,这些函数每次执行仅处理一个请求(限制为1000个同时执行)。因此,如果我们有一个长时间运行的外部进程或具有大量延迟的外部依赖项,则每个函数的执行都将被挂起,直到外部进程完成(假设Lambda被同步调用)。

这是一个带有三个处理程序的Lambda示例,我将其中第三个放入单独的名为“ DavidSleep”的Lambda中,该Lambda仅表示长期运行的外部依赖项。当我使用前两个处理程序中的任何一个调用另一个名为“ DavidTest”的Lambda时,我看不到异步/等待版本与缺少异步/等待版本的功能或性能没有区别。这两个函数都需要多个并发的Lambda执行,并且花费相同的时间。

因此,异步版本似乎与无异步版本没有区别,但是有什么区别吗?

public class Test
{
    private IAmazonLambda lambda;

    public Test()
    {
        lambda = new AmazonLambdaClient();
    }

    [LambdaSerializer(typeof(JsonSerializer))]
    public async Task HandleAsync(Request request)
    {
        Console.WriteLine($"Executing for { request.Name }");
        await lambda.InvokeAsync(new InvokeRequest
        {
            FunctionName = "DavidSleep",
            InvocationType = InvocationType.RequestResponse,
            Payload = JsonConvert.SerializeObject(request)
        });
    }

    [LambdaSerializer(typeof(JsonSerializer))]
    public void Handle(Request request)
    {
        Console.WriteLine($"Executing for { request.Name }");
        lambda.InvokeAsync(new InvokeRequest
        {
            FunctionName = "DavidSleep",
            InvocationType = InvocationType.RequestResponse,
            Payload = JsonConvert.SerializeObject(request)
        }).Wait();
    }

    [LambdaSerializer(typeof(JsonSerializer))]
    public void Sleep(Request request)
    {
        Console.WriteLine($"{ request.Name }{ request.RequestId } begin");
        Thread.Sleep(request.WaitInSeconds * 1000);
        Console.WriteLine($"{ request.Name }{ request.RequestId } end");
    }
}
Run Code Online (Sandbox Code Playgroud)

jjx*_*tra 2

在无服务器上下文中 async/await 的好处仍然是您可以放弃对调用线程的控制,从而释放另一个调用者来使用该线程。我不知道 AWS 是否会await从 1000 个呼叫限制中删除呼叫,但他们有可能。

对于这些在方法中没有其他异步调用的线性任务调用,您可以简单地返回任务。无论 AWS Lambda 1000 调用限制如何,标记方法async和调用await都会增加不必要的开销。

例子:

[LambdaSerializer(typeof(JsonSerializer))]
public Task HandleAsync(Request request)
{
    Console.WriteLine($"Executing for { request.Name }");
    return lambda.InvokeAsync(new InvokeRequest
    {
        FunctionName = "DavidSleep",
        InvocationType = InvocationType.RequestResponse,
        Payload = JsonConvert.SerializeObject(request)
    });
}
Run Code Online (Sandbox Code Playgroud)