session 粘滞性
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
但是有缺点,这存在单点风险,倘若我已经在192.168.0.14:88端口登录后,过段时间发现14服务器挂了(session时间未过期),那么这时候会访问到15服务器,那这时候需要重新登录,因为在拿14服务器上的JsessionId去15服务器请求发现不存在。
在nginx配置文件中,增加配置, 对IP进行HASH后,散列到服务器。
这个实现最简单。但对于前端部署了SBC的,或者很多请求都是从某一个外网网关过来的,就没用了。而且对于app会切换wifi变ip的,也不好用。
session 复制
可以通过tomcat的server.xml文件进行配置,这样每个tomcat都会同步对应的session,那么此时即使某个tomcat被宕机了,也不影响服务。
具体的tomcat可以参见如下 ,tomcat 官网对应的tomcat集群配置
在 tomcat的web.xml中配置为集群模式,
在tomcat的server.xml中配置集群信息。
配置后,就可以自动复制session了。
缺点是每台服务器上都要保存全量的session信息,在服务器多的情况下,基本不可用。但开发简单,在只有两三台服务器的时候,是可以的。
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
session 共享(springboot)
对应的项目中pom文件添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
在对应的application.properties中配置redis信息
spring.redis.host=localhost
spring.redis.port=6379
添加开启spring session支持的注解@EnableRedisHttpSession
@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
}
添加验证的接口
@Value("${server.port}")
String port;
@GetMapping("/session")
public Object getSession(HttpServletRequest request){
Map<String, Object> map = new HashMap<String, Object>();
map.put("SessionId", request.getSession().getId());
map.put("ServerPort", "服务端口号为 "+port);
return map;
}
访问 http://localhost:8080/session
下面我们换个端口再访问一次看看
这次我把端口换成了8888 访问:http://localhost:8888/session
刷新了redis数据库,缓存的数据也没变
结果中的SessionId是一致的,却是由两个不同项目工程来提供服务。这样子,SpringSession 利用拦截器 Filter 帮我们在每个请求前进行了同步设置,达到了分布式系统中 session 共享。
session 共享(springmvc)
首先在pom.xml文件中添加对应的jar
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
在对应springmvc-context.xml文件中配置
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="600"/>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="100" />
<property name="maxIdle" value="10" />
<property name="testOnBorrow" value="true" />
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<property name="poolConfig" ref="jedisPoolConfig" />
<property name="port" value="6379" />
<property name="hostName" value="192.168.1.11" />
<property name="password" value="xxx" />
<property name="timeout" value="30000" ></property>
</bean >
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
<property name="connectionFactory" ref="connectionFactory" />
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
</bean >
<bean id="redisUtil" class="com.isea533.mybatis.service.RedisUtil" >
<property name="redisTemplate" ref="redisTemplate" />
</bean >
其次在web.xml中配置(非常重要,filter的名字必须是springSessionRepositoryFilter)
<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>
访问项目路径呈现结果
往期文章
Nginx系列教程(1)nginx基本介绍和安装入门
Nginx系列教程(2)nginx搭建静态资源web服务器
Nginx系列教程(3)nginx缓存服务器上的静态文件
Nginx系列教程(4)nginx处理web应用负载均衡问题以保证高并发
Nginx系列教程(5)如何保障nginx的高可用性(keepalived)
Nginx系列教程(6)nginx location 匹配规则详细解说
Nginx系列教程(7)nginx rewrite配置规则详细说明
Nginx系列教程(8)nginx配置安全证书SSL