gpt4 book ai didi

Tomcat集群中的Spring Websocket

转载 作者:IT老高 更新时间:2023-10-28 13:49:57 26 4
gpt4 key购买 nike

在我们当前的应用程序中,我们在 STOMP 上使用 Spring Websockets。我们正在寻求水平扩展。关于我们应该如何处理多个 tomcat 实例上的 websocket 流量以及我们如何跨多个节点维护 session 信息,是否有任何最佳实践。是否有可以引用的工作示例?

最佳答案

您的需求可以分为 2 个子任务:

  • 跨多个节点维护 session 信息:您可以尝试由 Redis 支持的 Spring Sessions 集群(请参阅:HttpSession with Redis)。这非常非常简单,并且已经支持 Spring Websockets(参见:Spring Session & WebSockets)。
  • 处理多个 tomcat 实例上的 websockets 流量:有几种方法可以做到这一点。
  • 第一种方式:使用全功能代理(例如:ActiveMQ)并尝试新功能 Support multiple WebSocket servers (来自:4.2.0 RC1)
  • 第二种方式:使用全功能代理并实现分布式UserSessionRegistry (例如:使用 Redis :D )。默认实现 DefaultUserSessionRegistry使用内存存储。

  • 更新:我用Redis写了一个简单的实现,有兴趣的可以试试

    要配置功能齐全的代理(代理中继),您可以尝试:
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    ...

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableStompBrokerRelay("/topic", "/queue")
    .setRelayHost("localhost") // broker host
    .setRelayPort(61613) // broker port
    ;
    config.setApplicationDestinationPrefixes("/app");
    }

    @Bean
    public UserSessionRegistry userSessionRegistry() {
    return new RedisUserSessionRegistry(redisConnectionFactory);
    }

    ...
    }


    import java.util.Set;

    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.BoundHashOperations;
    import org.springframework.data.redis.core.BoundSetOperations;
    import org.springframework.data.redis.core.RedisOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import org.springframework.messaging.simp.user.UserSessionRegistry;
    import org.springframework.util.Assert;

    /**
    * An implementation of {@link UserSessionRegistry} backed by Redis.
    * @author thanh
    */
    public class RedisUserSessionRegistry implements UserSessionRegistry {

    /**
    * The prefix for each key of the Redis Set representing a user's sessions. The suffix is the unique user id.
    */
    static final String BOUNDED_HASH_KEY_PREFIX = "spring:websockets:users:";

    private final RedisOperations<String, String> sessionRedisOperations;

    @SuppressWarnings("unchecked")
    public RedisUserSessionRegistry(RedisConnectionFactory redisConnectionFactory) {
    this(createDefaultTemplate(redisConnectionFactory));
    }

    public RedisUserSessionRegistry(RedisOperations<String, String> sessionRedisOperations) {
    Assert.notNull(sessionRedisOperations, "sessionRedisOperations cannot be null");
    this.sessionRedisOperations = sessionRedisOperations;
    }

    @Override
    public Set<String> getSessionIds(String user) {
    Set<String> entries = getSessionBoundHashOperations(user).members();
    return (entries != null) ? entries : Collections.<String>emptySet();
    }

    @Override
    public void registerSessionId(String user, String sessionId) {
    getSessionBoundHashOperations(user).add(sessionId);
    }

    @Override
    public void unregisterSessionId(String user, String sessionId) {
    getSessionBoundHashOperations(user).remove(sessionId);
    }

    /**
    * Gets the {@link BoundHashOperations} to operate on a username
    */
    private BoundSetOperations<String, String> getSessionBoundHashOperations(String username) {
    String key = getKey(username);
    return this.sessionRedisOperations.boundSetOps(key);
    }

    /**
    * Gets the Hash key for this user by prefixing it appropriately.
    */
    static String getKey(String username) {
    return BOUNDED_HASH_KEY_PREFIX + username;
    }

    @SuppressWarnings("rawtypes")
    private static RedisTemplate createDefaultTemplate(RedisConnectionFactory connectionFactory) {
    Assert.notNull(connectionFactory, "connectionFactory cannot be null");
    StringRedisTemplate template = new StringRedisTemplate(connectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new StringRedisSerializer());
    template.afterPropertiesSet();
    return template;
    }

    }

    关于Tomcat集群中的Spring Websocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26853745/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com