我有多个Azure事件中心位于不同的Azure区域。我想编写一个webjob /函数,它可以接收来自所有这些事件中心的消息,而不必硬编码要监听的EH。
所以,通常你会有这样的东西,一个可以从config中定义的一个EH接收消息的函数:
public void Func([EventHubTrigger("%eventhubInName%")] string data)
在我的情况下,我有6个不同的EventHubs分布在6个azure地区。我想要的是以某种方式在启动时设置我的函数来监听几个事件中心,这样我就不需要硬编码6个相同的函数(Func1,Func2 ..)或托管我的webjob 6次。
这有可能吗?例如,在启动webjob期间做某事?
答案 0 :(得分:2)
我知道这个帖子太老了,无法回答,但最近我处理了类似的需求(每当引入新客户时,我们被要求为每个客户动态添加一个 EventHub)。
我通过开发一个 WebJob 解决了这个问题,它每小时从数据库中提取 EventHub 连接详细信息(当然还有它的主要功能)。如果在数据库中添加了任何新的 EventHub,则仅针对该 EventHub,它会生成一个新线程。 此外,如果任何 EventHub 已从数据库中删除,则它会终止该特定线程。
我通过使用一个静态列表来实现这一点,每个 eventhub 都有唯一的 id。
示例代码:
private static List<Guid> _existingEventHubs; // static list consisting of unique identifier for each EventHub. It will be empty at first.
List<EventHubMappingDetails> eventHubDetails = // a database call here. This list will have eventHub connection details.
if (eventHubDetails.Any())
{
//Logic to create new ConsumerRead Thread only for newly created event hubs and to kill the threads if the eventhub has been removed.
if (_existingEventHubs.Count > 0) // check if there are already any entries available in the list
{
//addDetails list contains the eventHub details for newly added eventHubs
List<EventHubMapping> addDetails = eventHubDetails.Where(_ => !_existingEventHubs.Contains(_.EHId)).ToList();
//removeDetails list contains eventhubMappingIds for the eventHubs which has been removed
List<Guid> removeDetails = _existingEventHubs.Where(_ => !eventHubDetails.Select(o => o.EHId).Contains(_)).ToList();
if (addDetails.Count > 0)
{
_existingEventHubs.AddRange(addDetails.Select(_ => _.EHId));
eventHubConnectionDetails = addDetails.Select(_ => new EventHubConnectionDetails()
{
connectionString = "Endpoint= + _.EHHostNameRead + ;SharedAccessKeyName= + _.EHSharedAccessKeyNameRead + ;SharedAccessKey= + _.EHSharedAccessKeyValueRead + ;EntityPath= + _.EHEntityPathRead",
counsumerGroup = // consumer Group Name here,
eventHubName = _.EHEntityPathRead,
ID = _.EHId.ToString()
}).ToList();
//Call to ConsumerReadEvent method to create new thread for all the newly created eventHubs
await _eventHubConsumerBusiness.ConsumerReadEvent(eventHubConnectionDetails);
}
if (removeDetails.Count > 0)
{
List<string> EHTobeRemovedList = removeDetails.Select(_ => _.ToString()).ToList();
_existingEventHubs.RemoveAll(_ => removeDetails.Contains(_));// remove all the EventHub unique identifiers from the static list if these are removed from data base
}
}
else
{
_existingEventHubs.AddRange(eventHubDetails.Select(_ => _.EHId));
eventHubConnectionDetails = eventHubDetails.Select(_ => new EventHubConnectionDetails()
{
connectionString = "Endpoint= + _.EHHostNameRead + ;SharedAccessKeyName= + _.EHSharedAccessKeyNameRead + ;SharedAccessKey= + _.EHSharedAccessKeyValueRead + ;EntityPath= + _.EHEntityPathRead",
counsumerGroup = // consumer Group Name here,
eventHubName = _.EHEntityPathRead,
ID = _.EHId.ToString()
}).ToList();
await _eventHubConsumerBusiness.ConsumerReadEvent(eventHubConnectionDetails);
}
}
然后为 Parallel.ForEach
列表的每个 eventHub 添加 eventHubConnectionDetails
。
为每个线程添加以下代码,
EventProcessorClient processor = new EventProcessorClient(storageClient, eventHubConnectionDetails.consumerGroup, eventHubConnectionDetails.connectionString, eventHubConnectionDetails.eventHubName);
try
{
processor.ProcessEventAsync += ProcessEventHandler;
processor.ProcessErrorAsync += ProcessErrorHandler;
await processor.StartProcessingAsync();
//Logic to delay the StopProcessingAsync till _existingEventHubs list contains the eventHubMappingId for the currently running eventHub
while (_existingEventHubs.Contains(eventHubConnectionDetails.ID))
{
await Task.Delay(TimeSpan.FromMinutes(5));
}
await processor.StopProcessingAsync();
}
catch
{
}
答案 1 :(得分:1)
单个Azure功能无法链接到多个触发器,据我所知,WebJob SDK也无法做到这一点。显然,您可以编写自己的Web作业(不是SDK),但我想这不是您所要求的。
最简单的方法可能就是写一个辅助方法:
public void Impl(string data) { ... }
然后使用不同的事件中心定义6个相同的函数:
public void Func1([EventHubTrigger("%hub1%", Connection = "Conn1")] string data)
=> Impl(data);
public void Func6([EventHubTrigger("%hub6%", Connection = "Conn6")] string data)
=> Impl(data);
您还可以手动在6个文件夹中创建6个function.json
个文件,并使它们指向相同的Impl
功能,但使用不同的事件中心设置。