Home  >  Article  >  php教程  >  Nginx server Nginx and tomcat achieve load balancing

Nginx server Nginx and tomcat achieve load balancing

高洛峰
高洛峰Original
2016-12-01 16:56:381304browse

Nginx server Nginx and tomcat achieve load balancing

本文讲解我们如何使用Nginx做反向带服务器,实现nginx与tomcat服务器集群做负载均衡。

一、nginx与tomcat实现负载均衡

1、在/usr/local/ngnix/conf  创建文件 nginx-tomcat.conf

文件内容:

user  nobody;
worker_processes  2;
events {   
    worker_connections  1024;    
}
http{
    # upstream 配置一组后端服务器,
    # 请求转发到upstream后,nginx按策略将请求指派出某一服务器
    # 即配置用于负载均衡的服务器群信息
    upstream tomcats{
        fair;
        server 121.42.41.143:8080;
        server 219.133.55.36;
    }
    server {
        listen       80;
        server_name  121.42.41.143;
        access_log  logs/tomcat-nginx.access.log  combined;
        # 反向代理设置,将所有/路径下请求发给本机上的tomcat
        location / {
            #root   html;
            index  index.html index.htm;
            #==========Nginx提供的代理============
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://tomcats;
        }
   }
}

、使用该配置文件启动nginx (启动前先关闭nginx)

    [root@iZ28b4kreuaZ bin]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-tomcat.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;
        }

    }
}

三、fair策略的安装

fair策略:根据各个服务器的性能的不同,自动选择使用响应能力强的服务器。该策略是第三方提供的,所以要先安装。

安装步骤

1、下载 gnosek-nginx-upstream-fair-a18b409.tar.gz

2、解压  tar zxvf gnosek-nginx-upstream-fair-a18b409.tar.gz

3、将解压后的文件移动到 /usr/local目录下并 改名为 nginx-upstream-fair

Nginx server Nginx and tomcat achieve load balancing

4、将该模块添加到我们安装的nginx中

a、首先进入nginx-1.8.1源文件目录下在执行:

[root@iZ28b4kreuaZ nginx-1.8.1]# ./configure --prefix=/usr/local/nginx --add-module=/usr/local/nginx-upstream-fair/

b、执行:make    进行编译

c、进入 nginx-1.8.1/objs/下将最新的nginx启动项 覆盖原来的 /usr/local/nginx/sbin/nginx启动项。

    [root@iZ28b4kreuaZ objs]# cp nginx /usr/local/nginx/sbin

d、开启Nginx 看看是可以使用

 四、在分布式服务器集群中session共享问题

问题:当我们的用户在tomcat1服务器上登录后,tomcat1会保存用户的登录信息,但当用户的请求被代理服务器分配给tomcat2/tomcat3服务器时,这时就会出现tomcat2/tomcat3无法获取用户登录信息,从而导致用户需要重新登录的现象。我们有三种解决方案:

1、同一个用户的请求锁定在同一台服务器上,这样就不会存在session在不同服务器之间共享问题。这种方案简单,但缺乏容错性(一旦服务器故障,那用户的请求将被分配给其他服务器,这时就需要重新登录)

实现方式:设置集群策略为 ip_hash ;

 upstream tomcats{
        ip_hash;
    }

2、session复制方式: 当任何服务器中session值发生改变,他都会将该改变广播给其他服务器,当其他服务器收到广播后也做相应的改变,从而实现session在所有服务器中一直。缺点 当集群中tomcat服务器很多时会增加网络负荷,性能低下。实现方式:

a、在tomcat的server.xml中配置session广播

<!-- 基于网络广播的策略,一个节点session变化,其它节点同步复制,节点多或数据量大时性能低下 -->
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
        <Channel className="org.apache.catalina.tribes.group.GroupChannel">   
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
                      address="192.168.6.223"  
                      port="8080"/> 
        </Channel>
      </Cluster>

b、在我们的分布式应用的web.xml 中添加 标签

:作用是公告我们的应用可以处于集群环境中。

 3、通过创建额外的共享空间用来管理session,一般我们使用分布式缓存技术redis、memcached缓存技术,在这里我么使用memcached。

  a、memcached的安装:http://www.cnblogs.com/jalja/p/6121978.html

  b、memcached 的 session共享原理

   粘性共享:

Nginx server Nginx and tomcat achieve load balancing

非粘性:

Nginx server Nginx and tomcat achieve load balancing

c、tomcat访问memcached的相关环境(我们使用的是tomcat7)

  1. 复制jar包到tomcat/lib目录,jar分三类

    1)spymemcached.jar memcached java客户端        

    2)memcached相关的包  memcached-session-manager-{version}.jar       核心包         memcached-session-manager-tc{tomcat-version}-{version}.jar   Tomcat版本相关的包

    3)序列化工具包,有多种可选方案,不设置时使用jdk自带序列化,其它可选kryo,javolution,xstream,flexjson等   msm-{tools}-serializer-{version}.jar  其它序列化工具相关包  一般第三方序列化工具不需要实现serializable接口

Nginx server Nginx and tomcat achieve load balancing

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 下 作用于Context docBase指定的应用
         如果只希望session管理作用于特定应用,最好用3,4方式设置,希望作用全体,可用1,2,5设置

 conf/context.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>

<Context>

    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- sticky session 最小配置-->
    <!-- className 管理器类名 -->
    <!-- memcachedNodes memcached服务器节点,以节点名:主机:端口形式表示,其中节点名随意命名,但不同tomcat间要一致 -->
    <!-- sticky隐含默认值为true,此时为sticky session模式 -->
    <!-- failoverNodes 仅适用于sticky模式, n1表示主要将session备份到n2,如果n2不可用,再用n1-->
    <!-- 另一台服务器配置正好相反,这样保证将session保存到其它机器,避免整个机器崩溃时tomcat与session一起崩溃-->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
        memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
        failoverNodes="n1"
    />
    
    <!-- 经常用到的生产环境sticky(粘性)模式配置 -->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
        memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
        failoverNodes="n1"
        requestUriIgnorePattern=".*\.(jpg|png|css|js)$" 
        memcachedProtocol="binary"
        transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    
    <!-- 经常用到的生产环境non-sticky(非粘性模式)模式配置 -->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
        memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
        sticky="false"
        sessionBackupAsync="false"
        lockingMode="auto"
        requestUriIgnorePattern=".*\.(jpg|png|css|js)$" 
        memcachedProtocol="binary"
        transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    
    <!--
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
        memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
        
        #sticky模式,默认true
        sticky="false"
        
        #仅适用于sticky模式,n1表示主要将session备份到n2,如果n2不可用,再用n1
        failoverNodes="n1"
        
        #忽略的请求类型,这些类型请求不处理session
        requestUriIgnorePattern=".*\.(jpg|png|css|js)$" 
        
        #例如context中设置sessionPath=/时,一个host下多个应用可能有相同session_id,
        #此时向memcached写入时会造成混乱,可通过以下方式加前缀区分不同应用
        storageKeyPrefix="static:name|context|host|webappVersion|context.hash|host.hash|多项组合,以,间隔"
        
        #设置mecached协议数据传输方式,默认text,设为binary有助力性能提升
        memcachedProtocol="binary"
        
        #是否异步存储session变化,默认true,性能好,适用于sticky模式,
        #non-sticky时建议设置为false,避免延迟造成信息不一致
        sessionBackupAsync="false"
        
        #仅适用于non-sticky模式,为避免同步编辑冲突,在修改session时锁定
        #同步编辑一种可能发生的情况是在ajax请求时,同一页多个请求同时发起,可能会访问不同后端
        #auto 读模式不锁写模式锁
        #uriPattern模式,将URI+"?"+queryString与模式Regex匹配,如果匹配则锁定
        lockingMode="none|all|auto|uriPattern:Regex"
        
        #使用第三方序列化工具,提高序列化性能
        #常用的第三方工具kryo, javolution, xstream等
        #此时需要向tomcat/lib下添加相关jar包
        transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
        
    />
    -->
   
</Context>

四、集群环境开发注意事项

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、图片)

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn