我今天遇到了障碍 . 在我们的组织中,所有部署都由TFS Build完成 . 每个NSB主机组件由构建门户打包和部署的位置 . 当我们尝试使用NSB的Scale-Out功能时,我们必须使用Master和Worker配置文件安装相同的组件 . 我们通过在打包时传递所需的参数来管理Master&Worker安装程序 . 为了简化流程,我们计划为Master和Worker使用一个配置文件,我们为master和worker保留了MasterNode配置 . 一切都好!它运作得很好 .

根据策略,我们不应该在配置文件上使用服务器名称,我们必须在Config文件中使用DNS别名 . 我们通过在DNS别名之上启用MSMQ工作来实现它 .

现在真正的问题开始了,NServiceBus.Master配置文件将Node值附加到输入队列上 . 当我们将DNS别名用作Node时,它会抛出以下异常 .

System.Exception:启动 endpoints 时出现异常,已记录错误 . 原因:输入队列[somequeue@some-dns.bus]必须与此进程[SOMEDITSERVER01]在同一台机器上 . ---> System.InvalidOperationException:输入队列[somequeue@some-dns.bus]必须与此进程[SOMEDITSERVER01]在同一台机器上 . 在NServiceBus.Unicast.Queuing.Msmq.MsmqMessageReceiver.Init(地址,布尔事务),位于NServiceBus.Unicast.UnicastBus的NServiceBus.Unicast.Transport.Transactional.Transactionalnsnsport.NServiceBus.Unicast.Transport.ITransport.Start(地址) . NServiceBus.IStartableBus.Start(Action startupAction)位于NServiceBus.Hosting.GenericHost.Start()---内部异常堆栈跟踪结束---位于Magnum.StateMachine.EventActionList1的NServiceBus.Hosting.GenericHost.Start() . 执行(T stateMachine,Event事件,Object参数)---内部异常堆栈跟踪的结束---在Magnum.StateMachine.EventActionList1的Magnum.StateMachine.ExceptionActionDictionary1.HandleException(T stateMachine,Event事件,Object参数,Exception异常)处在Topshelf.Internal.ServiceCo的Magnum.StateMachine.StateMachine1.RaiseEvent(事件引发)的Magnum.StateMachine.State1.RaiseEvent(T实例,BasicEvent1 eevent,Object value)中的.Execute(T stateMachine,Event事件,Object参数)在NSsviceBus.Hosting.Windows.Program.Main(String [] args)的Topshelf.Internal.Hosts.ConsoleHost.Run()中的Topshelf.Internal.ServiceCoordinator.Start()中的ntrollerProxy.Start()

Questions:

当NSB严格查找当前MachineName作为当前输入队列的有效服务器名称时,为什么NSB会在输入队列和其他队列上附加MasterNode值?为什么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. Failed Approach: 更改IHandleProfile上的MasterNodeConfig的Node值 . 我喜欢这种方法,但它有一些缺点 . 它不会工作,因为MasterNodeConfig没有覆盖IsReadonly()的默认行为,它会抛出错误 . 如果使用集成配置文件,则在安装期间不会创建Worker&Distributor队列
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.为worker和master保存两个不同的Config文件并打包它 . 很多工作看起来都可行 .

3.在主组件部署期间删除MasterNodeConfig .

我不反对NSB,我喜欢NSB . 我只是表达了我的沮丧,想知道原因为什么!为什么它附加了MasterNode值以及为什么它只是用Environemnt验证而不是解析它 .

我非常愿意接受你的任何建议 .