发布到具有不同商店的多个 Rebus 队列

Publishing to multiple Rebus queues with different stores

我们有一个发布消息的应用程序 - PublishApp。

消息(MessageA 和 MessageB)由两个不同的消费者应用程序(ConsumerA 和 ConsumerB)接收。

所有应用程序都使用SQL服务器作为传输和温莎配置,但是两个消费者在SQL服务器中有不同的数据库。

我们如何配置 PublishApp 为 ConsumerA 发布 MessageA,为 ConsumerB 发布 MessageB?

我已经尝试按照 here 所述使用 DetermineMessageOwnership,但似乎并没有实际调用(没有断点命中)。我对返回的字符串端点应该是什么有点迷惑。

我希望我可以在 Windsor 中设置一个具有特定名称的 IBus 组件,然后在设置我的 MessageB 发布时通过名称引用它 class。然而,目前还不清楚如何在为我完成这一切的魔盒之外的温莎设置 IBus。

如果我尝试调用 Configure.With(new WindsorContainerAdapter(container)) 两次,摆弄 Windsor 配置会导致我出现 Windsor 错误,因为它被解释为注册 IBus 接口两次。我在这里看不到扩展点来给 IBus 个实例之一命名,因此在 Windsor 中区分它们。

或者,尝试重用 Configure.With... 调用会抛出一个错误,告诉我我已经在配置器上调用了 .Transport() 两次,这也是不允许的(但这会让我使用不同的连接字符串...)

添加 XML 配置可以让我为不同的消息指定不同的端点,但不会有不同的 SQL 连接字符串。

我真正想要的结果是这样的:

// Set up Bus A
var busA = Configure.With(new WindsorContainerAdapter(container))
    .Transport(tc => tc.UseSqlServerInOneWayClientMode("ConnectionStringA"))
    .Subscriptions(sc => sc.StoreInSqlServer("ConnectionStringA", "RebusSubscriptions"))
    .CreateBus()
    .Start();

// Set up Bus B
var busB = Configure.With(new WindsorContainerAdapter(container))
    .Transport(tc => tc.UseSqlServerInOneWayClientMode("ConnectionStringB"))
    .Subscriptions(sc => sc.StoreInSqlServer("ConnectionStringB", "RebusSubscriptions"))
    .CreateBus()
    .Start();

// Register Bus A in Windsor
container.Register(Component.For<IBus>()
    .Named("BusA")
    .Instance(busA));

// Register a class that depends on IBus, and set it to use Bus A
container.Register(Component.For<IPublishA>()
    .ImplementedBy<PublishA>()
    .DependsOn(Dependency.OnComponent(typeof(IBus), "BusA"));

// And a registration also for IBus B, and for IPublishB to reference named "BusB"

注意:我不想监听多个总线,只向它们发布事件。其他应用程序正在监视队列,每个应用程序只侦听一个队列上的一个事件。

首先:没有办法(至少目前)无法在两个 SQL 服务器数据库之间传送消息。为了使端点之间的消息 sent/published,您需要在一个共享数据库中使用一个 table

您的设置提示那里有问题,因为您正在使用 "ConnectionStringA""ConnectionStringB" 进行传输。

我不清楚你是否真的 want/need 进行 pub/sub 消息传递 - pub/sub 是你希望每条消息有多个收件人时通常使用的方式,这通常会是某种事件(即名称为过去时的消息,如:"this and that happened")。

如果您想要一个消息的特定收件人,您想要 bus.Send 该消息,这时您的端点映射将被命中以获得消息的目的地。

如果你告诉我更多关于你想要实现的目标,我相信我可以帮助你:)

我们最终通过删除 WindsorContainerAdaptor 解决了这个问题。由于我们不处理任何消息,只有 publishing/sending,我们不需要容器适配器中的任何 'handler' 东西,我们可以将 IBus 组件的注册切换到发生在 configuration/starting 之外,而不是在其中。这使我们能够控制命名 IBus 注册。

    public static void ConfigureAndStartBus(IWindsorContainer container)
    {
        _RegisterBus(container, "ConnectionStringA" "BusA");
        _RegisterBus(container, "ConnectionStringB" "BusB");
    }

    private static void _RegisterBus(IWindsorContainer container, string connectionString, string busName)
    {
        var bus = Configure.With(new BuiltinContainerAdapter())
            .Transport(tc => tc.UseSqlServerInOneWayClientMode(connectionString))
            .Subscriptions(sc => sc.StoreInSqlServer(connectionString, "RebusSubscriptions"))
            .CreateBus()
            .Start();

        container.Register(
            Component.For<IBus>()
                .Named(busName)
                .LifestyleSingleton()
                .Instance(bus));
    }

那么在classPublishA中我们可以注册BusA的依赖,PublishB可以注册BusB的依赖。消息发送到不同的数据库,并由不同的订阅者获取以在这些不同的数据库中工作。