我正在为事件的发布者和消费者实现一个库,以通过 Azure 服务总线进行通信,我认为 MassTransit 可能是一个不错的选择。
我可以使用它发布多个事件,并且如果我让 MassTransit 创建它需要的任何主题并通过在消费者上仅指定我指定队列名称的 3 种事件类型的接收器端点,我可以让多个消费者接收它们而没有任何问题.
示例消费者:
var busControl =
Bus.Factory.CreateUsingAzureServiceBus(
cfg =>
{
CreateAzureServiceBusHost(cfg, serviceBusUri, serviceBusKeyName, serviceBusKey);
cfg.ReceiveEndpoint(queueName, endpoint =>
{
foreach (var eventDtoType in eventsTypes)
{
var adapterType = typeof(EventHandlerAdapter<>).MakeGenericType(eventDtoType);
var resolvedType = sp.GetService(adapterType);
endpoint.Consumer(adapterType, type => resolvedType);
}
});
});
请注意,我将 an 指定为使用者,EventHandlerAdapterType<TEvent>
因为我有一个适配器可以从 MassTransit 中抽象出事件处理程序。但这与这个问题无关。
发布者配置如下:
var busControl =
Bus.Factory.CreateUsingAzureServiceBus(
cfg =>
{
CreateAzureServiceBusHost(cfg, serviceBusUri, serviceBusKeyName, serviceBusKey);
});
问题是我需要使用与创建自己的主题的系统集成的这个库,并且它具有安全性(只有某些应用程序可以发布到它,只有某些应用程序可以读取已发布到该主题的消息)
所以我需要为想要发布某些主题的事件的发布者以及想要从某些主题中阅读的消费者创建一个令牌 sas。但是,令牌的创建超出了这个问题的范围。
我的解决方案尝试:我在 Azure 服务总线中准备了以下场景:-创建主题topic-attempt-one
(启用分区,但不确定是否相关)-在其中创建订阅subscription-attempt-one
-topic-attempt-one
在主题上创建仅发送权限的共享访问策略SamplePublishOnly
-创建共享SampleReadOnly
具有只听权限的主题的访问策略
我修改了我的示例,以便发布者按照 per 使用 key 和 keyName,SamplePublishOnly
并且两个消费者按照 per 使用 key 和 keyNameSampleReadOnly
在发布者上,我将其配置为对 3 个不同的事件使用相同的主题。
var busControl =
Bus.Factory.CreateUsingAzureServiceBus(
cfg =>
{
CreateAzureServiceBusHost(cfg, serviceBusUri, serviceBusKeyName, serviceBusKey);
// Here I add the same topic name for the 3 event types I want to publish.
cfg.Message<IEventOne>(topology =>
{
topology.SetEntityName("topic-attempt-one");
});
cfg.Message<IEventTwo>(topology =>
{
topology.SetEntityName("topic-attempt-one");
});
cfg.Message<IEventThree>(topology =>
{
topology.SetEntityName("topic-attempt-one");
});
});
消费者我为这三条消息配置了一个接收端点(消费者一有一个队列名称,消费者二有一个不同的队列名称),并添加了准确指定主题和要使用的订阅。
var busControl =
Bus.Factory.CreateUsingAzureServiceBus(
cfg =>
{
CreateAzureServiceBusHost(cfg, serviceBusUri, serviceBusKeyName, serviceBusKey);
cfg.ReceiveEndpoint(queueName, endpoint =>
{
//I specify the topic and subscription name that is already created in ServiceBus
endpoint.Subscribe("topic-attempt-one", "subscription-attempt-one");
foreach (var eventDtoType in eventsTypes)
{
var adapterType = typeof(EventHandlerAdapter<>).MakeGenericType(eventDtoType);
var resolvedType = sp.GetService(adapterType);
endpoint.Consumer(adapterType, type => resolvedType);
}
});
});
var busControlWrapper = new BusControlWrapper(busControl);
return busControlWrapper;
消费者现在不能启动公共汽车。我认为存在权限问题:
Microsoft.Azure.ServiceBus.UnauthorizedException: Manage,EntityRead claims required for this operation. TrackingId:2d6953d0-c8e1-4bdc-bed5-cc6e5d2d1f9e_G27, SystemTcker:sunnyatticsoftware.servicebus.windows.net:topic-attempt-one, Timestamp:2020-03-07T20:26:38
好的,所以我决定在 Azure 服务总线中为每个消费者手动创建两个队列,希望 MassTransit 可以在需要不同消息时创建虚拟队列。- 创建queue-one
- 创建共享访问策略,声明仅收听,我调用它QueueReadOnly
并尝试使用它的 keyName 和密钥。
没有什么。一个不同的错误,但仍然无法使其工作
Microsoft.Azure.ServiceBus.UnauthorizedException: claim is empty. TrackingId:9e344a3f-d40a-475d-bf61-7aae274ed2d1_G17, SystemTracker:sunnyatticsoftware.servicebus.windows.net:topic-attempt-one, Timestamp:2020-03-07T20:40:33
哪种是有道理的,因为我告诉它使用特定的主题和订阅,但不使用对它们具有读取权限的令牌,因为我已将其替换为队列之一。
问题
- 这是适合我的场景的正确方法吗?
- 可以尝试共享同一个主题来发布 3 种不同的消息类型吗?似乎 MassTransit 的设计让我每条消息使用一个主题。
- 如何实现我需要的?如果我不希望 MassTransit 发布者和消费者使用
Manage
完全权限令牌,因为我不希望消费者(例如)在某个主题上发布,那么其他人如何处理权限?
谢谢!
PS:我发现了一个类似的问题,但不幸的是它并没有解决我的问题。 如何指定要与 MassTransit 一起使用的 Azure 服务总线主题
更新 1
我发现了这一点:是否可以在没有管理权限策略的情况下将 MassTransit 3 与 Azure 服务总线一起使用?
如果最新的 6.2 版本仍然是这种情况,它可以解释为什么我会收到这些错误。如果我不能使用“管理”以外的任何声明,那就太可惜了。那么,Masstransit 没有细粒度的权限吗?如何防止具有Manage
令牌的应用程序读取不应该读取的消息?
如果无法创建主题、订阅或队列等实体,是否可以使用 Masstransit?
我猜我缺乏很多知识,所以任何链接也将不胜感激!