什么是Nginx
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。
为什么要用Nginx
由C语言编写,对系统资源和CPU资源利用率都很高,支持50000并发连接数,并且安装和配置简便,启动速度极快,支持Linux、Mac OS X、Microsoft Windows等众多主流操作系统。
如何用Nginx
实现负载均衡轮询,这里主要介绍nginx.conf配置文件,以及相关注意事项。
worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; # upstream 配置一组后端服务器, # 请求转发到upstream后,nginx按策略将请求指派出某一服务器 # 即配置用于负载均衡的服务器群信息 upstream backends { #=========均衡策略============= #none 轮询(权重由weight决定) #ip_hash 通过hash算法将用户的请求与第一次请求的服务器进行绑定,后续该用户所有的请求都将被分配到该服务器上。除非该服务器挂掉。 #============== 第三方 均衡策略=========== #fair 根据各个服务器的性能的不同,自动选择使用响应能力强的服务器。 #url_hash 根据url选择服务器。 #===============服务器集============== server 192.168.1.62:8080; server 192.168.1.63; #==========weight权重策略:权重值越高负载越大========== # server 192.168.1.64 weight=5; #===============backup:备份机,只有非备份机都挂掉了才启用=============== server 192.168.1.64 backup; #==============down: 停机标志,不会被访问(对临时维护的服务器设置)============= server 192.168.1.65 down; # max_fails:达到指定次数认为服务器挂掉; # fail_timeout:挂掉之后过多久再去测试是否已恢复 server 192.168.1.66 max_fails=2 fail_timeout=60s; } server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } # 反向代理设置,将所有/proxy_test/路径下请求发给本机上的tomcat location /proxy_test/ { proxy_pass http://localhost:8080; } # 负载均衡设置,将所有jsp请求发送到upstream backends指定的服务器群上 location ~ \.jsp$ { proxy_pass http://backends; # 真实的客户端IP proxy_set_header X-Real-IP $remote_addr; # 请求头中Host信息 proxy_set_header Host $host; # 代理路由信息,此处取IP有安全隐患 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 真实的用户访问协议 proxy_set_header X-Forwarded-Proto $scheme; # 默认值default, # 后端response 302时 tomcat header中location的host是http://192.168.1.62:8080 # 因为tomcat收到的请求是nginx发过去的, nginx发起的请求url host是http://192.168.1.62:8080 # 设置为default后,nginx自动把响应头中location host部分替换成当前用户请求的host部分 # 网上很多教程将此值设置成 off,禁用了替换, # 这样用户浏览器收到302后跳到http://192.168.1.62:8080,直接将后端服务器暴露给浏览器 # 所以除非特殊需要,不要设置这种画蛇添足的配置 proxy_redirect default; } # 一个url重写的例子,浏览器请求 /page.go时,url被重写成/test/page.jsp location ~ \.go$ { rewrite ^(.*)\.go$ /test/$1\.jsp last; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
在分布式服务器集群中session共享问题
问题:当我们的用户在tomcat1服务器上登录后,tomcat1会保存用户的登录信息,但当用户的请求被代理服务器分配给tomcat2/tomcat3服务器时,这时就会出现tomcat2/tomcat3无法获取用户登录信息,从而导致用户需要重新登录的现象。我们有三种解决方案:
1、同一个用户的请求锁定在同一台服务器上,这样就不会存在session在不同服务器之间共享问题。这种方案简单,但缺乏容错性(一旦服务器故障,那用户的请求将被分配给其他服务器,这时就需要重新登录)
实现方式:设置集群策略为 ip_hash?;
upstream tomcats{ ip_hash; }
2、session复制方式: 当任何服务器中session值发生改变,他都会将该改变广播给其他服务器,当其他服务器收到广播后也做相应的改变,从而实现session在所有服务器中一直。缺点 当集群中tomcat服务器很多时会增加网络负荷,性能低下。实现方式:
2、在tomcat的server.xml中配置session广播
a、
?
b、在我们的分布式应用的web.xml 中添加标签 :作用是公告我们的应用可以处于集群环境中。
?3、通过创建额外的共享空间用来管理session,一般我们使用分布式缓存技术redis、memcached缓存技术,在这里我么使用memcached。
a、memcached的安装:http://www.cnblogs.com/jalja/p/6121978.html
b、memcached?的 session共享原理
? 粘性共享:
非粘性:
c、tomcat访问memcached的相关环境(我们使用的是tomcat7)
1. 复制jar包到tomcat/lib目录,jar分三类
1)spymemcached.jar memcached java客户端????????
2)memcached相关的包
? ? ? ? ? ? ? ? ? ? ?核心包 memcached-session-manager-{version}.jar?
? ? ? ? ? ? ? ? ? ???Tomcat版本相关的包 memcached-session-manager-tc{tomcat-version}-{version}.jar??
3)序列化工具包,有多种可选方案,不设置时使用jdk自带序列化,其它可选kryo,javolution,xstream,flexjson等? ?msm-{tools}-serializer-{version}.jar ?其它序列化工具相关包? 一般第三方序列化工具不需要实现serializable接口。
d、配置Context,加入处理session的Manager? MemcachedBackupSessionManager
?Context配置查找顺序:
??????? 1)conf/context.xml 全局配置,作用于所有应用
??????? 2) conf/[enginename]/[hostname]/context.xml.default 全局配置,作用于指定host下全部应用
??????? 3) conf/[enginename]/[hostname]/[contextpath].xml 只作用于contextpath指定的应用
??????? 4) 应用META-INF/context.xml 只作用于本应用
??????? 5) conf/server.xml
???????? 如果只希望session管理作用于特定应用,最好用3,4方式设置,希望作用全体,可用1,2,5设置
?conf/context.xml的配置:
?
WEB-INF/web.xml ${catalina.base}/conf/web.xml
?集群环境开发注意事项
1、实体类要序列化( implements Serializable)
private static final long serialVersionUID = 3349238980725146825L;
2、获取客户端请求地址的方式 。在nginx-tomcat.conf中添加如下配置:
server { location / { proxy_set_header X-Real-IP $remote_addr; # 真实的客户端IP } }
java代码:
public static String getIp(HttpServletRequest request){ String remoteIp =request.getRemoteAddr(); String headIp=request.getHeader("X-Real-IP"); return headIp==null?remoteIp:headIp; }
3、动静分离
把静态文件放在nginx服务器中(css、js、图片)