一:集成redis(单机版:后期再改集群)
1.配置application.properties
#cache指定缓存类型 spring.cache.type=REDIS #data-redis spring.redis.database=15
spring.redis.host=192.168.**.** spring.redis.password= spring.redis.port=6379 spring.redis.timeout=2000 spring.redis.jedis.pool.max-active=8 spring.redis.jedis.pool.max-idle=8 spring.redis.jedis.pool.max-wait=-1 spring.redis.jedis.pool.min-idle=0 #spring.redis.sentinel.master=mymaster #spring.redis.sentinel.nodes=192.168.210.**\:26379 redis.proxyIpDBNum=15
#以下是我设置的session和授权等信息的过期时间
#session share unit hours(设置成分钟方便测试)
session.timeout=3
#cacheTimeOut unit hours
cache.timeout=12
2.Application开启缓存
@SpringBootApplication @EnableCaching //开启缓存 public class OneserviceManagerApplication { public static void main(String[] args) { SpringApplication.run(OneserviceManagerApplication.class, args); } }
3.编写RedisConfig.java配置类,主要作用是对象序列化
package com.ch.oneservice.manager.config.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig extends CachingConfigurerSupport { @Autowired private RedisConnectionFactory redisConnectionFactory; /** * 获取RedisTemplate对象,处理Redis数据,并且进行最佳序列化 * @return */ @Bean(name="redisTemplate") public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> template = new RedisTemplate<>(); //手动序列化 JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); template.setValueSerializer(jdkSerializationRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setHashValueSerializer(jdkSerializationRedisSerializer); //连接Redis //jedisConnectionFactory.setDatabase(6); template.setConnectionFactory(redisConnectionFactory); template.afterPropertiesSet(); return template; } }
二:redis做shiro的session共享
1.RedisSessionDao的自定义实现(session的缓存处理)

package com.ch.evaluation.auth.shiro.cas; import com.ch.evaluation.common.util.PropertityUtil; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @description:SessionDao自定义实现 * @author: xia hua * @date: 2018年10月19日 * @modify by wangwei at 2018-10-19 * 将redis中存储的session时间单位改成毫秒 */ @SuppressWarnings("all") public class RedisSessionDao extends AbstractSessionDAO { private final String PREFIX="shiro_redis_session:"; private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class); private RedisTemplate redisTpl; @Override public void update(Session session) throws UnknownSessionException { if (session==null || session.getId() == null){ logger.error("redis update session error:session or session id is null"); return; } try { redisTpl.opsForValue().set(PREFIX+session.getId().toString(), session, PropertityUtil.getPropertity("session.timeout"), TimeUnit.HOURS); } catch (Exception e) { // TODO: handle exception logger.error(e.getMessage(), e); throw new UnknownSessionException(e); } } @Override public void delete(Session session) { // TODO Auto-generated method stub if (session==null || session.getId() == null){ logger.error("redis delete session error:session or session id is null"); return; } try { redisTpl.delete(PREFIX+session.getId().toString()); } catch (Exception e) { // TODO: handle exception logger.error(e.getMessage(), e); } } @Override public Collection<Session> getActiveSessions() { // TODO Auto-generated method stub return (Collection<Session>) redisTpl.execute(new RedisCallback<Collection<Session>>() { @Override public Collection<Session> doInRedis(RedisConnection connection) throws DataAccessException { // TODO Auto-generated method stub Set<Session> sessions = new HashSet<Session>(); Set keys = redisTpl.keys(PREFIX+"*"); for(Object key : keys){ Session session=(Session) redisTpl.opsForValue().get(key); sessions.add(session); } // // for (Session session : sessions) { // sessions.add(session); // } return sessions; } }); } @Override protected Serializable doCreate(Session session) { // TODO Auto-generated method stub if (session==null){ logger.error("redis create session error:session is null"); return null; } // TODO Auto-generated method stub Serializable sessionId = generateSessionId(session); assignSessionId(session, sessionId); redisTpl.opsForValue().set(PREFIX+sessionId.toString(), session, session.getTimeout()/1000, TimeUnit.SECONDS); return sessionId; } @Override protected Session doReadSession(Serializable sessionId) { if (sessionId == null){ logger.error("redis read session error:sessionId is null"); return null; } // TODO Auto-generated method stub Session session = null; try { session = (Session) redisTpl.opsForValue().get(PREFIX+sessionId); } catch (Exception e) { // TODO: handle exception logger.error(e.getMessage(), e); } return session; } public void setRedisTpl(RedisTemplate redisTpl) { this.redisTpl = redisTpl; } }
1.1这里引用了一个工具类读取配置文件

package com.ch.evaluation.common.util; import org.apache.log4j.chainsaw.Main; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertityUtil { public static int getPropertity(String key){ Properties properties = new Properties(); ClassLoader load = Main.class.getClassLoader(); InputStream is = load.getResourceAsStream("application.properties"); try { properties.load(is); String value = properties.getProperty(key); int val = 0; if(value!=null){ val = Integer.parseInt(value); } return val; } catch (IOException e) { e.printStackTrace(); } return 0; } }
2.RedisCache的自定义实现(对权限和认证信息的缓存处理)

package com.ch.dataauthority.common.redis; import com.ch.dataauthority.common.util.PropertityUtil; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.springframework.data.redis.core.RedisTemplate; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; /** * Redis缓存类 * Created by 005803 on 2017/10/12. */ public class RedisCache<K, V> implements Cache<K, V> { private RedisTemplate redisTemplate; private static final String PREFIX = "shiro_redis_cache:"; public RedisCache(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Override public V get(K key) throws CacheException { return (V) redisTemplate.opsForValue().get(PREFIX + key); } @Override public V put(K key, V value) throws CacheException { redisTemplate.opsForValue().set(PREFIX + key, value, PropertityUtil.getPropertity("cache.timeout"), TimeUnit.HOURS); return value; } @Override public V remove(K key) throws CacheException { Object value = redisTemplate.opsForValue().get(PREFIX + key); redisTemplate.delete(PREFIX + key); return (V) value; } @Override public void clear() throws CacheException { redisTemplate.delete(keys()); } @Override public int size() { return keys().size(); } @Override public Set<K> keys() { Set keys = redisTemplate.keys(PREFIX + "*"); return keys != null ? keys : Collections.<K>emptySet(); } @Override public Collection<V> values() { Set<K> keys = keys(); Collection<V> c = new HashSet<>(); for (K key : keys) { c.add((V) redisTemplate.opsForValue().get(key)); } return c; } }
3.Redis缓存管理器的配置RedisCacheManager.java
package com.ch.oneservice.manager.common.redis; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.springframework.data.redis.core.RedisTemplate; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Redis缓存管理器 * Created by wangwei on 2018/10/19. */ public class RedisCacheManager implements CacheManager { private RedisTemplate redisTemplate; private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<>(); public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { Cache cache = caches.get(name); if (cache == null) { cache = new RedisCache(redisTemplate); caches.put(name, cache); } return cache; } }
4.在你自定义的shiro的realm中重写key的策略
public class ExtendCasRealm extends CasRealm { private static Logger LOGGER = LoggerFactory.getLogger(ExtendCasRealm.class); @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { ...................... } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { ........................ } .................... .................. @Override protected Object getAuthorizationCacheKey(PrincipalCollection principals) { return principals.getPrimaryPrincipal() + ":authorization"; } @Override protected Object getAuthenticationCacheKey(PrincipalCollection principals) { return principals.getPrimaryPrincipal() + ":authentication"; } @Override protected Object getAuthenticationCacheKey(AuthenticationToken token) { return token.getPrincipal() + ":authentication"; } }
5.基本上配置以上信息就可以用了,值得注意的是要在ShiroCasConfig中配置这些Bean的关联关系,记得session的获取方式有两种,一种是servlet的session一种是shiro默认的session管理器DefaultWebSessionManager ,我们要记得注入DefaultWebSessionManager 管理器,不然程序执行过程中可能会默认执行isServletContainerSessions方法导致抛出一个session类型的异常
贴一下ShiroCasConfig配置,具体自己看吧

package com.ch.oneservice.manager.config.shirocas; import com.ch.oneservice.manager.auth.shiro.cas.ExtendCasRealm; import com.ch.oneservice.manager.auth.shiro.cas.RedisSessionDao; import com.ch.oneservice.manager.auth.shiro.filter.ExtendAuthorizationFilter; import com.ch.oneservice.manager.auth.shiro.filter.ExtendCasFilter; import com.ch.oneservice.manager.auth.shiro.filter.ExtendLogoutFilter; import com.ch.oneservice.manager.auth.shiro.filter.MyShiroSSOFilter; import com.ch.oneservice.manager.auth.shiro.service.IAuthorizationService; import com.ch.oneservice.manager.common.constants.WebConstants; import com.ch.oneservice.manager.common.redis.RedisCacheManager; import org.apache.shiro.cas.CasSubjectFactory; 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.jasig.cas.client.session.SingleSignOutFilter; import org.jasig.cas.client.session.SingleSignOutHttpSessionListener; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.filter.DelegatingFilterProxy; import javax.servlet.Filter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; /** * Created by sunyong - 20170906 */ @Configuration public class ShiroCasConfig { @Value("${cas.server.url}") private String casServerUrl; @Value("${shiro.cas-server}") private String casServerUrlPrefix; @Value("${shiro.server}") private String shiroServerUrlPrefix; @Value("${session.timeout}") private int sessionTimeout; private static final String CAS_FILTER_NAME = "casFilter"; private static final String SHIRO_FILTER_NAME = "shiroFilter"; private static final String AUTH_FILTER_NAME = "authFilter"; private static final String LOGOUT_FILTER_NAME = "logoutFilter"; /** * 该类可以保证实现了org.apache.shiro.util.Initializable接口的shiro对象的init或者是destory方法被自动调用, * 而不用手动指定init-method或者是destory-method方法 * 注意:如果使用了该类,则不需要手动指定初始化方法和销毁方法,否则会出错 * @return */ // @Bean(name = "lifecycleBeanPostProcessor") // public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { // return new LifecycleBeanPostProcessor(); // } /** * 注册DelegatingFilterProxy(Shiro) */ @Bean public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean() { FilterRegistrationBean<DelegatingFilterProxy> filterRegistration = new FilterRegistrationBean<DelegatingFilterProxy>(); filterRegistration.setFilter(new DelegatingFilterProxy(SHIRO_FILTER_NAME)); filterRegistration.addInitParameter("targetFilterLifecycle", "true"); filterRegistration.setEnabled(true); filterRegistration.addUrlPatterns("/*"); return filterRegistration; } /** * 下面两个配置主要用来开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; * * @return */ // @Bean // @DependsOn("lifecycleBeanPostProcessor") // public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { // DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); // daap.setProxyTargetClass(true); // return daap; // } /** * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor( DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * 会话管理器 * @auth 011336 * @DATE 2018/10/15 * @return */ @Bean(name = "sessionManager") public DefaultWebSessionManager getDefaultWebSessionManager(RedisSessionDao sessionDAO, RedisCacheManager redisCacheManager) { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(sessionTimeout); sessionManager.setDeleteInvalidSessions(true); //sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionDAO(sessionDAO); sessionManager.setCacheManager(redisCacheManager); // TODO simpleCookie return sessionManager; } /** * 实例化SecurityManager,该类是shiro的核心类 * * @return */ @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(ExtendCasRealm extendCasRealm, DefaultWebSessionManager sessionManager, RedisCacheManager redisCacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(extendCasRealm); securityManager.setCacheManager(redisCacheManager); securityManager.setSessionManager(sessionManager); securityManager.setSubjectFactory(new CasSubjectFactory()); return securityManager; } /** * RedisSessionDao * @auth 011336 * @DATE 2018/10/15 * @return */ @Bean public RedisSessionDao getRedisSessionDao(RedisTemplate redisTemplate) { RedisSessionDao sessionDAO = new RedisSessionDao(); sessionDAO.setRedisTpl(redisTemplate); return sessionDAO; } /** * redisCacheManager * @auth 011336 * @DATE 2018/10/15 * @return */ @Bean public RedisCacheManager getRedisCacheManager(RedisTemplate redisTemplate) { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisTemplate(redisTemplate); return redisCacheManager; } /* *//** * MyShiroSSOFilter * @auth 011336 * @DATE 2018/10/15 * @return */ @Bean(name = "shiroSSOFilter") public MyShiroSSOFilter getMyShiroSSOFilter(DefaultWebSessionManager sessionManager, DefaultWebSecurityManager securityManager) { MyShiroSSOFilter myShiroSSOFilter = new MyShiroSSOFilter(); myShiroSSOFilter.setSessionManager(sessionManager); myShiroSSOFilter.setSecurityManager(securityManager); return myShiroSSOFilter; } /** * 配置缓存 * * @return */ /* @Bean public MemoryConstrainedCacheManager getMemoryCacheManager() { MemoryConstrainedCacheManager memoryCacheManager = new MemoryConstrainedCacheManager(); return memoryCacheManager; }*/ /** * 配置Realm,由于我们使用的是CasRealm,所以已经集成了单点登录的功能 * * @param authorizationService * @return */ @Bean public ExtendCasRealm getExtendCasRealm(IAuthorizationService authorizationService, RedisCacheManager redisCacheManager ) { ExtendCasRealm extendCasRealm = new ExtendCasRealm(); extendCasRealm.setAuthorizationService(authorizationService); // cas登录服务器地址前缀 extendCasRealm.setCasServerUrlPrefix(casServerUrlPrefix); // 客户端回调地址,登录成功后的跳转地址(自己的服务地址) extendCasRealm.setCasService(shiroServerUrlPrefix + WebConstants.CAS_FILTER_URI); extendCasRealm.setCachingEnabled(true); extendCasRealm.setAuthenticationCachingEnabled(true); extendCasRealm.setAuthenticationCacheName("authenticationCache"); extendCasRealm.setAuthorizationCachingEnabled(true); extendCasRealm.setAuthorizationCacheName("authorizationCache"); extendCasRealm.setCacheManager(redisCacheManager); return extendCasRealm; } /** * 注册单点登出的listener * * @return */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) // 优先级需要高于Cas的Filter public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() { ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> bean = new ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>(); bean.setListener(new SingleSignOutHttpSessionListener()); bean.setEnabled(true); return bean; } /** * 注册单点登出filter * * @return */ @Bean public FilterRegistrationBean<SingleSignOutFilter> singleSignOutFilter() { FilterRegistrationBean<SingleSignOutFilter> bean = new FilterRegistrationBean<SingleSignOutFilter>(); bean.setName("singleSignOutFilter"); bean.setFilter(new SingleSignOutFilter()); bean.addUrlPatterns("/*"); bean.setEnabled(true); return bean; } /** * CAS过滤器 * * @return */ //@Bean(name = CAS_FILTER_NAME) public ExtendCasFilter getExtendCasFilter() { ExtendCasFilter casFilter = new ExtendCasFilter(); casFilter.setName(CAS_FILTER_NAME); casFilter.setEnabled(true); // String loginUrl = casServerUrlPrefix + "/login?service=" + shiroServerUrlPrefix + CAS_FILTER_URI; casFilter.setFailureUrl("/error/casfailure"); casFilter.setExtendFailureUrl("/error/casfailure"); // 由于原failuserUrl为私有字段,在扩展类中不能获取到值 return casFilter; } /** * extAuth Filter */ //@Bean(name = AUTH_FILTER_NAME) public ExtendAuthorizationFilter getExtendAuthorizationFilter( IAuthorizationService authorizationService) { ExtendAuthorizationFilter extAuthFilter = new ExtendAuthorizationFilter(); extAuthFilter.setName(AUTH_FILTER_NAME); extAuthFilter.setEnabled(true); extAuthFilter.setAuthorizationService(authorizationService); return extAuthFilter; } /** * extLogout Filter */ //@Bean(name = LOGOUT_FILTER_NAME) public ExtendLogoutFilter getExtendLogoutFilter(IAuthorizationService authorizationService) { ExtendLogoutFilter extLogoutFilter = new ExtendLogoutFilter(); extLogoutFilter.setName(LOGOUT_FILTER_NAME); extLogoutFilter.setEnabled(true); extLogoutFilter.setAuthorizationService(authorizationService); extLogoutFilter.setRedirectUrl(casServerUrl + "/logout?service=" + shiroServerUrlPrefix); return extLogoutFilter; } /** * 使用工厂模式,创建并初始化ShiroFilter * * @param securityManager * @param authorizationService * @return */ @Bean(name = SHIRO_FILTER_NAME) public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, IAuthorizationService authorizationService) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); String loginUrl = casServerUrl + "/login?service=" + shiroServerUrlPrefix + WebConstants.CAS_FILTER_URI; shiroFilterFactoryBean.setLoginUrl(loginUrl); shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/error/unauthorized"); Map<String, Filter> filters = new HashMap<>(); filters.put(CAS_FILTER_NAME, getExtendCasFilter()); filters.put(LOGOUT_FILTER_NAME, getExtendLogoutFilter(authorizationService)); filters.put(AUTH_FILTER_NAME, getExtendAuthorizationFilter(authorizationService)); shiroFilterFactoryBean.setFilters(filters); loadShiroFilterChain(shiroFilterFactoryBean); return shiroFilterFactoryBean; } private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) { Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put(WebConstants.CAS_FILTER_URI, CAS_FILTER_NAME); filterChainDefinitionMap.put("/logout", LOGOUT_FILTER_NAME); filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/front/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/plugin/**", "anon"); filterChainDefinitionMap.put("/home/**", "anon"); filterChainDefinitionMap.put("/super", "anon"); filterChainDefinitionMap.put("/super/login", "anon"); filterChainDefinitionMap.put("/error/**", "anon"); filterChainDefinitionMap.put("/**", AUTH_FILTER_NAME); //filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); } }
以上代码我进行了优化,详情可点击这里
三:nginx实现负载均衡 【常用命令点这里】
首先我们把项目部署在两个节点上
192.168.43.96
192.168.43.98
记得要开启8080端口,否则无法访问,我已经在部署时去除了项目名称(具体方法不贴了,可以自行百度,也可以查看我的其他博客)
(后来同事测试功能的时候,发现有一个节点挂掉了但nginx任然在往这个节点上负载请求,是不是很坑?其实是因为他部属的时候没有去除项目名称,而我在nginx中只配置了端口号,所以当请求负载到我上面部属的两个节点的时候就能访问数据,负载到他部属的节点的时候就请求不到数据。而且这个时候nginx认为他部属的这个节点是没有挂掉的)
然后要注意的是项目要把单点登录的回调地址改成ngnix的地址,如下配置:
注意:采用nginx做反向代理之后,浏览器、单点登录服务器就都是和nginx打交道了,我们实际部署项目的96、98两个节点对外界是透明的。
同时注意区分80和8080不是同一个端口,所以我们原先配置的回调地址要改为nginx的80端口;
单节点是的配置:
#application.url=http://192.168.43.96:8080 //原先配置
#application.url=http://192.168.43.96:8080 //原先配置
使用nginx后,每个节点上的回调地址都要改成nginx的地址加端口
application.url=http://192.168.43.97:80 //改成ngnix配置因为我的ngnix默认的是80端口 97为ngnix的地址
注意:最好不要在nginx服务器上部署tomcat服务,因为你的请求可能会直接访问到tomcat服务器而不经过ngnix,可能是我没有配置好,我在把他们部署在一台服务器上的时候遇到了每次请求sessionID都会变化的情况
然后就一直报错。具体原因还没明白,有大神知道的话,可以在文档下方留言
2.ngnix的安装就不贴了,可自行百度,我们主要讲一下最简单的配置让你的项目跑起来
可通过find / -name ngnix 命令查找ngnix的位置
然后切换到conf目录编辑ngnix.conf文件,详细配置说明可百度
cd nginx/conf/ngnix.conf
直接修改如下配置即可
upstream tomcats { server 192.168.43.96:8080;//项目位置 server 192.168.43.97:8080;//项目位置 } server { listen 80;//默认80端口 server_name nginx-ww;//随意写 #charset koi8-r;
............
location / {
proxy_pass http://tomcats;//指定路由为我们配置的项目位置
}
3.启动nginx[重启等命令点这里]
cd usr/local/nginx/sbin
./nginx
可通过以下命令查看启动状态ps -ef | grep nginx 说明启动成功
[root@yjy-pt02 nginx]# ps -ef | grep nginx root 4669 1 0 01:12 ? 00:00:00 nginx: master process ./nginx nobody 4670 4669 0 01:12 ? 00:00:00 nginx: worker process root 5086 3145 0 02:41 pts/0 00:00:00 grep nginx [root@yjy-pt02 nginx]#
最后查看成果
1.浏览器输入nginx地址 http://192.168.43.98
2.回车就会跳转到单点登录地址然后输入用户名密码校验通过就可以
3.由于nginx默认采用weight轮询的方式负载服务
所以我们在点击页面是可以看到两个服务器的日志输出情况
tail -f catalina.out
可以发现日志轮流输出,说明负载实现,
我们也可以通过redis客户端查看权限缓存的信息
浏览器的cookie
redis信息