springboot+shiro-redis 使用Redis sentinel(哨兵)主从实现
最近公司项目遇到一台服务器崩溃导致项目无法运行,因项目采用单点的 Redis做session共享,权限处理,所以想到采用Redis主从方式这样降低耦合性,为方便以后查阅特记录此处。
服务器系统为centos 7 redis 4.0.6
两台主从Redis服务器: 192.168.0.35 6379 主
192.168.0.34 6379 从
一、Redis安装
cd /opt
wget http://download.redis.io/releases/redis-4.0.6.tar.gz 若提示为找到该命令,那么需要安装:yum install wget
tar xzf redis-4.0.6.tar.gz
cd redis-4.0.6
make
src/redis-server
客户端访问:
src/redis-cli
Redis设置开机自启动:
1.修改配置文件参数daemonize为yes
.vi /opt/redis-4.0.6/redis.conf
复制redis配置文件(启动脚本需要用到配置文件内容,所以要复制)
#1.在/etc下新建redis文件夹
$ mkdir /etc/redis
#2.把安装redis目录里面的redis.conf文件复制/etc/redis/6379.conf面,6379.conf是取的文件名称,启动脚本里面的变量会读取这个名称,所以要是redis的端口号改了,这里也要修改
$ cp /opt/redis-4.0.6/redis.conf /etc/redis/6379.conf
find / -name redis_init_scriptredis启动脚本一般在redis根目录的utils,如果不知道路径,可以先查看路径
find / -name redis_init_script
复制启动脚本到/etc/init.d/redis文件中cp /opt/redis-3.2.4//utils/redis_init_script /etc/init.d/redis修改启动脚本参数
vi /etc/init.d/redis
#在/etc/init.d/redis文件的头部添加下面两行注释代码,也就是在文件中#!/bin/sh的下方添加
#chkconfig: 2345 10 90
#description: Start and Stop redis
如图
同时还要修改参数,指定redis的安装路径
由于项目需求,redis需要外界访问所以采用密码方式:
masterauth test(注意若设置密码主从密码最好一直,方便后面sentinel模式访问)
打开redis命令:service redis start
关闭redis命令:service redis stop
设为开机启动:chkconfig redis on
至此35上的Redis安装成功,34服务器上也按类似方法安装,由于34是从所以在6379.conf中多一些配置
slaveof 192.168.0.35 6379
如图
登陆34查看信息
至此Redis主从全部安装完成,下面配置哨兵
二、sentinel 配置
#将sentinel配置文件拷贝到/etc/redis目录后编辑
1.自动启动
2.启动
redis-sentinel sentinel.conf
当退出是 sentinel也退出 了,这时我们就采用redis-sentinel /etc/redis/sentinel.conf
查看进程sentinel进程一直都在。在35上也同样配置到此Redis所有操作结束。
三、shior-Redis连接Redis
maven配置
此处切记shiro-redis架包使用比较新的,当时使用2.4.2.1-RELEASE时无法使用哨兵主从。
application配置
ShiroConfig 代码
@Configuration
public class ShiroConfig {
@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Value("${spring.redis.password}")private String password;@Value("${spring.redis.sentinel.nodes}")private String redisNodes;@Value("${spring.redis.sentinel.master}")private String master;@Value("${shiro.redisCacheExpire:1800}")private int redisCacheExpire;@Value("${shiro.filterChainDefinitions}")private String filterChainDefinitions;@Value("${shiro.sessionValidationInterval:300000}")private long sessionValidationInterval;@Autowiredprivate AuthorityService authorityService;/** * 配置shiro redisManager ----单点时使用 * 使用的是shiro-redis开源插件 * * @return */
// public RedisManager redisManager() {
// RedisManager redisManager = new RedisManager();
// redisManager.setHost(host);
// redisManager.setPort(port);
// redisManager.setPassword(password);
// redisManager.setExpire(redisCacheExpire);
//// redisManager.setTimeout(2000);
// return redisManager;
// }
/** * 配置shiro redisSentinelManager 哨兵模式 * 使用的是shiro-redis开源插件 * @return */public RedisSentinelManager redisSentinelManager(){ RedisSentinelManager redisSentinelManager = new RedisSentinelManager(); redisSentinelManager.setMasterName(master); redisSentinelManager.setHost(redisNodes); redisSentinelManager.setPassword(password); return redisSentinelManager;}/** * cacheManager 缓存 redis实现 * 使用的是shiro-redis开源插件 * * @return */public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager();
// redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setRedisManager(redisSentinelManager());
return redisCacheManager;
}
/** * RedisSessionDAO shiro sessionDao层的实现 通过redis * 使用的是shiro-redis开源插件 */public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisSentinelManager()); return redisSessionDAO;}/** * shiro session的管理 */public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionDAO(redisSessionDAO()); Cookie cookie = sessionManager.getSessionIdCookie(); cookie.setName("emp_sid"); sessionManager.setSessionIdCookie(cookie); //shiro session过期监听器 sessionManager.setSessionListeners(Arrays.asList(new ShiroSessionListener())); sessionManager.setSessionValidationInterval(sessionValidationInterval); return sessionManager;}/** * 凭证匹配器 * * @return */public CredentialsMatcher credentialsMatcher() { RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(cacheManager()); credentialsMatcher.setHashAlgorithmName("md5");//加密算法名称 credentialsMatcher.setHashIterations(2); credentialsMatcher.setStoredCredentialsHexEncoded(true); return credentialsMatcher;}/** * Realm实现 * * @return */@Beanpublic AuthorizingRealm userRealm() { EmployeeRealm employeeRealm = new EmployeeRealm(); employeeRealm.setCredentialsMatcher(credentialsMatcher()); //关闭登陆用户信息缓存 employeeRealm.setAuthenticationCachingEnabled(false); employeeRealm.setAuthorizationCachingEnabled(true); return employeeRealm;}/** * 安全管理器 * * @return */@Beanpublic SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm()); securityManager.setSessionManager(sessionManager()); securityManager.setCacheManager(cacheManager()); ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer(); authorizer.setRealms(securityManager.getRealms()); authorizer.setPermissionResolver(new EmployeePermissionResolver()); authorizer.setRolePermissionResolver(rolePermissionResolver()); securityManager.setAuthorizer(authorizer); securityManager.setRememberMeManager(rememberMeManager()); return securityManager;}@Beanpublic RolePermissionResolver rolePermissionResolver() { return new MyRolePermissionResolver();}@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, Filter> filters = shiroFilterFactoryBean.getFilters(); StaticUrlFilter staticUrlFilter = new StaticUrlFilter(); filters.put("staticUrl", staticUrlFilter); TokenFilter tokenFilter=new TokenFilter(); filters.put("token",tokenFilter); AuthorityFilter authorityFilter = new AuthorityFilter(); authorityFilter.setActionService(authorityService); filters.put("auth", authorityFilter); VersionFilter versionFilter = new VersionFilter(); filters.put("version", versionFilter); shiroFilterFactoryBean.setFilters(filters); //拦截器. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 配置不会被拦截的链接 顺序判断 //拦截器url配置格式为:/**=user,等号前面为路径,后面为名称,多个拦截器用','分割,多个配置之间用';'分割 if (!StringUtils.isEmpty(filterChainDefinitions)) { String[] array = StringUtils.delimitedListToStringArray(filterChainDefinitions, ";"); for (String str : array) { if(StringUtils.isEmpty(str)){ continue; } String[] urlArray = str.split("="); filterChainDefinitionMap.put(urlArray[0].trim(), urlArray[1].trim());
// String[] filterArray = urlArray[1].split(",");
// for (String s : filterArray) {
// filterChainDefinitionMap.put(urlArray[0].trim(), s.trim());
// }
}
}
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
// shiroFilterFactoryBean.setFilterChainDefinitions(filterChainDefinitions);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/");
shiroFilterFactoryBean.setUnauthorizedUrl("/401");
return shiroFilterFactoryBean;}public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager rememberMeManager = new CookieRememberMeManager(); rememberMeManager.getCookie().setMaxAge(2592000);//有效期30天 rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag==")); return rememberMeManager;}
}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。