我今天遇到了路障。在我们的组织中,所有的部署都是由 TFS Build 完成的。每个 NSB 主机组件都由构建门户打包和部署。当我们尝试使用 NSB 的横向扩展功能时,我们必须使用 Master 和 Worker 配置文件安装相同的组件。我们通过在打包时传递所需的参数来管理 Master 和 Worker 安装程序。为了简化流程,我们计划为 Master 和 Worker 使用一个配置文件,我们为 Master 和 Worker 保留 MasterNode 配置。一切都好!它工作得非常好。
根据政策,我们不应该在配置文件中使用服务器名称,我们必须在我们的配置文件中使用 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(Action startupAction) 在 NServiceBus.Hosting.GenericHost.Start()
--- 内部异常堆栈跟踪结束 --- 在 Magnum.StateMachine.EventActionList 的 NServiceBus.Hosting.GenericHost.Start() 处`1.Execute(T stateMachine, Event event, Object parameter)
--- 内部异常堆栈跟踪结束 --- 在 Magnum.StateMachine.ExceptionActionDictionary 1.Execute(T stateMachine, Event event, Object parameter) at Magnum.StateMachine.State 1 eevent, Object value) at Magnum.StateMachine.StateMachine` 1.RaiseEvent(事件引发)在 Topshelf.Internal.ServiceControllerProxy.Start() 在 Topshelf.Internal.ServiceCoordinator.Start() 在 Topshelf.Internal.Hosts.ConsoleHost.Run() 在 NServiceBus.Hosting.Windows.Program.Main(字符串 [] 参数)
1.HandleException(T stateMachine, Event event, Object parameter, Exception exception)
at Magnum.StateMachine.EventActionList1.RaiseEvent(T instance, BasicEvent
问题:
当 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.失败的方法:更改 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保留两个不同的配置文件并打包。很多工作看起来是可行的。
3.在Master组件部署过程中移除MasterNodeConfig。
我不反对NSB,我喜欢NSB。我只是表达我的沮丧,想知道为什么!为什么它附加 MasterNode 值以及为什么它只是用 Environemnt 验证而不是解决它。
我非常愿意接受您的任何建议。