Nginx如何实现负载均衡以及Session共享教程详解

最近迷上了Nginx,真实麻雀虽小,五脏俱全..功能实在强大..php

nginx不单能够做为强大的web服务器,也能够做为一个反向代理服务器,并且nginx还能够按照调度规则实现动态、静态页面的分离,能够按照轮询、ip哈希、URL哈希、权重等多种方式对后端服务器作负载均衡,同时还支持后端服务器的健康检查。html

若是只有一台服务器时,这个服务器挂了,那么对于网站来讲是个灾难.所以,这时候的负载均衡就会大显身手了,它会自动剔除挂掉的服务器.前端

下面简单的介绍下我使用Nginx作负载的体会nginx

下载---安装Nginx这些不介绍了,前篇有介绍.web

windows和Linux下配置Nginx负载的写法同样,故不分开介绍.redis

Nginx负载均衡一些基础知识:数据库

nginx 的 upstream目前支持 4 种方式的分配 1)、轮询(默认) 每一个请求按时间顺序逐一分配到不一样的后端服务器,若是后端服务器down掉,能自动剔除。 2)、weight 指定轮询概率,weight和访问比率成正比,用于后端服务器性能不均的状况。 2)、ip_hash 每一个请求按访问ip的hash结果分配,这样每一个访客固定访问一个后端服务器,能够解决session的问题。
3)、fair(第三方) 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash(第三方)windows

配置:后端

在http节点里添加: 定义负载均衡设备的 Ip及设备状态
upstream myServer {
server 127.0.0.1:9090 down; server 127.0.0.1:8080 weight=2; server 127.0.0.1:6060; server 127.0.0.1:7070 backup; } 在须要使用负载的Server节点下添加 proxy_pass http://myServer; upstream 每一个设备的状态: down 表示单前的server暂时不参与负载 weight 默认为1.weight越大,负载的权重就越大。 max_fails :容许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误 fail_timeout:max_fails 次失败后,暂停的时间。 backup: 其它全部的非backup机器down或者忙的时候,请求backup机器。因此这台机器压力会最轻。浏览器

Nginx还支持多组的负载均衡,能够配置多个upstream 来服务于不一样的Server.

配置负载均衡比较简单,可是最关键的一个问题是怎么实现多台服务器之间session的共享

下面有几种方法(如下内容来源于网络,第四种方法没有实践.)

  1. 不使用session,换做cookie

能把session改为cookie,就能避开session的一些弊端,在从前看的一本J2EE的书上,也指明在集群系统中不能用session,不然惹出祸端来就很差办。若是系统不复杂,就优先考虑可否将session去掉,改动起来很是麻烦的话,再用下面的办法。

  1. 应用服务器自行实现共享

asp.net能够用数据库或memcached来保存session,从而在asp.net自己创建了一个session集群,用这样的方式能够令 session保证稳定,即便某个节点有故障,session也不会丢失,适用于较为严格但请求量不高的场合。可是它的效率是不会很高的,不适用于对效率 要求高的场合。 以上两个办法都跟nginx没什么关系,下面来讲说用nginx该如何处理:

  1. ip_hash

nginx中的ip_hash技术可以将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能创建起稳固的session,ip_hash是在upstream配置中定义的: upstream backend { server 127.0.0.1:8080 ; server 127.0.0.1:9090 ; ip_hash; } ip_hash是容易理解的,可是由于仅仅能用ip这个因子来分配后端,所以ip_hash是有缺陷的,不能在一些状况下使用: 1/ nginx不是最前端的服务器。ip_hash要求nginx必定是最前端的服务器,不然nginx得不到正确ip,就不能根据ip做hash。譬如使用的是squid为最前端,那么nginx取ip时只能获得squid的服务器ip地址,用这个地址来做分流是确定错乱的。 2/ nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又经过另外的方式分流了,那么某个客户端的请求确定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,而后指向应用服务器。最好的办法是用location做一次分流,将须要session的部分请求经过ip_hash分流,剩下的走其它后端去。

  1. upstream_hash

为了解决ip_hash的一些问题,可使用upstream_hash这个第三方模块,这个模块多数状况下是用做url_hash的,可是并不妨碍将它用来作session共享: 假如前端是squid,他会将ip加入x_forwarded_for这个http_header里,用upstream_hash能够用这个头作因子,将请求定向到指定的后端: 可见这篇文档:www.sudone.com/nginx/nginx… 在文档中是使用request\_uri作因子,稍微改一下:
hashhttp_x_forwarded_for; 这样就改为了利用x_forwarded_for这个头做因子,在nginx新版本中可支持读取cookie值,因此也能够改为: hash $cookie_jsessionid; 假如在php中配置的session为无cookie方式,配合nginx本身的一个userid_module模块就能够用nginx自发一个cookie,可参见userid模块的英文文档: wiki.nginx.org/NginxHttpUs… 另可用姚伟斌编写的模块upstream_jvm_route:code.google.com/p/nginx-ups…

===============================================

blog.csdn.net/chao_1990/a…

共享session应用场景,基于分布式,session的原理大体以下(以tomcat为例),

tomcat有一套本身的session管理机制,每次建立链接的时候都会经过客户端传过来的jsessionid从session链接池中得到sessionId对应的session,若是存在,那么直接从池中得到session链接信息,若是没有经过程序中设置判断是否建立一个新的session信息保存到池中。

nginx贡献session的方式,大致上有ip_hash(nginx自带),redis共享session,基于cookie,基于db(各类关系型数据库和非关系型数据库)。

一、基于cookie

简单、方便,每次经过判断cookie中的用户状态信息判断用户的登陆状态;可是用户信息要存在客户端,存在安全隐患,除非有至关安全的加密措施,若是加密码负载,也会 增长运算的成本。

二、基于db(各类关系型数据库和非关系型数据库)

登陆信息存储到db中,虽然安全,但每次须要验证用户的登陆状态是都须要从db中进行IO操做,并发量高是势必会增长数据库的负载。

三、基于redis+cookie共享session

此种方式将将用户的登陆信息存储到redis中,由于是基于内存的读取,所以效率不会是响应效率的瓶颈,cookie中存储着jsessionid,不须要加密或处理,只须要存储redis中的key保存统一客户经过cookie中的key能够准确的登陆信息或是其余有效的信息,此种方式,cookie的存储不须要加密计算成本,其次redis将信息存储到缓存中,存取效率高,后面会详细介绍此种方式实现过程。

四、基于ip_hash

此种方式配置最为简单,可是有必定的局限性,其原理就是同一个ip的全部请求都会被nginx进行ip_hash进行计算,经过结果定位到指定的后台服务器即一个用户若是ip不变,那么每次请求其实请求的都是同一后台服务器;首先最外层的代理要保证源ip在请求 的过程不会被修改,若是你的架构里在最外层方式不仅仅是nginx服务,而是相似于请求分发的服务服务器,那么意味着一我的的请求可能被定位到不一样的服务器上,那么ip_hash就没有意义了。

五、基于tomcat容器session

此种方式在根本上实现共享session,他的实际状况是经过tomcat管理配置将一个tomct下的session复制到其余的tomcat的session池中,实现真实上的session共享;此种方式须要兼容tomcat配置及须要对其进行扩展,依赖性太强。

已实现的共享方式:

首先配置3个web容器,tomcat1(3301),tomcat2(3302)、tomcat3(3303)

一、ip_hash

nginx的配置这里再也不说明,主要说明ip_hash的配置,简直是简单到节点

  1. upstream backend {
  2. ip_hash;
  3. server localhost:3301 max_fails=2 fail_timeout=30s ;
  4. server localhost:3302 max_fails=2 fail_timeout=30s ;
  5. server localhost:3303 max_fails=2 fail_timeout=30s ;
  6. }

nginx的配置文件nginx.conf引入upstram数据,启动便可。

验证:

过访问web应用,例如http://localhost:8080/login.jsp登陆后存储session信息,每次访问这个页面都须要验证session的状态,页面实现的是tomcat1表示,此ip的请求被转发到了tomcat1的服务器上,不管怎么刷新页面,页面显示的都是tomcat1,此时停掉tomcat1,再次刷新页面,页面显示的是tomcat2或是tomcat3的登陆页面,此时表示nginx负载目的已经达到,可是session没有共享;局限性显而易见。

二、redis+cookie共享session

原理实现:

1)、登陆成功时,将还有redis的key保存到cookie中,将登陆用户的信息保存到redis中;

2)、配置拦截器,拦截须要验证登陆状态的请求,从cookie中得到redis的key,从redis中得到当前cookie对应的用户信息,对其登陆状态进行验证。

验证:

取消nginx的ip_hash配置,登陆web,例如例如http://localhost:8080/login.jsp登陆后存储session信息,首页显示tomcat1,此时不须要关闭任何tomcat,直接不停的刷新主页就会发现主页的再tomcat一、tocmat二、tomcat3之间来回切换,表示session已正常共享。我的认为此种方式是比较推荐的。

观点:

从功能的核心来看,其目的就是共享session,究其缘由就是客户端和服务之间须要一个惟一的值来创建关联关系,此值就是sessionId,不管请求哪一个网站经过工具查看cookie都会有发现,有jsessionid的值,此值在于服务器创建链接之后是基本不会变的(后台主动建立新的session)。及时上面的描述的共享方式5,基于session链接池的session管理,也是要依赖sessionid的,经过查看tomcatsession管理的源码,不难发现其也是经过cookie得到的sessionid,那么若是客户端请强制禁用了cookie,该如何得到jsessionId? 以前查阅过资源(未亲自证明),当浏览器禁用cookie后,请求的地址会被重定向,重定向后会在请求的url中拼接上jsessionid,这个容器就能得到sessionid,也就能够验证session 状态;此种场景有待证明。

往期文章

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 Nginx系列教程(9)nginx 解决session一致性

相关文章
相关标签/搜索