Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步调用AWS RDS CreateDBSnapshotAsync“;设定它,然后忘记它”;_C#_.net_Amazon Web Services_Asynchronous_Rds - Fatal编程技术网

C# 异步调用AWS RDS CreateDBSnapshotAsync“;设定它,然后忘记它”;

C# 异步调用AWS RDS CreateDBSnapshotAsync“;设定它,然后忘记它”;,c#,.net,amazon-web-services,asynchronous,rds,C#,.net,Amazon Web Services,Asynchronous,Rds,在AWS Lambda函数中,我希望能够调用组件来创建RDS DB快照。客户端上有一个名为CreateDBSnapshotAsync的异步方法。但是,因为这是AWS Lambda,我只有5分钟来完成任务。因此,如果我等待它,AWS Lambda函数将超时。而且,显然,当它超时时,调用被取消,然后快照没有完成 是否有某种方法可以以完全异步的方式进行调用,以便在调用它之后,无论Lambda函数是否超时,它都将完成? 换句话说,我不在乎结果,我只想调用过程继续前进,一种“设定它,然后忘记它”的心态 我

在AWS Lambda函数中,我希望能够调用组件来创建RDS DB快照。客户端上有一个名为CreateDBSnapshotAsync的异步方法。但是,因为这是AWS Lambda,我只有5分钟来完成任务。因此,如果我等待它,AWS Lambda函数将超时。而且,显然,当它超时时,调用被取消,然后快照没有完成

是否有某种方法可以以完全异步的方式进行调用,以便在调用它之后,无论Lambda函数是否超时,它都将完成? 换句话说,我不在乎结果,我只想调用过程继续前进,一种“设定它,然后忘记它”的心态

我的电话(显然没有等待)如下

        using (var rdsClient = new AmazonRDSClient())
        {
            Task<CreateDBSnapshotResponse> response = rdsClient.CreateDBSnapshotAsync(new CreateDBSnapshotRequest($"MySnapShot", instanceId));
        }
使用(var-rdsClient=new-AmazonRDSClient())
{
任务响应=rdsClient.CreateDBSnapshotAsync(新的CreateDBSnapshotRequest($“MySnapShot”,instanceId));
}
根据要求,以下是完整的方法:

    public async Task<CloudFormationResponse> MigrateDatabase(CloudFormationRequest request, ILambdaContext context)
    {
        LambdaLogger.Log($"{nameof(MigrateDatabase)} invoked: " + JsonConvert.SerializeObject(request));


        if (request.RequestType != "Delete")
        {
            try
            {
                var migrations = this.Context.Database.GetPendingMigrations().OrderBy(b=>b).ToList();
                for (int i = 0; i < migrations.Count(); i++)
                {
                    string thisMigration = migrations [i];
                    this.ApplyMigrationInternal(thisMigration);
                }
                this.TakeSnapshotAsync(context,migrations.Last());
                return await CloudFormationResponse.CompleteCloudFormationResponse(null, request, context);

            }
            catch (Exception e)
            {
                LambdaLogger.Log(e.ToString());
                if (e.InnerException != null) LambdaLogger.Log(e.InnerException.ToString());
                return await CloudFormationResponse.CompleteCloudFormationResponse(e, request, context);
            }
        }
        return await CloudFormationResponse.CompleteCloudFormationResponse(null, request, context);

    }

    internal void TakeSnapshotAsync(ILambdaContext context, string migration)
    {

        var instanceId = this.GetEnvironmentVariable(nameof(DBInstance));

        using (var rdsClient = new AmazonRDSClient())
        {


            Task<CreateDBSnapshotResponse> response = rdsClient.CreateDBSnapshotAsync(new CreateDBSnapshotRequest($"{instanceId}{migration.Replace('_','-')}", instanceId));
            while (context.RemainingTime > TimeSpan.FromSeconds(15))
            {
                Thread.Sleep(15000);
            }
        }
    }
public async Task MigrateDatabase(CloudFormationRequest请求,ILambdaContext上下文)
{
LambdaLogger.Log($“{nameof(MigrateDatabase)}调用:”+JsonConvert.SerializeObject(请求));
if(request.RequestType!=“删除”)
{
尝试
{
var migrations=this.Context.Database.GetPendingMigrations().OrderBy(b=>b.ToList();
对于(int i=0;iTimeSpan.FromSeconds(15))
{
睡眠(15000);
}
}
}

首先重构该子函数,以使用适当的异步语法以及
任务

internal async Task TakeSnapshotAsync(ILambdaContext context, string migration) {
    var instanceId = this.GetEnvironmentVariable(nameof(DBInstance));
    //don't wrap in using block or it will be disposed before you are done with it.
    var rdsClient = new AmazonRDSClient();
    var request = new CreateDBSnapshotRequest($"{instanceId}{migration.Replace('_','-')}", instanceId);
    //don't await this long running task
    Task<CreateDBSnapshotResponse> response = rdsClient.CreateDBSnapshotAsync(request);
    Task delay = Task.Run(async () => {
        while (context.RemainingTime > TimeSpan.FromSeconds(15)) {
            await Task.Delay(15000); //Don't mix Thread.Sleep. use Task.Delay and await it.
        }
    }
    // The call returns as soon as the first operation completes, 
    // even if the others are still running.
    await Task.WhenAny(response, delay);
}
这还应允许RDS客户端引发的任何异常被当前执行的线程捕获。这将有助于排除任何异常消息的故障

一些有趣的信息来自

在带有AWS Lambda的C#函数中使用异步 如果您知道Lambda函数需要一个长时间运行的过程,例如将大型文件上载到AmazonS3或从DynamoDB读取大量记录,那么您可以利用异步/等待模式。使用此签名时,Lambda会同步执行函数,并等待函数返回响应或执行到

功能设置

  • 超时–Lambda允许函数在停止之前运行的时间量。默认值为3秒。允许的最大值为900秒
如果获得HTTP超时,则缩短延迟,但保留长时间运行的任务。您仍然可以使用
任务。WhenAny
为长时间运行的任务提供一个先完成的机会,即使这不是期望的

internal async Task TakeSnapshotAsync(ILambdaContext context, string migration) {
    var instanceId = this.GetEnvironmentVariable(nameof(DBInstance));
    //don't wrap in using block or it will be disposed before you are done with it.
    var rdsClient = new AmazonRDSClient();
    var request = new CreateDBSnapshotRequest($"{instanceId}{migration.Replace('_','-')}", instanceId);
    //don't await this long running task
    Task<CreateDBSnapshotResponse> response = rdsClient.CreateDBSnapshotAsync(request);
    Task delay = Task.Delay(TimeSpan.FromSeconds(2.5));
    // The call returns as soon as the first operation completes, 
    // even if the others are still running.
    await Task.WhenAny(response, delay);
}
内部异步任务TakeSnapshotAsync(ILambdaContext上下文,字符串迁移){
var instanceId=this.GetEnvironmentVariable(nameof(DBInstance));
//不要使用block包装,否则在使用完它之前,它将被处理掉。
var rdsClient=new AmazonRDSClient();
var request=newcreatedbsnapshotRequest($“{instanceId}{migration.Replace(''''-')}”,instanceId);
//不要等待这个长时间运行的任务
任务响应=rdsClient.CreateDBSnapshotAsync(请求);
任务延迟=任务延迟(TimeSpan.FromSeconds(2.5));
//第一个操作完成后,调用立即返回,
//即使其他人还在跑。
等待任务。何时(响应、延迟);
}

下面是一个HTTP调用。我的印象是,一旦打电话,它将继续处理。我相信在超时的情况下,AmazonRDSClient的dispose正在对操作调用cancel。然后只需使用
块删除
。使用block
中调用异步调用肯定会导致客户端在调用时间之前被释放。您能否显示封装该调用的函数。是
TakeSnapshotAsync
函数中实际的AWS lambda函数处理程序还是被调用的子方法?这是Amazon SDK上的一个方法:谢谢!我会查看它(当us-east-1 RDS备份时)。我不知道他们将时间限制从5分钟提高到了15分钟。我建议检查链接,看看是否有其他您不知道的更改。嗯,它不起作用。但是,我不知道为什么,也没有时间完全深入研究它。但你的洞察力绝对值得赏金。所以,我有时间仔细看看。根本问题是Lambda函数没有rds:CreateDBSnapshot权限。问题是在没有等待的情况下完全异步调用它会导致异常不会抛出,因此不会被捕获或记录。易居
internal async Task TakeSnapshotAsync(ILambdaContext context, string migration) {
    var instanceId = this.GetEnvironmentVariable(nameof(DBInstance));
    //don't wrap in using block or it will be disposed before you are done with it.
    var rdsClient = new AmazonRDSClient();
    var request = new CreateDBSnapshotRequest($"{instanceId}{migration.Replace('_','-')}", instanceId);
    //don't await this long running task
    Task<CreateDBSnapshotResponse> response = rdsClient.CreateDBSnapshotAsync(request);
    Task delay = Task.Delay(TimeSpan.FromSeconds(2.5));
    // The call returns as soon as the first operation completes, 
    // even if the others are still running.
    await Task.WhenAny(response, delay);
}