Несколько методов реализации распределенного сеанса

Java

Распределенный сеанс SpringBoot

В сегодняшней ситуации кластера серверов сохранение состояния сеанса входа пользователя также изменилось с одного компьютера на распределенное требование.Ниже приводится подробное описание нескольких распределенных решений для хранения сеансов.

  1. Репликация сеанса: выполнение на сервере, поддерживающем репликацию сеанса, синхронизация сеансов и поддержание согласованности сеансов.

план:tomcat-redis-session-manager

  1. Закрепленная сессия: принудительно распределять сессии на каждый сервер

Решение: балансировка нагрузки

  1. Сеанс хранения файлов cookie: хранить идентификатор сеанса в файле cookie (небезопасно, файл cookie легко украсть, он может хранить неважные данные)
  2. Централизованное управление сеансом: храните сеанс пользователя в кеше одного или кластерного сервера, и все веб-серверы берут сеанс с него для реализации совместного использования сеанса.

Решение: Redis сохраняет идентификатор сеанса, сгенерированный пользователем, или сохраняет файл cookie, который сохраняет идентификатор сеанса.

Здесь объясняется только четвертая схема, которая является наиболее стабильной и наиболее часто используемой.

Redis кэширует сеанс постоянного хранения

Redis хранит файлы cookie, в которых хранится uuid, сгенерированный пользователем (токен как sessionId)

  • имя файла cookie и срок действия
public static final String COOKIE_NAME_TOKEN = "token";
private static final ex  = 3600;

  • Создать cookie и сохранить в Redis
private String addCookie(HttpServletResponse response,SeckillUser user){
        String token = UUIDUtil.uuid();
        redisService.set(token,user);//使用redis把token作为键存储user作为值 我使用jedis自己实现的也可以使用redisTemplate
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);//设置cookie 名称为token
        cookie.setMaxAge(ex);//设置过期时间 
        cookie.setPath("/");
        response.addCookie(cookie);
        return token;
    }

  • uuid как инструмент генерации sessionid
public class UUIDUtil {
    public static String uuid(){
        return UUID.randomUUID().toString();
    }
}

Интегрировано с использованием Широcrazy-cake(Используйте Redis для хранения SessionId)

  • Shiro — это фреймворк веб-безопасности для аутентификации при входе в систему, авторизации удостоверения пользователя, простой в использовании.spring-security, вы также можете наследовать сеанс, распределенное хранилище файлов cookie

Если вы не знаете, вы можете прочитать этот пост в блоге:Использование Shiro и интеграция Redis для кеширования

тайник

  • Использовать кеш для хранения сессий (один сервер использует EhCacheManager)
  • Однако в распределенной системе, в случае кластеров серверов, EhCacheManager не может решить проблему совместного использования данных (база данных будет запрашиваться несколько раз), поэтому выберите использование Redis в качестве кеша.
Redis реализует кеш Широ

  • Распределенный обмен информацией о сеансе и авторизации должен сохранять сеанс и авторизацию в базе данных или кэшировать кластер Shiro, чтобы предотвратить множественные вставки и запросы к базе данных.
  • Пользовательский класс реализации: или используйте shiro-redis с открытым исходным кодом Crazycake для реализации хороших инструментов.
    • RedisSessionDAOМожет наследовать EnterpriseCacheSessionDAO для управления сеансом.
    • RedisCacheНаследуйте класс Cache для реализации конкретных кэшей операций Redis (удаление, получение, установка, ключи и т. д.).
    • RedisCacheManagerРеализовать getCache интерфейса CacheManager, чтобы получить RedisCache и передать его в securityManager для управления.

Используйте ConcurrentMap для более эффективного управления данными и кешем

  1. существуетShiroConfigкласс конфигурацииsessionManagerсдаватьDefaultWebSecurityManagerуправлять
@Bean
    public DefaultWebSessionManager sessionManager(){
        DefaultWebSessionManager sessionManager  = new DefaultWebSessionManager();
        //session时间
        sessionManager.setGlobalSessionTimeout(redisConfig().getTimeout());
        //删除无效session
        sessionManager.setDeleteInvalidSessions(true);
        log.info("sessionManager注入成功");
        sessionManager.setSessionIdCookie(cookie());
        // sessionDao 分布式共享session和授权信息需要把session和授权持久化到数据库或者缓存 shiro集群为了防止多次插查询数据库
        sessionManager.setSessionDAO(redisSessionDao());
        return sessionManager;
    }

  1. существуетsessionManagerВнедрить хранилище cookie вjsessionId
@Bean
    public SimpleCookie cookie() {
        SimpleCookie cookie = new SimpleCookie("JSESSIONID");
        cookie.setHttpOnly(true);
        cookie.setPath("/");
        return cookie;
    }

  1. сноваsessionManagerинъекцияredisSessionDaoОтвечает за сохранение сеанса
@Bean
    public RedisSessionDAO redisSessionDao(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        redisSessionDAO.setSessionIdGenerator(sessionIdGenerator());
        return redisSessionDAO;
    }