springboot+shiro+redis实现高可用集群,shiro连接哨兵redis集群,springboot配置方法,接上篇文章

在上篇文章中,我记录了keeplived+nginx+tomcat实现高可用nginx集群,并且主备切换可以发送邮件提示管理员,链接:

centos7+keepalived+nginx+tomcat+springboot实现nginx+tomcat高可用以及故障邮件通知

shiro分布式session共享(链接单机redis)

nginx+springboot+shiro+redis实现分布式session共享,同一项目部署多份实现负载均衡

本文章要实现的需求是做到redis高可用,我要做的就是实现基本的高可用就是两个服务器,两个redis做高可用,redis做集群的话可以用哨兵模式,也可以用cluster模式,cluster模式解决数据量大,提高性能,我要实现单项目,小数据量的高可用,数据量小的话省事来吧,搭建redis哨兵模式,项目业务可以连接redis集群,shiro的Session也是要放入redis集群,本文主要介绍我搭建shiro连接哨兵模式集群redis的过程

两台centos7虚拟机安装redis,编译安装,或者是吧编译好的redis文件直接复制过来就可以,我之前的的文章有介绍怎么在oracle vm虚拟机安装centos7虚拟机。以及redis等的安装,有兴趣的伙伴可以访问下我的主页哦!

redis配置文件相较於单机redis主要做如下修改,首先为了使主从之间可以相互切换意思是:主机宕机,切换到从机,这时原来的从机是主机,原来的主机宕机,管理严修复启动原来宕机的主机后,原来的主机变为从机,这时主从互换了身份,然后现在主机再次宕机后,从机又升级为主机,有点晕了。。,重要的就是都相互配置上对方的远程连接密码,方法如下

【masterauth:要连接的密码】,注意是对方的密码,其次,从机比主机多一项【slaveof:192.168.1.6】,此ip地址是主机的ip地址

这样分别启动主机,从机,进入命令行使用info命令就可以查看主从状态了,如下

主机info信息

从机info信息

这样主从建立了连接,可以信息同步,但需要主机,从机可读,不可写,从机升级为主机后才可读可写

接下来要开启哨兵监控

创建sentinel.conf文件和redis-sentinel命令放在同级目录就可以,如下:

 主机sentinel.conf配置文件:

port 26379
# 守护进程模式
daemonize yes
# # 指明日志文件名
logfile "./sentinel.log"
#
dir "/opt/redis/redis-property/bin"
sentinel myid 40c7dd9ddad12a4c4dcf652dcb7b45a8dc5d8b0d
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.1.21 6666 1
sentinel down-after-milliseconds mymaster 5000

# Generated by CONFIG REWRITE
protected-mode no
sentinel failover-timeout mymaster 18000
sentinel auth-pass mymaster property
sentinel config-epoch mymaster 8
sentinel leader-epoch mymaster 9
sentinel known-replica mymaster 192.168.1.22 6666
sentinel known-sentinel mymaster 192.168.1.21 26379 8894c1030073e2062ea8369261528e1338919005
sentinel current-epoch 9

从机sentinel.conf配置文件:

port 26379
# 守护进程模式
daemonize yes
# # 指明日志文件名
logfile "./sentinel.log"
#
dir "/opt/redis/redis-property/bin"
sentinel myid 8894c1030073e2062ea8369261528e1338919005
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.1.21 6666 1
sentinel down-after-milliseconds mymaster 5000
# Generated by CONFIG REWRITE
protected-mode no
sentinel failover-timeout mymaster 18000
sentinel auth-pass mymaster property
sentinel config-epoch mymaster 8
sentinel leader-epoch mymaster 8
sentinel known-replica mymaster 192.168.1.22 6666
sentinel known-sentinel mymaster 192.168.1.22 26379 40c7dd9ddad12a4c4dcf652dcb7b45a8dc5d8b0d
sentinel current-epoch 9

启动命令如下,我都配置到了/etc/rc.d/rc.local中,方便开机自动启动:

/opt/redis/redis-property/bin/redis-server /opt/redis/redis-property/bin/redis.conf
/opt/redis/redis-property/bin/redis-sentinel /opt/redis/redis-property/bin/sentinel.conf

这样redis和哨兵分别启动,在spring boot中配置Shrio连接到集群这样配置原来的RedisManager修改为RedisSentineManager

shiro配置如下


package com.huohua.common.config;

import com.huohua.modules.sys.shiro.UserRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.crazycake.shiro.RedisSentinelManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean
    public DefaultWebSessionManager sessionManager(@Value("${globalSessionTimeout:3600}") long globalSessionTimeout){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setSessionValidationInterval(globalSessionTimeout * 1000);
        sessionManager.setGlobalSessionTimeout(globalSessionTimeout * 1000);
        sessionManager.setSessionDAO(redisSessionDAO(new Long(globalSessionTimeout).intValue()));
        return sessionManager;
    }
    @ConfigurationProperties("spring.redis.sentinel")
    @Bean
    public RedisSentinelManager redisSentinelManager() {
        return new RedisSentinelManager();
    }
    @Bean
    public RedisSessionDAO redisSessionDAO(@Value("${globalSessionTimeout:3600}") int globalSessionTimeout) {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setExpire(globalSessionTimeout);
        redisSessionDAO.setRedisManager(redisSentinelManager());
        return redisSessionDAO;
    }

    @Bean("securityManager")
    public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setRememberMeManager(null);

        return securityManager;
    }


    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login.html");
        shiroFilter.setUnauthorizedUrl("/");

        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/swagger/**", "anon");
        filterMap.put("/v2/api-docs", "anon");
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/webjars/**", "anon");
        filterMap.put("/swagger-resources/**", "anon");

        filterMap.put("/statics/**", "anon");
        filterMap.put("/login.html", "anon");
        filterMap.put("/sys/login", "anon");
        filterMap.put("/favicon.ico", "anon");
        filterMap.put("/captcha.jpg", "anon");
        filterMap.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

主要配置还是吧shiro的Session交给redis管理,只不过这篇文章相对于上篇,单机redis变成了哨兵集群

注意这里

我在application.yml这样配置:

这块有点纠结,host和nodes都是需要的,因为spring boot初始化redisTemplate需要用到nodes这个字段,初始化RedisSentineManager需要用到host这个字段,先这样实现吧,有更好办法的大佬欢迎赐教

这样配置完成后,启动可以吧spring boot项目打包部署多份,并且可以测试关掉主服务器就可以切换到从服务器了。

但是做到这里还不算完善,主机redis宕机,可以切换到从机,但是管理员无感知,所以我需要研究一下有没有官方方法,比如发邮件提示,实在没有的话我会写一个运维脚本,监测主从切换后自动发送邮件到我的邮箱!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章