Несколько входных очередей в одном процессе ребуса

Я пишу приложение «мультиворкерс», используя верхнюю полку и ребус.

Моя идея состоит в том, чтобы использовать шаблон MyWorker1Namespace - MyWorker1Namespace.Messages, MyWorker2Namespace - MyWorker2Namespace.Messages.

Я хотел бы запустить приложение, не охватывая несколько процессов, вместо этого я хотел бы настроить приложение с несколькими очередями ввода, чтобы быть готовым разделить его на несколько процессов, если это необходимо.

Есть ли способ объявить несколько входных очередей и несколько рабочих потоков в одном приложении с помощью Rebus?

Я предполагаю, что конфигурация должна быть примерно такой:

<rebus inputQueue="MyWorker1Namespace.input" errorQueue="MyWorker1Namespace.error" workers="1" maxRetries="5"> </rebus>
<rebus inputQueue="MyWorker2Namespace.input" errorQueue="MyWorker2Namespace.error" workers="1" maxRetries="5"> </rebus>
...

person Ganto    schedule 01.10.2014    source источник


Ответы (1)


Поскольку XML-код app.config Rebus оптимизирован для сценариев с одним экземпляром шины на процесс, вы не можете настроить несколько шин полностью в XML, но ничто не мешает вам запускать несколько экземпляров шины. внутри того же процесса.

Я часто делал это, например. в рабочих ролях Azure, где я хочу разместить несколько логических конечных точек, не неся затрат на физически отдельные развертывания, и я также иногда делал это с помощью служб Windows, размещенных на Topshelf.

Обычно мой app.config заканчивается следующим XML:

<rebus workers="1">
    <add messages="SomeAssembly.Messages" endpoint="someEndpoint.input"/>
    <add messages="AnotherAssembly.Messages" endpoint="anotherEndpoint.input"/>
</rebus>

что позволило мне раз и навсегда настроить количество рабочих по умолчанию на шину и сопоставление конечных точек. Затем, когда мое приложение запускается, оно будет хранить контейнер IoC для каждой шины в течение всего срока службы приложения — с Windsor я обычно получаю общий установщик шины, который имеет параметры для имен очередей, что позволяет мне настроить Windsor. так:

var containers = new List<IWindsorContainer> {
    new WindsorContainer()
        // always handlers first
        .Install(FromAssembly.Containing<SomeEndpoint.SomeHandler>())

        // and then the bus, which gets started at this point
        .Install(new RebusInstaller("someEndpoint.input", "error"))

        // and then e.g. background timers and other "living things"
        .Install(new PeriodicTimersInstannce()),

    new WindsorContainer()
        .Install(FromAssembly.Containing<AnotherEndpoint.AnotherHandler>())
        .Install(new RebusInstaller("anotherEndpoint.input", "error"))
};

// and then remember to dispose each container when shutting down the process

где RebusInstaller (который является механизмом Windsor) в основном просто помещает шину с правильными именами очередей в контейнер, например. так:

Configure.With(new WindsorContainerAdapter(container))
    .Transport(t => t.UseMsmq(_inputQueueName, _errorQueueName))
    .(...) etc
    .CreateBus().Start();

Мне нравится идея, что каждый экземпляр контейнера IoC функционирует как логически независимое приложение. Таким образом, было бы легко разбить что-то в будущем, если вы хотите, например. быть в состоянии развертывать свои конечные точки независимо.

Я надеюсь, что это вдохновит вас :) пожалуйста, не стесняйтесь спрашивать, нужны ли вам дополнительные указатели.

person mookid8000    schedule 02.10.2014
comment
Спасибо за интересный ответ. Я обычно использую Ninject как IoC. Я попробую аналогичный подход, используя один контейнер с контекстной привязкой, чтобы внедрить выделенную шину для каждого воркера. - person Ganto; 06.10.2014