Nginx+Tomcat负载均衡详述与实战

nginx是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器。它主要有以下优点:

  1. 高并发连接:
    官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。
  2. 内存消耗少:
    在3万并发连接下,开启的10个Nginx 进程才消耗150M内(15M*10=150M)。
  3. 配置文件非常简单:
    风格跟程序一样通俗易懂。
  4. 成本低廉:
    Nginx为开源软件,可以免费使用。而购买F5 BIG-IP、NetScaler等硬件负载均衡交换机则需要十多万至几十万人民币。
  5. 支持Rewrite重写规则:
    能够根据域名、URL的不同,将 HTTP 请求分到不同的后端服务器群组。
  6. 内置的健康检查功能:
    如果 Nginx Proxy 后端的某台 Web 服务器宕机了,不会影响前端访问。
  7. 节省带宽:
    支持 GZIP 压缩,可以添加浏览器本地缓存的 Header 头。
  8. 稳定性高:
    用于反向代理,宕机的概率微乎其微

由于nginx的性能很好,因此国内很多大公司都在使用,最主要的原因也是nginx是开源免费的。除了上面描述的一系列功能,项目中主要用nginx来实现以下三个功能:

  • 动静分离
  • 反向代理
  • 负载均衡

动静分离

动静分离的原理非常简单,我们可以将一些静态资源html文件、图片等交给nginx来处理,将后台请求转发给后台服务器处理,由于nginx会有缓存作用,因此这样不仅仅加快了访问速度,而且也减小了tomcat服务器的负载。

反向代理

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连的客户端,此时代理服务器对外就表现为一个服务器。
这里写图片描述

需要注意的是代理服务器可以作为前端服务器来处理前端等请求处理静态资源,但是不能处理后端服务器的请求。

nginx反向代理主要有以下特点:

反向代理又称为Web服务器加速,是针对Web服务器提供加速功能的。它作为代理Cache,但并不针对浏览器用户,而针对一台或多台特定Web服务器(这也是反向代理名称的由来)。代理服务器可以缓存一些web的页面,降低了web服务器的访问量,所以可以降低web服务器的负载。web服务器同时处理的请求数少了,响应时间自然就快了。同时代理服务器也存了一些页面,可以直接返回给客户端,加速客户端浏览。

负载均衡

负载均衡主要是为了解决服务器负载过大,在有的时候,系统的并发量过大,一台服务器无法负担的起用户发送的请求,因此我们需要搭建服务器集群,而nginx负载均衡就是接收用户的请求将其转发给后台服务器集群上的每一台机器。
这里写图片描述

扫描二维码关注公众号,回复: 2858518 查看本文章

负载均衡主要有以下特点:

  • 分散后台服务器的负载
  • 自动去掉后台宕机的服务器
  • 缓存后台请求内容,加速请求速度

    nginx负载均衡主要有以下五种策略:

    1. 轮询(默认)
      每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
    2. weight
      指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
    3. ip_hash
      每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
    4. fair(第三方)
      按后端服务器的响应时间来分配请求,响应时间短的优先分配。
    5. url_hash(第三方)
      按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

默认情况下是轮询的策略,但是这种方式的使用有一个问题,分布式session不一致的问题,不过我们可以使用ip_hash来将同一ip地址上的请求分配到一台服务器中处理,这样就不会出现session不一致的问题。这个问题不是我们这篇文章讨论的重点,感兴趣的读者可以自行查询资料。

下面我们开始今天的实战环节,对于环境的要求当然必须安装Java了,还有安装nginx服务器,以及tomcat服务器。

首先需要准备三台tomcat服务器和一台nginx服务器,然后建立一个文件夹www来存放应用的打包的源码。项目结构目录如下:
这里写图片描述

tomcat服务器中的配置如下(三台服务器的配置基本都一样,注意要修改每一台服务器的端口号):

 <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
            <Context path="" docBase="G:\BaiduNetdiskDownload\nginx\www\Sys" />
      </Host>

上面配置的路径就是我存放项目源码的路径。

为了区分三台服务器,我们可以去tomcat服务器中找打Catalina.bat(Windows环境下,linux下找到.sh文件即可)文件,依次修改TITLE选项为app01、app02、app03:
这里写图片描述

接下来就可以配置nginx服务器了,使用upstream来配置tomcat集群,其主要配置如下,三台服务器,在最后一行可以指定负载均衡的策略,如果什么也不写默认轮询策略,这里我们使用轮询策略,主要是方便观察:

upstream shinelon{
    server localhost:8080;
    server localhost:8081;
    server localhost:8082;
    #ip_hash
}

在配置nginx.conf文件时,有时我们需要配置多个虚拟主机server,因此我们可以为每一台虚拟主机写一个配置文件,然后利用nginx的include将其包含进主配置文件中,这样也方便我们管理,不至于主配置文件中内容冗余复杂不方便管理。所以一般在nginx的安装目录的conf目录下添加文件夹vhost文件夹,然后将子配置文件放入到这个文件夹中。
这里写图片描述

下面是子配置文件www.shinelon.com.conf子文件夹的完整配置:

upstream shinelon{
    server localhost:8080;
    server localhost:8081;
    server localhost:8082;
}

server {
        listen       80;
        server_name  www.shinelon.com;

        location \ {  
            root G:\BaiduNetdiskDownload\nginx\www\Sys; 
        }   

        location ~ \.action$ {
            proxy_pass   http://shinelon;
        }

        location ~ \.jsp$ {
            proxy_pass   http://shinelon;
        }

        location ~ ^/WEB-INF/ {
            deny  all;
        }
    }

上面配置文件的主要意思是设置一台虚拟服务器名为www.shinelon.com,然后使用upstream配置三台服务器来进行负载均衡,所有的请求都会去根目录下去寻找:

location \ {  
            root G:\BaiduNetdiskDownload\nginx\www\Sys; 
        }  

以.jsp或者.action结尾的请求转发到tomcat集群中处理:

location ~ \.action$ {
            proxy_pass   http://shinelon;
        }

        location ~ \.jsp$ {
            proxy_pass   http://shinelon;
        }

禁止访问WEB-INF目录下的文件:

location ~ ^/WEB-INF/ {
            deny  all;
        }

接着就是主配置文件nginx.conf文件中的内容:

worker_processes  1;

error_log  logs/error.log;

events {
    worker_connections  1024;
}

http {
    include       mime.types;

    include vhost/www.shinelon.com.conf;

    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

使用include将自配置文件加入到主配置文件中:

include vhost/www.shinelon.com.conf;

到这里我们就已经完成了所有配置,不过需要注意的是需要在操作系统的etc/hosts文件(Windows下)中加入上面所使用的域名的映射,全部映射到本机。配置如下所示:

127.0.0.1    www.shinelon.com
127.0.0.1    shinelon

现在我们可以启动服务器,然后发送请求,由于我之前搭建的web项目会在后台打印日志,因此这也方便我们观察是否使用轮询策略将请求负载到不同服务器上。在启动项目之后,总共发送五次登录请求,nginx会将这五次请求分发到不同的服务器中处理。结果如下图所示:
这里写图片描述

至此,我们就完成了对nginx负载均衡的测试,如有什么问题欢迎留言讨论。


猜你喜欢

转载自blog.csdn.net/qq_37142346/article/details/81048334