Позвольте мне сам четко ответить на этот вопрос.
После долгих поисков и помощи Андреаса Олунда из команды NSB (http://tech.groups.yahoo.com/group/nservicebus/message/17758) правильный ответ на этот вопрос:
- Как упоминал Уди Дахан, по замыслу ТОЛЬКО дистрибьютор / главный узел должен запускать диспетчер тайм-аута в сценарии горизонтального масштабирования.
- К сожалению, в ранних версиях NServiceBus 3 это реализовано не так, как задумано.
У вас есть 3 проблемы:
1) Работа с профилем распространителя НЕ запускает диспетчер тайм-аута.
Обходной путь:
Запустите диспетчер тайм-аута на дистрибьюторе самостоятельно, включив в него этот код:
class DistributorProfileHandler : IHandleProfile<Distributor>
{
public void ProfileActivated()
{
Configure.Instance.RunTimeoutManager();
}
}
Если вы запускаете главный профиль, это не проблема, поскольку на главном узле автоматически запускается диспетчер тайм-аута.
2) Каждый рабочий, работающий с профилем рабочего, запускает локальный диспетчер тайм-аута.
Это не так, как задумано, и мешает опросу хранилища тайм-аутов и отправке тайм-аутов. Все рабочие опрашивают хранилище тайм-аутов, говоря: «Дайте мне ближайшие таймауты для MASTERNODE». Обратите внимание, что они запрашивают таймауты для MASTERNODE, а не для W1, W2 и т. Д. Таким образом, несколько воркеров могут в конечном итоге получить одни и те же тайм-ауты из хранилища тайм-аутов одновременно, что приведет к конфликтам с Raven при удалении тайм-аутов из него.
Диспетчеризация всегда происходит через ЛОКАЛЬНЫЕ очереди .timouts / .timeoutsdispatcher, в то время как ДОЛЖНА осуществляться через очереди диспетчера тайм-аута на MasterNode / Distributor.
Обходной путь, вам нужно сделать оба:
а) Отключите диспетчер тайм-аута для рабочих. Включите этот код в своих рабочих
class WorkerProfileHandler:IHandleProfile<Worker>
{
public void ProfileActivated()
{
Configure.Instance.DisableTimeoutManager();
}
}
б) Перенаправьте NServiceBus на рабочих, чтобы использовать очередь .timeout на главном узле / распространителе.
Если вы этого не сделаете, любой вызов RequestTimeout или Defer для рабочего прекратит работу, за исключением того, что вы забыли настроить диспетчер тайм-аута. Включите это в конфигурацию вашего рабочего:
<UnicastBusConfig TimeoutManagerAddress="{endpointname}.Timeouts@{masternode}" />
3) Ошибочные сообщения «Готово» обратно дистрибьютору.
Поскольку диспетчер тайм-аута отправляет сообщения непосредственно в очереди ввода рабочих, не удаляя запись из доступных воркеров в очереди хранилища распределителя, рабочие отправляют ошибочные сообщения «Готово» обратно распределителю после обработки тайм-аута. Это происходит, даже если вы исправили 1 и 2, и не имеет значения, был ли тайм-аут получен от локального диспетчера тайм-аута на рабочем или на распределителе / главном узле. Следствием этого является создание дополнительной записи в очереди хранилища на распределителе для каждого тайм-аута, обрабатываемого работником.
Решение: используйте NServiceBus 3.3.15 или новее.
person
janovesk
schedule
10.02.2013