我有一个使用JBoss作为应用程序服务器的分布式系统应用程序。我有一个客户端应用程序作为模拟引擎。当客户端启动时,它会向服务器发送注册消息(JMS消息),然后在数据库中设置一些字段。当服务器启动时,它会向所有客户端发送一条消息(主题),以检查它们是否处于活动状态。如果客户端处于活动状态,他们可以读取消息并向服务器(队列)发送响应,表明它还处于活动状态。
如果用户正常关闭客户端,客户端会向服务器发送一条消息,我将取消注册。然后服务器取消注册它。这是在数据库方面完成的。
如果用户异常关闭客户端(kill),则客户端无法向服务器发送消息以进行取消注册。然后服务器不知道这个客户端不再活着。这会导致我的应用程序不一致。所以我需要一种方法来理解订阅主题的客户端不再订阅。
服务器向主题发送消息以检查客户端是否存活。
@Schedule(hour = "*", minute = "*", second = "30", persistent = false)
public void sendNodeStatusRequest() {
Message msg = MessageFactory.createStatusRequestMessage();
publishNodeMessage(msg);
}
一段时间后,服务器显示以下日志。我可以从Java那里听到这个警告吗?
07:17:00,698 WARN [org.hornetq.core.protocol.core.impl.RemotingConnectionImpl] Connection failure
has been detected: Did not receive ping from /127.0.0.1:61888. It is likely
the client has exited or crashed without closing its connection, or the
network between the server and client has failed. The connection will now be closed. [code=3]
07:17:00,698 WARN [org.hornetq.core.server.impl.ServerSessionImpl] Client
connection failed, clearing up resources for session 4e4e9dc6-153e-11e7-
80fa-742b62812c29
答案 0 :(得分:3)
对我而言,消息系统的重点是解耦通信。发件人(在您的情况下为服务器)将其内容发送到主题,而实际上不知道谁将获得该消息。客户来来往往,只要它(仍然)存在于主题中,他们就应该能够阅读该消息。
现在从您的问题中我了解到服务器通过将消息接收回专用队列来跟踪所有连接的客户端。
所以我问自己 - 也许这里的设计有问题。
让我提出略有不同的实施方式。 服务器最多不应该知道任何客户端(因为你的系统似乎这样工作)它应该知道客户端A,B和C现在只有,因为这些客户端传递给服务器这个知识强>
为什么不让客户端每隔1分钟(或更少,根据您的需要)向服务器队列发送“保持活动”消息,而不从服务器发送先前消息。 该消息可以包括一些客户端标识符,如果它没有被基础结构添加,则可能是时间)
因此,服务器将获得此消息,它将在内存中跟踪可用客户端列表以及他们上次发送内容的时间。 因此,如果某个客户端“正常”断开连接 - 它可以向服务器发送特殊消息,例如“我是客户端A并认为我已断开连接”。否则(异常终止/网络中断/无论如何) - 它只是不会发送任何东西,服务器将有一个特殊的进程,将检查列表中是否有陈旧的客户端,如果它找到它们 - 它知道出了问题。
答案 1 :(得分:0)
如果您仍然希望坚持使用JMS的方式,那么您可以尝试同步发送消息,这意味着生产者将等待它从消费者那里听到。更多信息请访问:http://docs.oracle.com/javaee/6/tutorial/doc/bncfa.html