前言:session原理
反向代理-负载均衡
一、什么是Nginx
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行。中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
特点
- 占有内存少,并发能力强
- 模块化组件,可扩展性强
- 跨平台,linux平台下性能更优异
适用场景
- 静态HTTP服务器
- 目录保护及访问限制
- 正/反向代理服务器
- 防盗链
- 负载均衡
- 下载限速
- 虚拟主机
- web缓存
- 电子邮件代理
- 请求转发
对于web集群,我们常采用ngnix,简单,耗资源少、负载能力强,轻松应对十万并发
淘宝的反向代理服务器就采用了Tengine,是基于Ngnix进行修改定制的
二、Nginx的负载均衡策略
- 轮询
- weight权重
- ip hash
- 支持扩展自定义策略
1、轮询策略
配置负载均衡,采用轮询策略,这样我们访问http://localhost 就可以负载均衡,采用轮询方式分别访问上面这两个8081、8082的Tomcat服务器了。
http{
upstream webProject{
# ip_hash;
server localhost:8081;
server localhost:8082;
#server localhost:8083 weight=3;
}
server{
listen 80;
server_name localhost;
location / {
proxy_pass http://webProject;
}
}
}
2、weight权重
通过配置weight来配置权重
http{
upstream webProject{
# ip_hash;
server localhost:8081 weight=1;
server localhost:8082 weight=3;
#server localhost:8083 weight=3;
}
...
}
3、ip_hash配置
什么是ip_hash
后台有5台服务器: 5
假设一台的ip为 10.1.12.13 >经过ip_hash算法后> 111
然后对 111 % 5 = 1 (0~4之间)就放在第二台服务器上
http{
upstream webProject{
ip_hash;
server localhost:8081;
server localhost:8082;
#server localhost:8083 weight=3;
}
...
}
三、正向带来和反向代理
1、正向代理
正向代理就是代理个人的PC端来访问互联网
2、反向代理
反向代理就是代理我们的服务器
3、总结
正向代理和反向代理的区别?
正向代理是代理客户端(个人PC)访问外网
例如 公司网络不能访问淘宝、拼夕夕等,需要采用VPN,这就是正向代理
反向代理是代理服务器对外提供服务
例如 使用Nginx
Session丢失问题
一、什么是Session丢失
在使用负载均衡的情况下,请求被分配到多台服务器上,当被分配到无Session的服务器上时造成状态不一样,导致Session丢失。
二、解决Session一致性问题
- 基于ip_hash的负载均衡
- 服务器Session复制
- Session统一缓存
1、基于ip_hash的负载均衡
优缺点
优点
- 配置简单,对应用无侵入性,不需要修改代码
- 只要hash属性是均匀的,多台web-server的负载是均衡的
- 便于服务器水平扩展
- 安全性较高
缺点
- 服务器重启会造成部分session丢失
- 水平扩展过程中也会造成部分session丢失
- 存在单点负载高的风险
2、服务器Session复制
(1)tomcat中的Session复制
实现方法
修改tomcat的配置文件
1. 修改server.xml中的Cluster节点
<Cluster classllame="org.apache.catalina.ha.tcp.Simple TcpCluster"/>
修改项目的web.xml文件
2. 修改应用web.xml,增加</distributable>
<distributable/>
优缺点
优点:
- 对应用无侵入性,不需要修改代码
- 能适应各种负载均衡策略
- 服务器重启或宕机不会造成session丢失
- 安全性较高
缺点
- Session同步会有一定的延时占用内网带宽资源
- 受制于内存资源,水平扩展能力差
- 服务器数量较多
- 序列化反序列化消耗CPU性能
2、Session复制原理解剖
IP网络数据传输三种方式:单播,组播和广播; 224.0.1.0~238.255.255.255为用户可用的组播地址
3、Session的统一缓存
(1)换成统一缓存需要做的改变
我们的业务代码中要用session都是通过request去获取的,业务代码只管用session对象,它们本就不管它的存取。 那我们想办法把tomcat生成的request替换为我们的request,再提供给业务代码使用是否就OK? 在我们的request中替换session的产生、存、取、失效操作。 如何替换tomcat的request为我们的request?
实现方法
具体配置,配置SpringSession完成Session统一缓存,修改应用的配置文件
1. 增加redis client和spring session的依赖中
<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>
2. 修改web.xml,增加filter:springSessionRFiter;
<--spring-session-实现了自定义的HttpServletRequest和Session操作>
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyk/filter</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3. 修改spring配置文件,在容器中注入spring session和redis相关的bean;
<bean id-"redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveInterval InSeconds"value="600"/>
</bean>
<bean id-"jedisPoolConfig"class-"redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal"value="1e0"/>
<property name="maxIdle"value="10"/>
</bean>
<bean id="jedisconnecttonFactory class="org.springframework.data.redis.connection.jedis.JedisConnecttonfactory"
destroy-method="destroy">
<property name="hostName"value-"Localhost"/>
<property name="port"value="6379"/>
<property name="timeout"value-"3000"/>
<property name="usePool"value="true"/>
<property name="poolConfig"ref="jedisPoolConfig"/>
</bean>
优缺点
优点
- 能适应各种负载均衡策略
- 服务器重启或宕机不会造成session丢失
- 安全性较高
- 扩展能力强
- 适合集群数量大时使用
缺点
- 对应用有侵入,需要增加相关配置
- 增加一次网络开销(用缓存),用户体验降低
- 序列化(redis存储序列化)反序列化消耗CPU性能
注意的坑
- 放置在session中的对象必须是可序列化的
- SpringSessionRepositoryFilter的顺序要在其他获取session的filter的之前;
- Session的失效时间由redis节点失效时间决定,原有的配置不起作用;
- 登出的时候,一定确保显式的调用了session.invalidate();
4、tomcat-redis-session-manager另一种方式(比较老)
此方案最简单之处就在于我们无需修改项目,只需要修改Tomcat的 context.xml配置文件即可,步骤:
-
tomcat-redis-session-manager-1.1.jar,jedis-2.1.0.jar,commons-pool-1.6.jar这三个包需放入tomcat的安装目录下的lib文件夹下
-
修改context.xml
<Valve classllame="com.radtadesign.cotal tna.sesston.RedisSesstonHandlerValve"/>
<Manager classlMame="com.rodtadestgn.catal ina.sesston.RedisSesstonManager"
host="127.0.0.1"|
port="9313"
database-"e"
maxInactiveInterval-"60"/>
三、经验总结