本文讲解我们如何使用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;
}
}
}

2、使用该配置文件启动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

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 中添加 <distributable/>标签

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

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       核心包         memcached-session-manager-tc{tomcat-version}-{version}.jar   Tomcat版本相关的包

    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 <Host>下 作用于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、图片)

Nginx 服务器 之Nginx与tomcat实现负载均衡的更多相关文章

  1. Nginx服务器的使用与反向代理负载均衡

    目录 Nginx服务器 一:什么是Nginx? 什么是Nginx - Nginx与其他服努器的性能比较 二:如何在Linux中搭建Nginx服务器? 常见的错误 三:Nginx的反向代理和负载均衡 什 ...

  2. Nginx安装使用及与tomcat实现负载均衡

    1. 背景 基于nginx强大的功能,实现一种负载均衡,或是不停机更新程序等.nginx相比大家基本上都知道是什么来头了,具体的文章大家可以去搜索相关文章学习阅读,或是可以查看Nginx中文文档和Ng ...

  3. Nginx+Tomcat+Memcached负载均衡集群服务搭建

    操作系统:CentOS6.5  本文档主要讲解,如何在CentOS6.5下搭建Nginx+Tomcat+Memcached负载均衡集群服务器,Nginx负责负载均衡,Tomcat负责实际服务,Memc ...

  4. nginx+tomcat+redis负载均衡及session共享

    概述 本文档是用来详细描述 nginx+tomcat+redis负载均衡实现session共享 所需软件及下载地址 软件名称 下载地址 功能说明 Nginx-v1.6.0 http://nginx.o ...

  5. Tomcat(五):nginx/httpd + tomcat及负载均衡tomcat

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  6. 使用 Nginx + Tomcat 搭建负载均衡

    负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡,英文名称为Load Balance, ...

  7. nginx+tomcat实现负载均衡集群

    一台tomcat站点由于可能出现单点故障及无法应付过多客户复杂多样的请求等问题,不能单独应用于生产环境下 所以需要一套可靠的解决方案来完善web站点架构 而Nginx只能访问静态页面,如果需要动态需要 ...

  8. Docker + Nginx + Tomcat 实现负载均衡简单演示

    Docker + Nginx + Tomcat 实现负载均衡 环境 [root@pinyoyougou-docker ~]# docker -v Docker version 1.12.6, buil ...

  9. nginx+tomcat实现负载均衡以及双机热备

    还记得那些年吗? 还记得更新代码之后,服务器起不来被领导训斥吗?还记得更新代码,需要停机过多的时间被渠道部们埋怨吗?还记得更新代码,代码出错时自己吓个半死吗?于是我们聪明勤快的程序员,看着电影待到夜深 ...

随机推荐

  1. 05.LoT.UI 前后台通用框架分解系列之——漂亮的时间选择器

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  2. 前端制作动画的几种方式(css3,js)

    制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...

  3. [原]Cachedb 网络模块文档

    Cachedb 网络模块文档 整体结构 多路复用 (epoll 模块) 事件驱动 (事件封装) 缓冲管理 (上层buffer管理) 设计思想 层次化的设计,每一个模块只调用上一个模块的接口,并将耦合聚 ...

  4. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  5. Collection集合

    一些关于集合内部算法可以查阅这篇文章<容器类总结>. (Abstract+) Collection 子类:List,Queue,Set 增: add(E):boolean addAll(C ...

  6. BPM与 SAP & Oracle EBS集成解决方案分享

    一.需求分析 SAP和Oracle EBS都是作为全球顶级的的ERP产 品,得到了众多客户的青睐.然而由于系统庞大.价格昂贵以及定位不同,客户在实施过程中经常会面临以下困惑: 1.SAP如何实现&qu ...

  7. Atitit.cto 与技术总监的区别

    Atitit.cto 与技术总监的区别 1. 核心区别1 2. Cto主要职责1 3. 如何提升到cto1 4. CTO五种基本的必备素质:2 5. 2 1. 核心区别 技术总监(Chief Tech ...

  8. Linux命令【第一篇】

    1.创建一个目录/data 记忆方法:英文make directorys缩写后就是mkdir. 命令: mkdir /data 或 cd /;mkdir data #提示:使用分号可以在一行内分割两个 ...

  9. GCC学习(1)之MinGW使用

    GCC学习(1)之MinGW使用 因为后续打算分享一些有关GCC的使用心得的文章,就把此篇当作一个小预热,依此来了解下使用GNU工具链(gcc.gdb.make等)在脱离IDE的情况下如何开发以及涉及 ...

  10. Topshelf 学习 跨平台

    Topshelf是一个开源的跨平台的宿主服务框架,支持Windows和Mono,只需要几行代码就可以构建一个很方便使用的服务宿主. 官网:http://topshelf-project.com Git ...