Rebus新手问题

时间:2016-12-20 17:50:58

标签: c# msmq rebus

我一直在评估不同的.Net消息传递组件,我在使用MSMQ的Rebus上遇到了一些麻烦,我无法通过文档,示例或谷歌解决这些问题。

我相信我的方案唯一独特之处在于我的客户可以发送或发布消息。看起来应该很简单,但我遇到了以下问题。代码片段遵循这些问题。

的问题:

  1. 未处理MetersRequest。它们只是堆积在outgoingMetersRequests队列中。
  2. 收到错误消息,指出creditAuthRequests队列不存在或我没有权限。我已经确认队列没有被创建,但我的假设是Rebus将确保在创建outgoingMetersRequests队列时创建它。 (旁注:如果我从Bus.Send(...)中删除'await',错误就会消失,但仍然没有创建队列,也没有找到消息。)
  3. ===========

    FROM CLIENT

        private void InitializeBus()
        {
             _messageActivator = new BuiltinHandlerActivator();
             Configure.With(_messageActivator)
                .Transport(t => t.UseMsmq("publisher"))
                .Routing(r => r.TypeBased().Map<MetersRequest>("outgoingMetersRequests")
                .Map<CreditAuthorizationRequest>("creditAuthRequests"))
                .Start();
        }
    
        private async Task SendCreditAuthRequestAsync(int numberToSend)
        {
             var cardNumber = generateCardNumber();
             await _messageActivator.Bus.Send(new CreditAuthorizationRequest(cardNumber));
             await WriteOutputAsync($"Sent credit auth request for card {cardNumber}.");
        }
    
        private async Task SendMetersRequestAsync(int numberToSend)
        {
             await _messageActivator.Bus.Send(new MetersRequest());
             await WriteOutputAsync("Sent meters request.");
        }
    

    ===========结束客户

    ============

    FROM SERVICE

        private void InitializeBus()
        {
            _messageActivator = new BuiltinHandlerActivator();
            _messageActivator.Register<PosOnlineHandler>(() => new PosOnlineHandler(WriteOutputAsync));
            _messageActivator.Register<PumpDownHandler>(() => new PumpDownHandler(WriteOutputAsync));
            _messageActivator.Register<MetersRequestHandler>(() => new MetersRequestHandler(WriteOutputAsync, _messageActivator.Bus));
            _messageActivator.Register<CreditAuthorizationHandler>(() => new CreditAuthorizationHandler(WriteOutputAsync, _messageActivator.Bus));
            Configure.With(_messageActivator)
                .Transport(t => t.UseMsmq("subscriber1"))
                .Routing(r => r.TypeBased()
                    .Map<PumpDownEvent>("publisher")
                    .Map<PosOnlineEvent>("publisher")
                    .Map<MetersRequest>("outgoingMetersRequests")
                    .Map<CreditAuthorizationRequest>("creditAuthRequests"))
            .Start();
           _messageActivator.Bus.Subscribe<PumpDownEvent>().Wait();
           _messageActivator.Bus.Subscribe<PosOnlineEvent>().Wait();
        }
    
    public class MetersRequestHandler : IHandleMessages<MetersRequest>
    {
        private readonly Random _randomizer = new Random();
        private readonly Func<string, Task> _outputDelegate2;
        private readonly IBus _messageBus;
    
        public MetersRequestHandler(Func<string, Task> outputDelegate, IBus messageBus)
        {
            _outputDelegate2 = outputDelegate;
            _messageBus = messageBus;
        }
    
        public async Task Handle(MetersRequest message)
        {
            var pump = _randomizer.Next(20);
            var meters = _randomizer.Next();
            decimal dollars = (decimal)_randomizer.NextDouble();
    
            var response = new MetersResponse(pump, meters, dollars);
            await _outputDelegate2($"Sending MetersResponse: (Pump={pump}) (Meters={meters}) (Dollars ={dollars}");
            await _messageBus.Reply(response);
        }
    }
    

    ============

1 个答案:

答案 0 :(得分:1)

在您发布的代码中,有几件事情似乎有点不对劲。我只会评论你的问题,然后我会提出一个前进的方法:)

  

未处理MetersRequest。它们只是在outgoingMetersRequests队列中堆积。

当您致电.Routing(t => t.TypeBased().Map<SomeMessage>("someQueue"))时,您说Rebus端点的SomeMessage类型由输入队列someQueue“拥有”。

当您await bus.Send(yourMessage)时,Rebus将获得拥有yourMessage类型的队列并在那里发送消息。这很好地解释了为什么MetersRequest转到outgoingMetersRequests队列。

但是,您尚未发布任何显示端点,其中outgoingMetersRequests队列作为其输入队列的代码。有人需要处理该队列中的消息才能发生某些事情。

“输入队列”是您在.Transport(t => t.UseMsmq("publisher"))部分中配置的内容 - 在这种情况下,输入队列为publisher

  

收到错误消息,指出creditAuthRequests队列不存在或我没有权限。

是的 - MSMQ错误消息通常不是最好的;)

  

我已经确认队列没有被创建,但我的假设是Rebus将确保在创建outgoingMetersRequests队列时创建它。

Rebus(使用MSMQ)仅创建输入队列和错误队列(默认情况下称为error)。这意味着您必须至少使用outgoingMetersRequests作为其输入队列运行一个端点,或者您是否手动创建了队列?

  

(旁注:如果我从Bus.Send(...)中删除'await',错误就会消失,但仍然没有创建队列,也没有找到消息。)

错误不会消失 - 异常被捕获并传递给在线程池线程上运行的延续,您永远不会看到它,因为您放弃了从Task返回的Send

我建议你这样做:

  1. 为输入队列提供良好的名称 - publishersubscriber过于通用,您应该首先选择与每个端点的责任或原因相对应的名称。< / p>

  2. 注意您的消息类型。您已将此事件命名为事件*Event,并且您对请求/回复的使用看起来也正确。

  3. 使用某种共享订阅存储,例如一个中央SQL Server。这样 - 如果您在所有发布者和订阅者中配置相同的集中订阅存储 - 您的事件类型不需要任何端点映射,这非常简洁。您可以在the wiki page about subscription storages

  4. 部分的the centralized type上阅读更多内容