Azure服务总线功能。批量接收消息

时间:2019-02-19 10:54:08

标签: azure-functions azure-servicebus-topics azure-servicebus-subscriptions

我想以批处理方式接收来自Azure ServiceBus主题的消息。

阅读https://docs.microsoft.com/en-us/azure/azure-functions/functions-best-practices时指出:

  

对于C#函数,您可以将类型更改为强类型数组。例如,方法签名可以是EventData [] sensorEvent,而不是EventData sensorEvent。

我有一个方法:

public static void Run([ServiceBusTrigger("mytopic name", "MySubscription",
AccessRights.Listen, Connection = TopicService.ConnectionStringName)]
string messages, TraceWriter logger)

此方法有效,但一次需要1条消息。

根据Microsoft文档,我可以将其更改为:

public static void Run([ServiceBusTrigger("mytopic name", "MySubscription",
AccessRights.Listen, Connection = TopicService.ConnectionStringName)]
string[] messages, TraceWriter logger)

并将以下内容添加到host.json文件(https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json):

{
    "aggregator": {
        "batchSize": 10,
        "flushTimeout": "00:00:30"
    }
}

但是运行该函数时,出现异常:

  

mscorlib:执行函数MyFunction时发生异常。   Microsoft.Azure.WebJobs.Host:异常绑定参数“ messages”。 System.Runtime.Serialization:反序列化类型为System.String []的对象时出错。输入源的格式不正确。 System.Runtime.Serialization:输入源的格式不正确。

注意:主题和订阅已启用设置“启用批处理操作”。

我在这里想念什么?

1 个答案:

答案 0 :(得分:0)

这是我尝试的代码。检查并查看是否有效。

//---------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.  

using Microsoft.Azure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ServiceBusTriggers
{
    class Settings
    {
        public const string TopicPath = "sbperftopicwithpartitions";
        public const string Subscription = "sub_1";
        public const string ContainerName = "sbperf-test-store2";

        internal Settings()
        {
            ServiceBusConnectionString = GetSetting("ServiceBusConnectionString", UserSettings.ServiceBusConnectionString);
            StorageAccountConnectionString = GetSetting("StorageAccountConnectionString", UserSettings.StorageAccountConnectionString);
            AzureWebJobsDashboardConnectionString = GetSetting("AzureWebJobsDashboardConnectionString", UserSettings.AzureWebJobsDashboardConnectionString);
            AzureWebJobsStorageConnectionString = GetSetting("AzureWebJobsStorageConnectionString", UserSettings.AzureWebJobsStorageConnectionString);

            NLogDatabaseConnectionString = GetSetting("NLogDatabaseConnectionString", UserSettings.NLogDatabaseConnectionString);

            PrefetchCount = GetSetting("PrefetchCount", 100);
            MaxConcurrentCalls = GetSetting("MaxConcurrentCalls",100);

            MetricsDisplayFrequency = new TimeSpan(0, 0, 30); //every 30 seconds
            TokenSource = new CancellationTokenSource();
        }

        private int GetSetting(string name, int defaultValue)
        {
            int value;
            string valueStr = CloudConfigurationManager.GetSetting(name);
            if (!int.TryParse(valueStr, out value))
            {
                Console.WriteLine("Config missing for {0}. Using default.",name);
                value = defaultValue;
            }
            return value;
        }

        private string GetSetting(string name, string defaultValue)
        {
            string valueStr = CloudConfigurationManager.GetSetting(name);
            if (string.IsNullOrEmpty(valueStr))
            {
                Console.WriteLine("Config missing for {0}. Using default.", name);
                valueStr = defaultValue;
            }
            return valueStr;
        }

        public string ServiceBusConnectionString { get; set; }

        public string StorageAccountConnectionString { get; set;  }
       
        public int PrefetchCount { get; set; }

        public int MaxConcurrentCalls { get; set; }

        public TimeSpan MetricsDisplayFrequency { get; internal set; }

        public CancellationTokenSource TokenSource { get; set; }

        public string NLogDatabaseConnectionString { get; private set; }

        public static string AzureWebJobsDashboardConnectionString { get; internal set; }

        public static string AzureWebJobsStorageConnectionString { get; internal set; }

        public void WriteSettings()
        {
            ProjectLogger.Info("1|None|{1}|DisplayFrequency|{0}|", MetricsDisplayFrequency, Thread.CurrentThread.ManagedThreadId);
            ProjectLogger.Info("1|None|{1}|PrefetchCount|{0}|", PrefetchCount, Thread.CurrentThread.ManagedThreadId);
            ProjectLogger.Info("1|None|{1}|MaxConcurrentCalls|{0}|", MaxConcurrentCalls, Thread.CurrentThread.ManagedThreadId);
        }

    }
}

这是我的程序文件

//---------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.  
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
//---------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.ServiceBus;
using Microsoft.ServiceBus.Messaging;
using Microsoft.Azure;

namespace ServiceBusTriggers
{
    // To learn more about Microsoft Azure WebJobs SDK, please see https://go.microsoft.com/fwlink/?LinkID=320976
    class Program
    {
        // Please set the following connection strings in app.config for this WebJob to run:
        // AzureWebJobsDashboard and AzureWebJobsStorage
        static void Main()
        {
            var config = new JobHostConfiguration();

            if (config.IsDevelopment)
            {
                config.UseDevelopmentSettings();
            }
            Settings settings = new Settings();
            config.DashboardConnectionString = Settings.AzureWebJobsDashboardConnectionString;
            config.StorageConnectionString = Settings.AzureWebJobsStorageConnectionString;

            ServiceBusConfiguration sbconfig = new ServiceBusConfiguration()
            {
                ConnectionString = settings.ServiceBusConnectionString,
                PrefetchCount = settings.PrefetchCount,
                MessageOptions = new OnMessageOptions
                {
                    MaxConcurrentCalls = settings.MaxConcurrentCalls
                }
            };

            config.UseServiceBus(sbconfig);

            Functions.Initialize(settings);
            var host = new JobHost(config);
            // The following code ensures that the WebJob will be running continuously
            host.RunAndBlock();
        }
    }
}

这是我的功能文件

 public class Functions
    {
        static CloudStorageAccount storageAccount = null;
        static Metrics metrics = null;
        static Settings Settings = null;

        internal static void Initialize(Settings settings)
        {
            Settings = settings;
            Initialize();
        }

        static void Initialize()
        {
            ProjectLogger.Initialize(Settings);
            storageAccount = CloudStorageAccount.Parse(Settings.StorageAccountConnectionString);
            WriteMessageCount();
            metrics = new Metrics(Settings);
            metrics.StartMetricsTask(Settings.TokenSource.Token).Fork();
        }

        public static async Task ProcessTopicAsync(
                [ServiceBusTrigger(Settings.TopicPath, Settings.Subscription )]
                    BrokeredMessage message)
        {
            Stopwatch sw = Stopwatch.StartNew();
            await WriteToBlob(message);
            sw.Stop();
            metrics.IncreaseProcessMessages(1);
            metrics.IncreaseProcessBatch(1);
            metrics.IncreaseProcessLatency(sw.Elapsed.TotalMilliseconds);
        }

        private static async Task WriteToBlob(BrokeredMessage message)
        {
            var data = message.GetBody<byte[]>();
            var blobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = blobClient.GetContainerReference(Settings.ContainerName);
            await container.CreateIfNotExistsAsync();
            var blob = container.GetBlockBlobReference(Guid.NewGuid().ToString());
            await blob.UploadFromByteArrayAsync(data, 0, data.Length);
        }

        static void WriteMessageCount()
        {
            var namespaceManager = NamespaceManager.CreateFromConnectionString(Settings.ServiceBusConnectionString);
            var subscriptionDesc = namespaceManager.GetSubscription(Settings.TopicPath, Settings.Subscription);
            long subMessageCount = subscriptionDesc.MessageCount;
            ProjectLogger.Info("1|None|{1}|MessagesinSub|{0}|", subMessageCount, Thread.CurrentThread.ManagedThreadId);
        }
    }

有关更多信息,您可以浏览以下github存储库

https://github.com/tcsatheesh/samples/blob/master/ServiceBusTrigger/Functions.cs

希望有帮助。