Nginx+Sticky实现负载均衡(2)

来源:互联网 发布:百度淘宝网购物商城 编辑:程序博客网 时间:2024/05/24 01:30

http://blog.csdn.net/a897180673/article/details/78364996
这是第二遍博客,上面的是第一篇

之前可以用Nginx实现 对客户端的请求随机分配到 两台Tomcat 上去.
我们这样做的目的就是负载均衡,两台Tomcat 分担压力.

虽然达到分流的目的了,但是有一个问题出现了:客户端请求在两个Tomcat上随机分配,每次请求Tomcat都会在各自内存中创建Session,用来保存会话信息,这样的话,浪费内存也就算了,要命的是
我们在第一台服务器上保存了相关数据,有可能第二次要使用时,突然跳到第二台服务器上,这样肯定是没有用的.

由此问题出现了:

1.Nginx随机分配请求,有可能2Tomcat都会被分配到, 都在内存中创建Session,浪费内存,虽然分流,但是并没有缓解压力.2.由于出现1的情况,会出现Session信息保存在Tomcat1服务器,结果跳到Tomcat2上进行业务处理时.取不到Session,这个事最要命的!

所以我们解决的办法就是,让客户端第一次转到Tomcat1了,以后的请求都转到Tomcat1,如果第一次转到Tomcat2了,那么以后的请求都转到Tomcat2

这样才能真正实现Nginx的负载均衡.

Nginx有一个Sticky扩展模块 可以帮我们实现这样的功能

下面说一下大概的硬件配置:

Nginx:192.168.100.10Tomcat2:192.168.100.13:8080Tomcat1:192.168.100.12:8080

三台服务器,第一篇已经写了怎么样安装Nginx
下面说一下怎么为Nginx 安装扩展的Sticky

wget http://nginx-sticky-module.googlecode.com/files/nginx-sticky-module-1.1.tar.gz
解压到一个目录假设:/opt/123/nginx-sticky-module-1.1
假设Nginx 的安装目录是 /usr/local/Nginx
然后进入Nginx 的目录 运行一下代码

./configure --prefix=/usr/local/Nginx --add-module=/opt/123/nginx-sticky-module-1.1  

然后 make
安装成功后 重启 Nginx
下面还是配置Nginx conf目录下面的Nginx.conf 文件
相对于第一篇博客 就增加了一句

顺便说一下,有可能Sicky模块安装不了,这个是版本的原因,安装低一点的版本就OK了

http{Xxxxx  #其他代码upstream cluster_test.com{      sticky;  #就增加这一句   server 192.168.100.12:8080  weight=1;   server 192.168.100.13:8080  weight=2 ;}  location / {            proxy_pass http://cluster_test.com;            proxy_redirect default;        }Xxxxxx #其他代码}

突然感觉配置 有点 简单的过分了,其实这一句是默认配置

如果想丰富配置,可以参考下面

sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1][no_fallback=yes|no];name: 可以为任何的string字符,默认是routedomain:哪些域名下可以使用这个cookiepath:哪些路径对启用sticky,例如path/test,那么只有test这个目录才会使用sticky做负载均衡expires:cookie过期时间,默认浏览器关闭就过期,也就是会话方式。no_fallbackup:如果设置了这个,cookie对应的服务器宕机了,那么将会返回502(bad gateway 或者 proxy error),建议不启用

比如设置cookie的名字为hahah,cookie采用sha1加密

sticky name=hahaha hash=sha1

ok 下面跑一下看看

这回的测试界面变了,因为我们要看Session 的测试效果 ,所以我们写两个Servlet试试

一个是Login:向内存中添加Session
一个是Show:从内存中读取Sesion并显示

上代码:

首先是 Login

@WebServlet("/Login")public class Login extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setCharacterEncoding("utf-8");        response.setContentType("text/html; charset=utf-8");        String name=request.getParameter("name");        request.getSession().setAttribute("name", name);    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        // TODO Auto-generated method stub        this.doGet(request, response);    }}

然后是Show

@WebServlet("/Show")public class Show extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setCharacterEncoding("utf-8");        response.setContentType("text/html; charset=utf-8");        PrintWriter out =response.getWriter();        Object obj=request.getSession().getAttribute("name");        if(obj==null)        {            out.println("name为null");        }else {        out.println(obj.toString());        }    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

把这个应用导出为Nginx.war,放到两个Tomcat上面运行
先来测试一下写入Session
http://192.168.100.10/Nginx/Login?name=123
然后测试一下读取Session:
http://192.168.100.10/Nginx/Show
然后显示:

这里写图片描述

不停得刷新,还是这个结果
说明我们的请求固定了,没有出现跳到另外一个Tomcat.如果跳到另外一个Tomcat会显示name为null

下面还是老规矩 调试下 看看结果

这里写图片描述

可以看到 客户端带了两个cookie给Nginx服务器,其中一个cookie的名字是route,Nginx就是根据这个值进行转发的.
转发到具体的Tomcat后,Tomcat只要根据另外一个Cookie的名字JESSISONID到自己的内存中拿取Session就可以得到数据了.