TIBCO EMS故障转移重新连接C# (TIBCO.EMS.dll)

13
我们有一个 TIBCO EMS 解决方案,使用内置的2-4服务器环境下的服务器故障转移。如果 TIBCO 管理员将服务从一个 EMS 服务器故障转移到另一个服务器,则连接应自动在 EMS 服务级别上转移到新服务器。对于我们使用 EMS 服务的 C# 应用程序而言,这种情况并没有发生——在故障转移后,用户连接没有被转移到新服务器,我们不确定原因。
我们的应用程序在启动时连接到 EMS,因此,如果 TIBCO 管理员在用户启动我们的应用程序之后进行故障转移,则用户需要重新启动应用程序才能重新连接到新服务器(我们的 EMS 连接使用包含所有 4 个生产 EMS 服务器的服务器字符串,如果第一次尝试失败,则移动到字符串中的下一个服务器并重试)。
我正在寻找一种自动化方法,如果检测到连接已断开,将定期尝试重新连接 EMS,但我不确定如何最好地实现。
有什么想法吗?我们正在使用 TIBCO.EMS.dll 版本 4.4.2 和 .Net 2.x(SmartClient 应用程序)。
感谢任何帮助。

你目前是如何实现容错的?在服务器上的“factories.conf”文件中吗?你的“url”属性是否包含在“tib_ems_dotnet_ref.pdf”的第134页中指定的逗号分隔的URL列表? - Anthony Mastrean
是的,信不信由你,这就是问题所在。当 EMS 服务器故障转移时,应该将连接从一个服务器传输到另一个服务器。如果您在连接字符串中有一个分隔符分隔的 EMS 服务器列表,则应该可以正常工作,但我认为 EMS.lib 中存在一个错误,导致它无法正常工作。 - ScottCher
在故障转移后,监听器会抛出错误吗? 在故障转移后,生产者(发送消息时)会抛出错误吗? 很可能,该库希望您重新连接。在连接期间,提供连接字符串中的多个服务器只是让它进行轮询 - 而不是以后... - TheSoftwareJedi
1
ConnectionAttempts设置客户端重新连接服务器的次数。ReconnectAttempts设置客户端在网络断开后尝试重新连接的次数。但是,这两个设置似乎并没有按照它们所说的那样工作。是的,在发布时我们会收到异常。 - ScottCher
Scott,(让我们清楚地了解环境)
  1. 如果还没有完成,请设置客户端以从服务器接收故障转移通知(请参阅我之前评论中提到的页面)
  2. 设置您的连接以具有ExceptionListener
  3. 确认EMSException包含备份服务器的URL
- Anthony Mastrean
显示剩余3条评论
3个回答

8
首先,是的,我在回答自己的问题。 但是需要注意的是,没有ajmastrean,我就一事无成了。非常感谢你!
一: ConnectionFactory.SetReconnAttemptCount、SetReconnAttemptDelay、SetReconnAttemptTimeout 应该适当设置。 我认为默认值重试太快(每次重试之间的间隔大约为1/2秒)。因为网络存储等原因,我们的 EMS 服务器可能需要很长时间才能进行故障转移,因此5次重试和1/2秒的间隔远远不够。
二: 我认为启用客户端-服务器和服务器-客户端心跳非常重要。尚未验证,但如果没有这些设置,客户端可能无法获得服务器离线或切换到故障转移模式的通知。当然,这是 EMS 的服务器端设置。
三: 您可以通过设置 Tibems.SetExceptionOnFTSwitch(true) 并连接异常事件处理程序来监视故障转移事件。在单服务器环境中,您将看到“连接已终止”消息。但是,如果您处于容错多服务器环境中,则会看到这个消息:“连接已执行容错切换到”。您不一定需要此通知,但它可能很有用(特别是在测试时)。
四: EMS 文档中显然不清楚,连接重新连接在单服务器环境中将不起作用。您需要处于多服务器、容错的环境中。然而,有一个窍门。您可以将同一台服务器两次放入连接列表中-这很奇怪,但它可以让内置的重新连接逻辑起作用。
一些代码:
private void initEMS()
{
    Tibems.SetExceptionOnFTSwitch(true);
    _ConnectionFactory = new TIBCO.EMS.TopicConnectionFactory(<server>);
    _ConnectionFactory.SetReconnAttemptCount(30);       // 30retries
    _ConnectionFactory.SetReconnAttemptDelay(120000);   // 2minutes
    _ConnectionFactory.SetReconnAttemptTimeout(2000);   // 2seconds
_Connection = _ConnectionFactory.CreateTopicConnectionM(<username>, <password>);
    _Connection.ExceptionHandler += new EMSExceptionHandler(_Connection_ExceptionHandler);
}
private void _Connection_ExceptionHandler(object sender, EMSExceptionEventArgs args)
{
    EMSException e = args.Exception;
    // args.Exception = "Connection has been terminated" -- single server failure
    // args.Exception = "Connection has performed fault-tolerant switch to <server url>" -- fault-tolerant multi-server
    MessageBox.Show(e.ToString());
}

6

这篇文章应该总结我的当前评论并更详细地解释我的方法...

TIBCO的“ConnectionFactory”和“Connection”类型是重型、线程安全的类型。TIBCO建议您保持每个配置工厂的一个 ConnectionFactory 和一个连接。

服务器似乎也负责现场“连接”故障转移和重连,因此让我们确认它正在执行其工作,然后依靠该功能。

创建客户端解决方案要比修复服务器或客户端设置问题稍微复杂一些。从失败的连接创建的所有会话都需要重新创建(更不用说生产者、消费者和目标了)。这两种类型都没有“重新连接”或“刷新”方法。这些会话也不保留对其父连接的引用。

您将不得不管理连接/会话对象的查找,并重新初始化它们!或实现某种会话故障事件处理程序,可以获取新连接并重新连接它们。

因此,现在让我们深入挖掘并查看客户端是否设置为接收故障转移通知(TIB EMS用户指南第292页)。并确保捕获的异常包含故障转移URL,并且正在正确处理。


1
我已经设置了Tibems.SetExceptionOnFTSwitch(true),所以现在当我们的连接失败时,我可以看到异常情况。虽然我们还没有能够在故障转移设置中进行测试,但是当连接断开时,我会收到异常情况。然而,当服务器恢复时,内置的重新连接并没有起作用。 - ScottCher
我们已经检查了服务器-客户端和客户端-服务器心跳。它们在测试环境中被禁用,我认为这可能是重新连接不起作用的原因。启用后,设置为10秒,我们仍然没有收到重新连接尝试。 - ScottCher
虽然我可以捕获服务器连接失败,这是一个好的迹象,但我宁愿让 EMS 库的重新连接逻辑自动处理重连尝试,而不是手动循环尝试重连。 - ScottCher
我处于类似的情况。我正在重构一个旧的消息系统,该系统一直在尝试重新初始化Connection实例而陷入无限循环...我希望能够避免这种情况。虽然我主要是根据TIBCO文档工作,但我并没有太多实践知识。 - Anthony Mastrean
ajmastream的意思是你可以访问文档。我基本上不得不乞求才能获得访问权限。它们被锁在网络驱动器上,所以我甚至无法阅读它们 - 自从我们开始实施以来,我一直在盲目地进行EMS操作。 - ScottCher
如果TIBCO有任何相关声明,我会在这里发布 - 我们的TIB管理员正在提交一个问题工单,其中包括我的一些代码 - 或者如果我们以其他方式解决了这个问题。感谢您的帮助。 - ScottCher

1

客户端应用程序可以通过设置tibco.tibjms.ft.switch.exception系统属性来接收故障转移通知。

也许库需要这个来工作?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接