在运行时设置webjob ServiceBusTriggers或队列名称(没有硬编码属性)?

时间:2016-07-14 23:52:26

标签: azure azure-webjobs azure-webjobssdk

有没有办法配置没有属性的触发器?我不能提前知道队列名称。

让我在这里解释我的场景..我有一个服务总线队列,由于各种原因(复杂的重复抑制业务逻辑),队列消息必须一次处理一个,所以我有{{1}设置为1.因此处理消息会占用整个队列,直到完成为止。不用说,这不是最理想的。

这个'一次一个'政策不是那么简单。消息可以并行处理,只需将它们分组(基于消息中的字段),比如ServiceBusConfiguration.OnMessageOptions.MaxConcurrentCallsA。小组B可以一次处理一个消息,小组A可以一次处理一个消息,等等BA并行处理很好。

因此,我可以为每个组创建一个队列,BABC等。大约有50个组,所以有50个队列。

我可以为每个创建一个队列,但如何使用Azure Webjobs SDK进行此操作?我不想为每个队列复制粘贴一个方法,使用不同的...来发现SDK,只是为每个队列/组执行一次,然后使用每当需要另一个组时,另一个复制粘贴。最好在启动时获取队列列表并绑定到该函数。

我环顾四周,我没有看到任何方法可以做我想做的事。 ServiceBusTrigger接口非常难以查找属性。我可能会滥用ITypeLocator,但似乎我仍然需要一堆近乎重复的方法。我可以以某种方式创建SDK在启动/运行时寻找的东西吗?

(很明显,我知道如何使用INameResolver来获取How to set Azure WebJob queue name at runtime?的队列名称,但是虽然类似,但这不是我的问题。我想在启动时为多个队列设置触发器函数来获取每个队列一次一个处理,而不是反复使用触发器属性50次。我想我再问一遍,因为SDK repo相当活跃并且已经过了一年。 )。

或者我说这一切都错了?愚蠢?遗漏了什么?关于这种困境的任何建议都会受到欢迎。

2 个答案:

答案 0 :(得分:1)

Azure Webjob Host在启动时使用ServiceBusTrigger属性发现并索引这些函数。因此,无法设置队列在运行时触发。

更简单的解决方案是创建一个长时间运行的作业并手动实现:

public class Program
{
    private static void Main()
    {
        var host = new JobHost();
        host.CallAsync(typeof(Program).GetMethod("Process"));
        host.RunAndBlock();
    }

    [NoAutomaticTriggerAttribute]
    public static async Task Process(TextWriter log, CancellationToken token)
    {
        var connectionString = "myconnectionstring";
        // You can also get the queue name from app settings or azure table ??
        var queueNames = new[] {"queueA", "queueA" };
        var messagingFactory = MessagingFactory.CreateFromConnectionString(connectionString);
        foreach (var queueName in queueNames)
        {
            var receiver = messagingFactory.CreateMessageReceiver(queueName);
            receiver.OnMessage(message =>
            {
                try
                {
                    // do something
                    ....

                    // Complete the message
                    message.Complete();
                }
                catch (Exception ex)
                {
                    // Log the error
                    log.WriteLine(ex.ToString());

                    // Abandon the message so that it can be retry.
                    message.Abandon();
                }
            }, new OnMessageOptions() { MaxConcurrentCalls = 1});
        }

        // await until the job stop or restart
        await Task.Delay(Timeout.InfiniteTimeSpan, token);
    }
}

否则,如果您不想处理多个队列,可以查看azure servicebus topic/subscription并创建SqlFilter以将您的消息发送到正确的订阅。

另一种选择可能是创建自己的触发器:azure webjob SDK提供可扩展点来创建自己的触发器绑定:

祝你好运!

答案 1 :(得分:0)

根据我的理解,您的需求似乎是并行构建消息批处理系统。 @Thomas解决方案很好,但我认为使用Table存储的Azure Batch服务可能更好,而不是带有触发器的ServiceBus队列+ WebJobs的复杂解决方案。

将Azure Batch与表存储一起使用,您可以控制任务创建并大规模并行执行任务,甚至可以监控这些任务,请参考tutorial了解如何操作。