【发布时间】:2017-09-01 05:43:55
【问题描述】:
在包org.springframework.messaging.simp.user 中有一个类MultiServerUserRegistry。
这个类看起来可以在多服务器应用程序上工作,但我找不到任何文档可以帮助我理解它是如何工作的或者我应该如何使用它。
这个类有什么作用以及如何使用它?如何使用 websocket 处理多服务器应用程序?
【问题讨论】:
在包org.springframework.messaging.simp.user 中有一个类MultiServerUserRegistry。
这个类看起来可以在多服务器应用程序上工作,但我找不到任何文档可以帮助我理解它是如何工作的或者我应该如何使用它。
这个类有什么作用以及如何使用它?如何使用 websocket 处理多服务器应用程序?
【问题讨论】:
默认发布机制使用本地会话存储库来解析用户的套接字 ID。
如果您正在设置集群,则不能使用此策略。我们需要使用远程存储库。
removeRepository 已经作为 MultiServerUserRegistry 存在于 Spring 中。要激活它,您只需配置您的 MessageBrokerRegistry :
registry.enableStompBrokerRelay("/topic/", "/queue/", "/exchange/")
.setUserDestinationBroadcast("/topic/unresolved-user")
.setUserRegistryBroadcast("/topic/user-registry")
它对我来说很好用。我希望它会有所帮助。
【讨论】:
根据 MultiServerUserRegistry 的 JavaDoc,它是 SimpUserRegistry 的一个实现,它使我们能够查找本地和远程用户注册表。
在“本地”用户注册表中查找用户的 SimpUserRegistry 以及一组“远程”用户注册表。本地注册表提供为 通过广播更新远程注册表时的构造函数参数 由 UserRegistryMessageHandler 处理,然后通知此 收到更新时的注册表。
另一个SimpUserRegistry的实现是DefaultSimpUserRegistry,它只能获取本地用户。
我看了相关的源码知道,当我们在 enableStompBrokerRelay 中配置 setUserRegistryBroadcast 时,会创建一个 MultiServerUserRegistry,无论他们连接在集群中的哪个服务器,我们都可以获取所有用户的在线状态。
这里是 AbstractMessageBrokerConfiguration 中的关键源代码:
@Bean
@SuppressWarnings("deprecation")
public SimpUserRegistry userRegistry() {
SimpUserRegistry registry = createLocalUserRegistry();
if (registry == null) {
registry = createLocalUserRegistry(getBrokerRegistry().getUserRegistryOrder());
}
boolean broadcast = getBrokerRegistry().getUserRegistryBroadcast() != null;
return (broadcast ? new MultiServerUserRegistry(registry) : registry);
}
由于这个函数带有@Bean注解,我们可以通过@Autowired获取SimpUserRegistry实例:
@Autowired
private SimpUserRegistry simpUserRegistry;
使用这个接口,我们可以:
/**
* Get the user for the given name.
* @param userName the name of the user to look up
* @return the user, or {@code null} if not connected
*/
@Nullable
SimpUser getUser(String userName);
/**
* Return a snapshot of all connected users.
* <p>The returned set is a copy and will not reflect further changes.
* @return the connected users, or an empty set if none
*/
Set<SimpUser> getUsers();
/**
* Return the count of all connected users.
* @return the number of connected users
* @since 4.3.5
*/
int getUserCount();
/**
* Find subscriptions with the given matcher.
* @param matcher the matcher to use
* @return a set of matching subscriptions, or an empty set if none
*/
Set<SimpSubscription> findSubscriptions(SimpSubscriptionMatcher matcher);
我们可以使用它来获取整个集群中所有在线用户的数量(getUserCount),并检测特定用户是否在线(getUser)。
作为我的实践,在多服务器场景中建议使用以下消息代理配置:
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableStompBrokerRelay("/topic", "/queue")
.setUserDestinationBroadcast("/topic/log-unresolved-user")
.setUserRegistryBroadcast("/topic/log-user-registry")
.setRelayHost(brokerConfig.getHost())
.setRelayPort(brokerConfig.getPort())
.setVirtualHost(brokerConfig.getVirtualHost())
.setClientLogin(brokerConfig.getUsername())
.setClientPasscode(brokerConfig.getPassword())
.setSystemLogin(systemUsername)
.setSystemPasscode(systemPassword);
}
【讨论】: