Приложение-функция Azure Триггер служебной шины Azure срабатывает дважды

Я использую приложения-функции Azure с триггером служебной шины, чтобы читать служебную шину и что-то делать с содержимым сообщения служебной шины. Служебная шина получает сериализованный объект JSON, а затем я десериализую сообщение JSON обратно в объект в приложении-функции. Однако по какой-то причине всякий раз, когда что-то отправляется на служебную шину, триггер срабатывает дважды: одно - это сообщение JSON, а второе - сообщение, содержащее текст «Сообщение служебной шины».

Я понятия не имею, что вызывает второе сообщение, поэтому я просто де-сериализовал сообщение служебной шины, и когда оно не срабатывает с «сообщением служебной шины», я просто перехватываю исключение и проигнорирую его. Однако я не думаю, что это правильный способ решения этой проблемы, и фактические ошибки при десериализации JSON будут проигнорированы. Как правильно обработать второе сообщение?

Пример кода:

using Newtonsoft.Json;

public static void Run(string myQueueItem, ILogger log, out SendGridMessage mailMessage)
{
    MyClass myObject = null;
    try
    {
        myObject = JsonConvert.DeserializeObject<MyClass>(myQueueItem);
        // do stuff
    }
    catch (JsonException je)
    {
        // ignore this exception
    }
    catch (Exception e)
    {
        // handle the other exceptions and send an alert
    }
}

Изменить: Одна вещь, которую я оставил в исходном сообщении, - это то, что у меня тоже есть выход SendGrid. Я не понимаю, почему это могло повлиять на триггер, поэтому я его не упомянул. Однако я добавляю его сейчас на всякий случай, если это может быть причиной по какой-то странной причине.

Изменить 2: добавлен полный рабочий код, который подчеркивает проблему

// Sender
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus;
using Newtonsoft.Json;

namespace myapp
{
    class Program
    {
        static void Main(string[] args) => MainAsync().GetAwaiter().GetResult();

        static async Task MainAsync()
        {
            string serviceBusConnectionString = "<your servicebus connectionstring>";
            string queueName = "<your queue name>";
            IQueueClient queueClient = new QueueClient(serviceBusConnectionString, queueName);
            string messageBody = JsonConvert.SerializeObject(new Test());
            var message = new Message(Encoding.UTF8.GetBytes(messageBody));
            await queueClient.SendAsync(message);
            await queueClient.CloseAsync();
        }

        class Test
        {
            public string Text { get; set; } = "test";
        }
    }
}
// Receiver
#r "Newtonsoft.Json"

using System;
using System.Threading.Tasks;
using Newtonsoft.Json;

public static void Run(string myQueueItem, ILogger log)
{
    try
    {
        Test test = JsonConvert.DeserializeObject<Test>(myQueueItem);
        log.LogInformation($"C# ServiceBus queue trigger function processed message: {test.Text}");
    }
    catch (Exception e)
    {
        log.LogInformation($"Exception: {e.Message}");
    }
}

class Test
{
    public string Text { get; set; } = "test";
}

Результат:

2019-11-04T08:38:10.544 [Information] Executing 'Functions.test' (Reason='This function was programmatically called via the host APIs.', Id=06e10006-baa6-430f-b5db-9a5eae5c154c)
2019-11-04T08:38:10.659 [Information] Exception: Unexpected character encountered while parsing value: S. Path '', line 0, position 0. // This here is caused by "Service bus message"
2019-11-04T08:38:10.659 [Information] Executed 'Functions.test' (Succeeded, Id=06e10006-baa6-430f-b5db-9a5eae5c154c)
2019-11-04T08:39:02.582 [Information] Executing 'Functions.test' (Reason='New ServiceBus message detected on 'test'.', Id=5d7622a7-cc8d-44c9-8720-626fdbb8cabb)
2019-11-04T08:39:02.583 [Information] Trigger Details: MessageId: 13bba779fd524fa1a0098acd6634aded, DeliveryCount: 1, EnqueuedTime: 11/4/2019 8:39:02 AM, LockedUntil: 11/4/2019 8:39:07 AM
2019-11-04T08:39:02.584 [Information] C# ServiceBus queue trigger function processed message: test // This here is the actual message
2019-11-04T08:39:02.584 [Information] Executed 'Functions.test' (Succeeded, Id=5d7622a7-cc8d-44c9-8720-626fdbb8cabb)

person Roihu    schedule 01.11.2019    source источник
comment
stackoverflow.com/questions/45045535/   -  person Sajeetharan    schedule 01.11.2019
comment
Другой вопрос.   -  person Roihu    schedule 01.11.2019
comment
@Roihu Вы вносите какие-либо изменения в myQueueItem, который не отображается в вашем примере?   -  person Markus Meyer    schedule 02.11.2019
comment
Нет, единственная ссылка на myQueueItem - это когда я де-сериализую его. Может быть, завтра я напишу полный пример, чтобы люди могли сами попробовать такое поведение.   -  person Roihu    schedule 03.11.2019


Ответы (1)


Судя по моему тесту, триггер не сработает дважды.

namespace ServiceBusTrigger
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static void Run([ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")]string myQueueItem, ILogger log)
        {
            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

            var myMessage = JsonConvert.DeserializeObject<MyMessage>(myQueueItem);

            log.LogInformation($"ID: {myMessage.id}\tContent:{myMessage.content}");
        }
    }
}

Отправьте сообщение вручную и получите следующий результат:


Pause Clear Expand

2019-11-04T08:18:56.837 [Information] Executing 'Function1' (Reason='New ServiceBus message detected on 'myqueue'.', Id=7fb37483-b9a3-4c19-baa3-235b419bb585)
2019-11-04T08:18:56.837 [Information] Trigger Details: MessageId: c00a8e41-d883-4620-992f-6b9b4fdae320, DeliveryCount: 1, EnqueuedTime: 11/4/2019 8:18:56 AM, LockedUntil: 11/4/2019 8:19:26 AM
2019-11-04T08:18:56.838 [Information] C# ServiceBus queue trigger function processed message: {"id":"1","content":"abc"}
2019-11-04T08:18:56.838 [Information] ID: 1 Content:abc
2019-11-04T08:18:56.839 [Information] Executed 'Function1' (Succeeded, Id=7fb37483-b9a3-4c19-baa3-235b419bb585)

Итак, не могли бы вы проверить производителя служебной шины, чтобы узнать, было ли отправлено какое-либо дополнительное сообщение.

Вы можете просто остановить свое функциональное приложение, отправить сообщение вручную и проверить на портале:

введите здесь описание изображения

Если все в порядке, то активное сообщение должно быть только 1.


Обновлять

введите здесь описание изображения

введите здесь описание изображения

person Jack Jia    schedule 04.11.2019
comment
Хорошо, благодаря вашему примеру я нашел проблему. log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}"); в начале метода Run кажется обязательным. Без него происходит то, что я описал. - person Roihu; 04.11.2019
comment
@Roihu Неправда. Я прокомментировал вывод журнала. По-прежнему срабатывает только один раз. Проверить обновление. - person Jack Jia; 04.11.2019
comment
Ооо, сюжет сгущается. Пока строка есть (даже если она закомментирована), она работает должным образом. Если линия действительно удалена, возникает проблема. Я пометил ваш ответ как ответ, потому что он помог мне решить эту проблему. - person Roihu; 04.11.2019