美文网首页
2019-08-20 tomcat基于redis会话共享的集群配

2019-08-20 tomcat基于redis会话共享的集群配

作者: FredWorks | 来源:发表于2019-08-20 15:41 被阅读0次

    实际上这个需求包含三个部分:

    • 基于tomcat的多个应用节点,但并不希望配置tomcat cluster
    • 基于httpd 实现负载均衡。
    • 为实现上述目的,考虑使用redis作为集中session存储,实现一个节点登录后,在所有节点都处于已登录状态。

    tomcat的配置

    tomcat的部署和配置过程就不描述了,属于基本操作。
    这里只描述部署的结构,后面配置httpd的负载均衡时要用到。
    tomcat1:
    访问路径:http://ip1:port1/appName
    tomcat2:
    访问路径:http://ip1:port2/appName
    tomcat3:
    访问路径:http://ip2:port3/appName

    httpd负载均衡

    httpd2.4版本的配置文件结构,和我们有关的部分如下:

    /etc/httpd/
                   conf/
                   conf.d/
                   conf.module.d/
    
    1. 添加负载均衡配置
      使用如下命令编辑配置文件:
    vi /etc/httpd/conf.d/proxy.conf
    

    添加内容:

    <Proxy balancer://myCluster>
        BalancerMember http://ip1:port1/appName loadfactor=3
        BalancerMember http://ip1:port2/appName loadfactor=3
        BalancerMember http://ip2:port3/appName loadfactor=3
        ProxySet lbmethod=byrequests
    </Proxy>
    ProxyRequests Off
    ProxyPass /appName balancer://myCluster stickysession=JSESSIONID nofailover=Off
    ProxyPassReverse /appName balancer://myCluster
    
    1. 添加负载均衡监控配置
      使用个如下命令新增配置文件:
    vi /etc/httpd/conf.d/lbmgr.conf
    

    添加内容:

    <Location /balancer-manager>
        SetHandler balancer-manager
        Order Allow,Deny
        Allow from all
    </Location>
    

    其中,<Location / 后面的名字,不一定是 balancer-manager,你可以取自己喜欢的名字,比如lbmgr。在最后访问httpd的负载均衡器监控时,记得你配置的是什么就行了。
    最后访问负载均衡器监控的路径是: http://ip/lbmgr

    1. 重启httpd使配置生效:
    service httpd restart
    

    应用配置

    要让我们基于spring-mvc的遗留系统支持spring-session和redis的会话共享,需要对应用进行配置。

    1. 添加spring-session的配置
      先看配置代码,再解释:
    
    @EnableRedisHttpSession
    @PropertySource({"classpath:/com/aa/bb/config/properties/redis.properties"})
    public class SpringSessionRedisConfig {
        
        @Bean 
        public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
            return new PropertySourcesPlaceholderConfigurer();
        }
        
        @Value("${maxInactiveIntervalInSeconds}")
        private int maxInactiveIntervalInSeconds;
    
        @Value("${maxTotal}")
        private int maxTotal;
    
        @Value("${maxIdle}")
        private int maxIdle;
    
        @Value("${host}")
        private String hostName;
    
        @Value("${port}")
        private int port;
    
        @Value("${timeout}")
        private int timeout;
    
        @Value("${usePool}")
        private boolean usePool;
    
        @Value("${maxWaitMillis}")
        private int maxWaitMillis;
    
        @Value("${testOnBorrow}")
        private boolean testOnBorrow;
    
        @Value("${password}")
        private String password;
        
        @Bean
        public  redisHttpSessionConfiguration() {
            RedisHttpSessionConfiguration bean = new RedisHttpSessionConfiguration();
            bean.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
            
            return bean;
        }
        
        @Bean
        public JedisPoolConfig jedisPoolConfig() {
            JedisPoolConfig bean = new JedisPoolConfig();
            bean.setMaxIdle(this.maxIdle);
            bean.setMaxTotal(this.maxTotal);
            
            return bean;
        }
        
        @Bean(destroyMethod = "destroy")
        public RedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
            //单机版jedis
            RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
            redisStandaloneConfiguration.setHostName(this.hostName);
            redisStandaloneConfiguration.setPort(this.port);
            redisStandaloneConfiguration.setDatabase(0);
    //        redisStandaloneConfiguration.setPassword(RedisPassword.of(this.password));
            //客户端配置
            JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
                    (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
            //指定jedisPoolConifig来修改默认的连接池构造器(真麻烦,滥用设计模式!)
            jpcb.poolConfig(jedisPoolConfig);
            JedisClientConfiguration jedisClientConfiguration = jpcb.build();
            
            //单机配置 + 客户端配置 = jedis连接工厂
            return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
        }
        
        @Bean
        public StringRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            return new StringRedisTemplate(redisConnectionFactory);
        }
    }
    

    1.1. 上述配置中,最关键的是:

        @Bean
        public RedisHttpSessionConfiguration redisHttpSessionConfiguration() {
            RedisHttpSessionConfiguration bean = new RedisHttpSessionConfiguration();
            bean.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
            
            return bean;
        }
    

    因为spring-session通过RedisHttpSessionConfiguration,提供了一系列的bean和相关配置,实现了用spring-session的会话管理器替换tomcat自己的session会话管理器,并存储到redis中的效果。
    这个bean必须和 @EnableRedisHttpSession 配合使用,否则不会生效。

    1.2. 配置redis连接池
    上述配置,只是让spring-session将会话存储到redis中,但并不知道如何连接到redis,因此需要添加必要配置,告知如何连接到redis。
    实际上有多种连接器可用,我们这里使用了Jedis连接器,其他连接器的使用方式参看spring-session的官方文档即可:

        @Bean
        public JedisPoolConfig jedisPoolConfig() {
    

    这个配置提供redis连接池配置

        @Bean(destroyMethod = "destroy")
        public RedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
    

    这个配置创建redis链接工厂

        @Bean
        public StringRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    

    这个配置提供redisTemplate。

    好了,有了上述配置,到redis的链接就完成了。
    需要注意的是,这里的方法名,就是最终生成的bean的名字,同时也是spring-session查找对应bean时,使用的名字。如果要自定义名字,那么就必须要提供全套配置,否则spring-session就找不到redis链接工厂等bean了。

    1.3. 配置spring读取SpringSessionRedisConfig这个配置bean
    需要在spring的xml配置文件中,增加如下配置:

    <context:component-scan base-package="com.aa.bb.config" />
    

    这个配置让spring去扫描包 com.aa.bb.config 下的@Configuratioin 注解了的配置类。

    1.4. 配置spring-mvc filter,去拦截请求处理session
    必须让这个filter在其他filter的前面,否则可能导致其他filter工作时找不到正确的会话。

        <filter>
            <filter-name>springSessionRepositoryFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>springSessionRepositoryFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    这个配置会向spring-mvc注入一个名字叫 springSessionRepositoryFilter 的filter bean。
    这个filter bean 是在前面配置的 RedisHttpSessionConfiguration 中创建的。

    到此为止,配置就完成了。

    相关文章

      网友评论

          本文标题:2019-08-20 tomcat基于redis会话共享的集群配

          本文链接:https://www.haomeiwen.com/subject/tcspsctx.html