我的Azure webjobs中有队列触发的函数。当然,正常的行为是当函数失败MaxDequeueCount
次时,将消息放入适当的中毒队列。我想修改错误消息之后,但之前插入毒物队列。示例:
初始消息:
{ "Name":"Tom", "Age", 30" }
在失败后,我想按以下方式修改消息,然后将修改后的消息插入毒物队列:
{ "Name":"Tom", "Age", 30", "ErrorMessage":"Unable to find user" }
可以做到吗?
答案 0 :(得分:0)
根据Webjobs文档,在尝试处理消息5次失败后,消息将被放入中毒队列:
SDK将调用一个函数最多5次以处理队列消息。 如果第五次尝试失败,则该消息将移至中毒队列。的 重试的最大次数是可配置的。
来源:https://github.com/Azure/azure-webjobs-sdk/wiki/Queues#poison
这是自动行为。但是,您仍然可以在WebJobs函数代码中处理异常(这样,异常不会离开您的函数,并且不会触发自动检测有害消息),并使用输出绑定将修改后的消息放入有害队列。
另一种选择是检查dequeueCount属性,该属性指示尝试处理该消息的次数。
您可以获得获取消息的次数 通过添加一个名为dequeueCount的int参数到您的处理 功能。然后,您可以在功能代码中检查出队计数,然后 当数量超过一个时,执行您自己的毒药消息处理 阈值,如以下示例所示。
public static void CopyBlob(
[QueueTrigger("copyblobqueue")] string blobName, int dequeueCount,
[Blob("textblobs/{queueTrigger}", FileAccess.Read)] Stream blobInput,
[Blob("textblobs/{queueTrigger}-new", FileAccess.Write)] Stream blobOutput,
TextWriter logger)
{
if (dequeueCount > 3)
{
logger.WriteLine("Failed to copy blob, name=" + blobName);
}
else
{
blobInput.CopyTo(blobOutput, 4096);
}
}
(也来自上面的链接)。
您的函数签名可能看起来像这样
public static void ProcessQueueMessage(
[QueueTrigger("myqueue")] CloudQueueMessage message,
[Queue("myqueue-poison")] CloudQueueMessage poisonMessage,
TextWriter logger)
答案 1 :(得分:0)
默认的最大重试时间为5。您还可以使用Queues.MaxDequeueCount
实例的属性JobHostConfiguration()
自行设置此值,如下所示:
static void Main(string[] args)
{
var config = new JobHostConfiguration();
config.Queues.MaxDequeueCount = 5; // set the maximum retry time
var host = new JobHost(config);
host.RunAndBlock();
}
然后,当达到最大重试时间时,您可以更新失败的队列消息。您可以指定一个不存在的Blob容器来强制重试机制。如下代码:
public static void ProcessQueueMessage([QueueTrigger("queue")] CloudQueueMessage message, [Blob("container/{queueTrigger}", FileAccess.Read)] Stream myBlob, ILogger logger)
{
string yourUpdatedString = "ErrorMessage" + ":" + "Unable to find user";
string str1 = message.AsString;
if (message.DequeueCount == 5) // here, the maximum retry time is set to 5
{
message.SetMessageContent(str1.Replace("}", "," + yourUpdatedString + "}")); // modify the failed message here
}
logger.LogInformation($"Blob name:{message} \n Size: {myBlob.Length} bytes");
}
完成上述操作后,您可以在队列毒物中看到更新的队列消息。
已更新:
由于CloudQueueMessage是一个密封的类,所以我们不能继承它。
对于MySpecialPoco消息,可以使用JsonConvert.SerializeObject(message),代码如下:
using Newtonsoft.Json;
static int number = 0;
public static void ProcessQueueMessage([QueueTrigger("queue")] object message, [Blob("container/{queueTrigger}", FileAccess.Read)] Stream myBlob, ILogger logger)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
CloudQueue queue = queueClient.GetQueueReference("queue-poison");// get the poison queue
CloudQueueMessage msg1 = new CloudQueueMessage(JsonConvert.SerializeObject(message));
number++;
string yourUpdatedString = "\"ErrorMessage\"" + ":" + "\"Unable to find user\"";
string str1 = msg1.AsString;
if (number == 5)
{
msg1.SetMessageContent(str1.Replace("}", "," + yourUpdatedString + "}"));
queue.AddMessage(msg1);
number = 0;
}
logger.LogInformation($"Blob name:{message} \n Size: {myBlob.Length} bytes");
}
但是不好的是,原始/更新的队列消息都被写入毒药队列。