我今天遇到了障碍。在我们的组织中,所有部署都由TFS Build完成。每个NSB主机组件由构建门户打包和部署的位置。当我们尝试使用NSB的Scale-Out功能时,我们必须使用Master和Worker配置文件安装相同的组件。我们管理了Master&工作者安装程序通过在打包时传递所需的参数。为了简化流程,我们计划为Master和Worker使用一个配置文件,我们为master和worker保留了MasterNode配置。一切都好!它运作得非常好。
根据策略,我们不应该在配置文件上使用服务器名称,我们必须在Config文件中使用DNS别名。我们通过在DNS别名之上启用MSMQ工作来实现它。
现在真正的问题开始了, NServiceBus.Master配置文件将Node值附加到输入队列中。当我们将DNS别名用作Node时,它会抛出以下异常。
System.Exception:启动端点时出现异常,错误已经发生 登录。原因:输入队列[somequeue@some-dns.bus]必须在 与此过程相同的机器[SOMEDITSERVER01]。 ---> System.InvalidOperationException:输入队列 [somequeue@some-dns.bus]必须与此过程位于同一台计算机上 [SOMEDITSERVER01]。在 NServiceBus.Unicast.Queuing.Msmq.MsmqMessageReceiver.Init(地址 地址,布尔事务处理) NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.NServiceBus.Unicast.Transport.ITransport.Start(地址 地址) NServiceBus.Unicast.UnicastBus.NServiceBus.IStartableBus.Start(动作 在NServiceBus.Hosting.GenericHost.Start()
的startupAction---内部异常堆栈跟踪结束--- at NServiceBus.Hosting.GenericHost.Start()at Magnum.StateMachine.EventActionList`1.Execute(T stateMachine,Event event,Object parameter)
---内部异常堆栈跟踪结束--- at Magnum.StateMachine.ExceptionActionDictionary
1.HandleException(T stateMachine, Event event, Object parameter, Exception exception)
1.Execute(T stateMachine,Event event,Object parameter)at Magnum.StateMachine.State
at Magnum.StateMachine.EventActionList1.RaiseEvent(T instance, BasicEvent
1 eevent,Object value)at Magnum.StateMachine.StateMachine`1.RaiseEvent(Event raise)at Topshelf.Internal.ServiceControllerProxy.Start()at Topshelf.Internal.ServiceCoordinator.Start()at Topshelf.Internal.Hosts.ConsoleHost.Run()at NServiceBus.Hosting.Windows.Program.Main(String [] args)
问题:
为什么NSB将MasterNode值附加到输入队列&其他队列,当NSB严格查找当前MachineName作为当前输入队列的有效服务器名称时? 为什么NSB在使用NServiceBus.Master或NServiceBus.Distributor运行时忽略MasterNode值?
如果NSB仍想在输入队列上附加MasterNode值... 为什么NSB不解析DNS名称,而是使用当前MachineName进行验证?
var configSection = Configure.GetConfigSection<MasterNodeConfig>();
if (configSection == null)
{
return;
}
var ipAddressesOfNode = Dns.GetHostEntry(configSection.Node).AddressList.Select(ip => ip.ToString()).ToArray();
var ipAddressesOfHost = Dns.GetHostEntry(Environment.MachineName).AddressList.Select(ip => ip.ToString()).ToArray();
if (ipAddressesOfHost.Any(ipAddressesOfNode.Contains))
{
//Valid DNS Name
}
最后,我们最终得到以下选项,
1. 失败的方法:更改IHandleProfile上的MasterNodeConfig的Node值。我喜欢这种方法,但它有一些缺点。它不会工作,因为MasterNodeConfig没有覆盖IsReadonly()的默认行为,它会抛出错误。如果您使用集成配置文件,则在安装过程中不会创建Worker&amp;分销商队列
internal class MasterNodeConfigSetup : IHandleProfile<Master>
{
public void ProfileActivated()
{
var configSection = Configure.GetConfigSection<MasterNodeConfig>();
configSection.Node = Environment.MachineName;
}
}
有一种黑客可以绕过上面代码创建的运行时错误。但是如果你手动注意其他队列创建,我们可以使用它;
var field = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(configSection, false);
configSection.Node = Environment.MachineName;
}
2.保留两个不同的Config文件,用于worker和master&amp;打包它。很多工作看起来都很可行。
3.在主组件部署期间删除MasterNodeConfig。
我不反对NSB,我喜欢NSB。我只是表达了我的沮丧,想知道原因为什么!为什么它附加MasterNode值&amp;为什么它只是用Environemnt验证而不是解决它。
我非常愿意接受你的任何建议。