简体   繁体   English

如何确定中毒队列消息的原因

[英]How to determine reason for poison queue message

I have an azure function with a QueueTrigger that processes an image and outputs a blob as well as a table record.我有一个带有 QueueTrigger 的 azure 函数,它处理图像并输出一个 blob 以及一个表记录。

Sometimes when processing several large images I have run into OutOfMemory exceptions, which can cause the queue item to be placed into a poison queue.有时在处理多个大图像时,我会遇到 OutOfMemory 异常,这会导致队列项被放入有害队列。

Sometimes there is a race condition and the table record being inserted errors out because there is already a record with that partition key and row key.有时会出现竞争条件,并且插入的表记录会出错,因为已经存在具有该分区键和行键的记录。

I could work around these issues myself within the functions, but my preferred way to handle this would be for the poison message to include a reason or the exception that caused the item to be placed in the poison queue.我可以在函数中自己解决这些问题,但我首选的处理方式是让有害消息包含导致项目被放入有害队列的原因或异常。 That way I can have another trigger listen on the poison queue and act accordingly after assessing what went wrong.这样我就可以让另一个触发器监听中毒队列,并在评估出了什么问题后采取相应的行动。

How should this be handled?这应该如何处理? I'm aware of the ErrorTrigger, which is nice to get the exception but I don't see how I can relate it back to the specific queue item that caused it.我知道 ErrorTrigger,它很高兴获得异常,但我不知道如何将它与导致它的特定队列项目相关联。

There is no way to change a poison storage queue message queue after your Queue trigger fails.队列触发器失败后,无法更改毒物存储队列消息队列。

Azure functions uses Web Jobs SDK. Azure 函数使用 Web 作业 SDK。 Using Web Jobs SDK directly it is possible to overwrite QueueProcessor.CopyMessageToPoisonQueueAsync.直接使用 Web 作业 SDK 可以覆盖 QueueProcessor.CopyMessageToPoisonQueueAsync。 Some useful links:一些有用的链接:

https://github.com/Azure/azure-webjobs-sdk/issues/1204 https://github.com/Azure/azure-webjobs-sdk/issues/1204

https://github.com/Azure/azure-webjobs-sdk-samples/blob/master/BasicSamples/MiscOperations/CustomQueueProcessorFactory.cs https://github.com/Azure/azure-webjobs-sdk-samples/blob/master/BasicSamples/MiscOperations/CustomQueueProcessorFactory.cs

https://github.com/Azure/azure-webjobs-sdk/blob/ffae7c86ea87fd73748186bac2c38c5401b80f68/test/Microsoft.Azure.WebJobs.Host.EndToEndTests/AzureStorageEndToEndTests.cs https://github.com/Azure/azure-webjobs-sdk/blob/ffae7c86ea87fd73748186bac2c38c5401b80f68/test/Microsoft.Azure.WebJobs.Host.EndToEndTests/AzureStorageEndToEndTests.cs

There is a hacky way to track the exception and the message that caused the message using a FunctionInvocation filter.有一种使用 FunctionInvocation 过滤器跟踪异常和导致消息的消息的hacky 方法。

public static class QueueFunction
{
    [FunctionName("QueueFunction")]
    [TrackFailedMessages]
    public static void Run([QueueTrigger("myqueue")]string message)
    {
        throw new Exception("OMG");
    }
}

public class TrackFailedMessages : FunctionInvocationFilterAttribute
{
    private static readonly ConcurrentDictionary<Guid, object> QueueParamters = new ConcurrentDictionary<Guid, object>();
    public override Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
    {
        if (executingContext.Arguments.TryGetValue("message", out var data))
        {
            QueueParamters.AddOrUpdate(executingContext.FunctionInstanceId, data, (id, obj) => data);
        }
        return Task.CompletedTask;
    }

    public override Task OnExecutedAsync(FunctionExecutedContext executedContext, CancellationToken cancellationToken)
    {
        if (executedContext.FunctionResult.Exception != null &&
            QueueParamters.TryGetValue(executedContext.FunctionInstanceId, out var message))
        {
            executedContext.Logger.LogCritical(
                "The message {message} caused the exception {exception}",
                message,
                executedContext.FunctionResult.Exception.ToString());
        }
        QueueParamters.TryRemove(executedContext.FunctionInstanceId, out var _);
        return Task.CompletedTask;
    }
}

OnExecutinAsync will be called, when ever a function is invoked. OnExecutinAsync 将在调用函数时被调用。 Using the executingContext you have access to the parameters of the function.使用 executionContext 您可以访问函数的参数。 You can search for your QueueTrigger paramter and store the value in a dictionary, where the FunctionInstanceId is the key.您可以搜索 QueueTrigger 参数并将值存储在字典中,其中 FunctionInstanceId 是键。 FunctionInstanceId is a unique Id for every invocation. FunctionInstanceId 是每次调用的唯一 ID。

In OnExecuted you can check if the function raised and exception and get the message from the dictionary, then store it somewhere else (database, log, etc.)在 OnExecuted 中,您可以检查函数是否引发异常并从字典中获取消息,然后将其存储在其他地方(数据库、日志等)

I am not sure if this catches the Table Storage Exception...我不确定这是否捕获了表存储异常...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM