簡體   English   中英

在隊列觸發的Azure Webjobs中,可以在webjob功能失敗之后但在中毒之前修改Azure存儲隊列消息嗎?

[英]In queue-triggered Azure Webjobs can an Azure Storage Queue message be modified after webjob function failure but before poisoning?

我的Azure webjobs中有隊列觸發的功能。 正常行為當然是當函數失敗時, MaxDequeueCount次將消息放入相應的毒性隊列。 我想在錯誤發生 ,但有害隊列插入之前修改的消息。 例:

初步訊息:

{ "Name":"Tom", "Age", 30" }

失敗后,我想按如下方式修改消息,並將修改后的消息插入到毒性隊列中:

{ "Name":"Tom", "Age", 30", "ErrorMessage":"Unable to find user" }

可以這樣做嗎?

根據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)

默認的最大重試時間是5.您還可以使用JobHostConfiguration()實例的JobHostConfiguration()屬性Queues.MaxDequeueCount設置此值,代碼如下所示:

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");
 }

完成上述操作后,您可以在queue-poison中看到更新的隊列消息。

更新:

由於CloudQueueMessage是一個密封類,我們無法繼承它。

對於MySpecialPoco消息,您可以使用JsonConvert.SerializeObject(消息),代碼如下:

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");
        }

但不好的是,原始/更新的隊列消息都被寫入毒性隊列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM