专栏首页Laoqi's Linux运维专列Tomcat搭建高可用/负载均衡/动静分离的Web服务器集群

Tomcat搭建高可用/负载均衡/动静分离的Web服务器集群

这篇文章会集中以前博客讲到的所有Nginx功能点,包括基本的负载均衡,还有动静分离技术再加上这篇文章的重点,通过Keepalived实现的HA(High Available),为什么要实现高可用呢?以前在搭建的时候只用了一台Nginx服务器,这样的话如果Nginx服务器宕机了,那么整个网站就会挂掉,所以要实现Nginx的高可用,一台挂掉还会有另一台顶上去,从而保证网站可以持续的提供服务。关于负载均衡和动静分离在前面博客中都有相关的介绍,这篇博客就不在详细提了,只会在配置文件中体现。不多说了,下面开始搭建。

拓扑环境

下面表格是这次测试需要的拓扑环境,几台服务器,每台服务器上安装什么,都有介绍。

服务器名称

系统版本

预装软件

IP地址/VIP

Nginx主服务器

CentOS 7 最小安装

Nginx +Keepalived

192.168.22.227/192.168.22.231

Nginx从服务器

CentOS 7 最小安装

Nginx +Keepalived

192.168.22.228/192.168.22.231

Web服务器A

CentOS 7 最小安装

tomcat+jdk

192.168.22.229

Web服务器B

CentOS 7 最小安装

tomcat+jdk

192.168.22.230

前置条件

Keepalived配置安装:keepalived配置高可用集群 Nginx动静分离、负载均衡:Nginx+Tomcat实现动静分离、负载均衡

原理图

开始搭建

一、配置VIP

关于VIP(即虚拟IP)的作用,上篇博客《Keepalived原理篇》已经介绍过了。227和228服务器需要配置相同的VIP,虚拟IP在某时刻只能属于某一个节点,另一个节点作为备用节点存在。当主节点不可用时,备用节点接管虚拟IP,成为主节点(即虚拟IP漂移至从节点),提供正常服务。这个VIP就像个墙头草,两头跑,谁是主他就为谁服务。配置VIP的博客,上面也有链接哦。

二、安装软件

按照上面的表格,在相应服务器上安装软件,安装过程不再多说了,有问题可以点击上面的博客链接哦。

三、配置Nginx

227服务器上的Nginx配置:

    user nobody;

    worker_processes 2;

    events{
            worker_connections 1024; 
    }

    http{
    #设置默认类型为二进制流
            default_type    application/octet-stream;

            server_names_hash_bucket_size   128;
            #指定来自客户端请求头的headerbuffer大小,设置为32KB
            client_header_buffer_size   32k;
            #指定客户端请求中较大的消息头的缓存最大数量和大小,这里是4个32KB
            large_client_header_buffers 4 32k;
            #上传文件大小
            client_max_body_size 356m;
            #nginx的HttpLog模块指定,指定nginx日志的输出格式,输出格式为access
            log_format access '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
            #access日志存在未知
            access_log  /usr/local/nginx/logs/access.log    access;
            #开启高效模式文件传输模式,将tcp_nopush和tcp_nodelay两个指另设置为on,用于防止网络阻塞。
            sendfile    on;
            tcp_nopush  on;
            tcp_nodelay on;
            #设置客户端连接保持活动的超时时间
            keepalive_timeout   65;
            server_tokens   off;
            #客户端请求主体读取缓存
            client_body_buffer_size 512k;
            proxy_connect_timeout   5;
            proxy_send_timeout      60;
            proxy_read_timeout      5;
            proxy_buffer_size       16k;
            proxy_buffers           4 64k;
            proxy_busy_buffers_size 128k;
            proxy_temp_file_write_size 128k;

            #fastcgi_connect_timeout 300;
            #fastcgi_send_timeout   300;
            #fastcgi_read_timeout   300;
            #fastcgi_buffer_timeout 300;
            #fastcgi_buffers 4 64k;
            #fastcgi_busy_buffers_size 128k;
            #fastcgi_temp_file_write_size 128k;

            #开启gzip
            gzip    on;
            #允许压缩的最小字节数
            gzip_min_length 1k;
            #4个单位为16k的内存作为压缩结果流缓存
            gzip_buffers 4 16k;
            #设置识别HTTP协议版本,默认是1.1
            gzip_http_version 1.1;
            #gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
            gzip_comp_level 2;
            #压缩的类型
            gzip_types text/plain application/x-javascript text/css application/xml;
            #让前端的缓存服务器混村经过的gzip压缩的页面
            gzip_vary   on;

            upstream mycluster{
                     server 192.168.22.229:8080 weight=1;
                     server 192.168.22.230:8080 weight=1;
                    }

            server{
                    listen 8088;
                    server_name 192.168.22.227;
                    charset    utf-8; #设置编码为utf-8
                    #root   html;

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

            #location ~ .*\.(jsp|do|action)$
            location / {
                    proxy_next_upstream http_502 http_504 error timeout invalid_header;
                    proxy_pass http://mycluster;
                    # 真实的客户端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;
            }
            #静态文件交给nginx处理
            location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
            {
                    root /usr/local/webapps;
                    expires 30d;
            }
            #静态文件交给nginx处理
            location ~ .*\.(js|css)?$
            {
                    root /usr/local/webapps;
                    expires 1h;
            }
            error_page   500 502 503 504  /50x.html;  

            location = /50x.html {
                root   html;
            }

            }
    }

228服务器上的Nginx配置:

    user nobody;

    worker_processes 2;

    events{
            worker_connections 1024; 
    }

    http{
    #设置默认类型为二进制流
            default_type    application/octet-stream;

            server_names_hash_bucket_size   128;
            #指定来自客户端请求头的headerbuffer大小,设置为32KB
            client_header_buffer_size   32k;
            #指定客户端请求中较大的消息头的缓存最大数量和大小,这里是4个32KB
            large_client_header_buffers 4 32k;
            #上传文件大小
            client_max_body_size 356m;
            #nginx的HttpLog模块指定,指定nginx日志的输出格式,输出格式为access
            log_format access '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
            #access日志存在未知
            access_log  /usr/local/nginx/logs/access.log    access;
            #开启高效模式文件传输模式,将tcp_nopush和tcp_nodelay两个指另设置为on,用于防止网络阻塞。
            sendfile    on;
            tcp_nopush  on;
            tcp_nodelay on;
            #设置客户端连接保持活动的超时时间
            keepalive_timeout   65;
            server_tokens   off;
            #客户端请求主体读取缓存
            client_body_buffer_size 512k;
            proxy_connect_timeout   5;
            proxy_send_timeout      60;
            proxy_read_timeout      5;
            proxy_buffer_size       16k;
            proxy_buffers           4 64k;
            proxy_busy_buffers_size 128k;
            proxy_temp_file_write_size 128k;

            #fastcgi_connect_timeout 300;
            #fastcgi_send_timeout   300;
            #fastcgi_read_timeout   300;
            #fastcgi_buffer_timeout 300;
            #fastcgi_buffers 4 64k;
            #fastcgi_busy_buffers_size 128k;
            #fastcgi_temp_file_write_size 128k;

            #开启gzip
            gzip    on;
            #允许压缩的最小字节数
            gzip_min_length 1k;
            #4个单位为16k的内存作为压缩结果流缓存
            gzip_buffers 4 16k;
            #设置识别HTTP协议版本,默认是1.1
            gzip_http_version 1.1;
            #gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
            gzip_comp_level 2;
            #压缩的类型
            gzip_types text/plain application/x-javascript text/css application/xml;
            #让前端的缓存服务器混村经过的gzip压缩的页面
            gzip_vary   on;

            upstream mycluster{
                     server 192.168.22.229:8080 weight=1;
                     server 192.168.22.230:8080 weight=1;
                    }

            server{
                    listen 8088;
                    server_name 192.168.22.228;
                    charset    utf-8; #设置编码为utf-8
                    #root   html;

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

            #location ~ .*\.(jsp|do|action)$
            location / {
                    proxy_next_upstream http_502 http_504 error timeout invalid_header;
                    proxy_pass http://mycluster;
                    # 真实的客户端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;
            }
            #静态文件交给nginx处理
            location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
            {
                    root /usr/local/webapps;
                    expires 30d;
            }
            #静态文件交给nginx处理
            location ~ .*\.(js|css)?$
            {
                    root /usr/local/webapps;
                    expires 1h;
            }
            error_page   500 502 503 504  /50x.html;  

            location = /50x.html {
                root   html;
            }

            }
    }

另外还需要在227,228服务器上新建一个目录/usr/local/webapps/drp/img,在img文件夹中存放图片girl.jpg。如果Nginx服务器较多的话,可以使用Rsync做服务端自动同步或者使用NFS、MFS分布式共享存储,避免一个个拷贝文件。

还有,这块Nginx配置是做过一些优化的,比如开启gzip压缩,开启高效文件传输模式,设置缓存,动静分离,负载均衡等,可以直接拿到项目中使用。

四、配置Keepalived

227服务器上的Keepalived配置:

! Configuration File for keepalived

    #配置邮件相关信息
    global_defs {
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       notification_email_from Alexandre.Cassen@firewall.loc
       smtp_server 192.168.200.1
       smtp_connect_timeout 30
       router_id LVS_DEVEL
    }

    #配置Nginx健康监测脚本
    vrrp_script check_nginx {
            script "</dev/tcp/127.0.0.1/8088"
            interval 3
            weight -2
    }

    vrrp_instance VI_1 {
        state MASTER
      #网卡名称
        interface eno16777736
        virtual_router_id 151
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }

            track_script {
                    check_nginx
            }

        virtual_ipaddress {
            192.168.22.231
        }
    }

228服务器上的Keepalived配置:

    ! Configuration File for keepalived

    global_defs {
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       notification_email_from Alexandre.Cassen@firewall.loc
       smtp_server 192.168.200.1
       smtp_connect_timeout 30
       router_id LVS_DEVEL
    }

    vrrp_script check_nginx {
            #script "/opt/chknginx.sh"
            script "</dev/tcp/127.0.0.1/8088"
            interval 3
            weight -2
    }

    vrrp_instance VI_1 {
        state MASTER
        interface eno16777736
        virtual_router_id 151
        priority 99
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }

            track_script {
                    check_nginx
            }

        virtual_ipaddress {
            192.168.22.231
        }
    }

特别注意,Nginx健康监测脚本。在本地写一个shell脚本,Keepalived监测不到。不知道为什么,网上的博客都是这么写的。但是在我这里就不行。最后直接在Keepalived配置文件的script标签中写了这段监测的脚本,才得以成功。

    vrrp_script chk_http_port {
    script "</dev/tcp/192.168.22.227/80"
    interval 1
    weight -10
    }

里面针对每条配置文件都做了详细解析。

五、Tomcat配置

229服务器,添加默认页

在Tomcat的webapps目录下新建文件夹drp,并且创建index.jsp页面

        <%@ page language="java" contentType="text/html; charset=GB18030"
                pageEncoding="GB18030"%>

        <HTML>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
        <title>Nginx+Keepalived高可用,负载均衡,动静分离测试</title>
        </head>

                <body>
                        <h1>您正在访问服务器:192.168.22.229</h1>
                        <img src="/drp/img/girl.jpg"  alt="女孩" />
                </body>

        </html>

230服务器同上

六、启动服务并测试

分别启动各个服务器上的Nginx、Keepalived、Tomcat,并测试能否正常访问。

①启动测试Tomcat

可以看到229和230服务器上的Tomcat已经可以正常访问,图片没有加载出来,是因为图片没有在Tomcat服务器上存储,而放在了Nginx上。

②启动测试Nginx

可以看到227和228上的Nginx启动成功,并且实现了负载均衡和动静分离的效果,图片被成功的加载了出来。

③ 保证所有服务均可正常访问后,启动Keepalived测试。

启动227,228服务器上的Keepalived,在浏览器中输入地址:http://192.168.22.231:8088/drp/index.jsp

192.168.22.231是咱们设置的虚拟ip,在访问网站的时候不在通过Nginx的ip了,而要通过这个vip进行访问。

Keepalived启动后咱们可以通过查看/var/log 下的messages文件(日志文件),查看主从状态。 查看227服务器/var/log/messages:

可以看到227为Master服务器,那么咱们现在通过192.168.22.231访问的就是227上的Nginx。

Nginx高可用测试

现在咱们通过两个方面来测试高可用:

① 服务器层的双机热备,模拟方式为关闭服务器,或者关闭Keepalived。

a. 关闭227Keepalived进程

现在提供服务的是227服务器,使用命令service keepalived stop将227上的Keepalived进程关闭掉之后。

查看227服务器messas日志:

228原来为从服务器,当227服务器宕机后,228服务器由从服务器升级为主服务器,并且绑定上192.168.22.231这个虚拟IP,以继续提供服务,网站能够继续访问。

b. 启动227Keepalived

查看227服务器messas日志:

Keepalived成功启动后,227服务器继续接管192.168.22.231,成为MASTER服务器,继续提供服务。

查看228服务器messages日志:

相应的228服务器,转变为BACKUP服务器,并且移除VIP。

② 应用层的双机热备,模拟方式为Kill掉Nginx进程

a. 关闭227Nginx

查看227服务器messages日志:

VRRP_Script(check_nginx) failed ,意思是健康监测脚本执行失败,表明Nginx服务坏掉,或者没有启动。然后Keepalived会使227服务器转变为BACKUP状态,移除VIP。

查看228服务器messages日志:

当然不出所料,228服务器已经变为MASTER状态,从而继续提供服务。

b. 重新启动227Nginx

查看227服务器messages日志:

VRRP_Script(check_nginx) succeeded ,意思是健康监测脚本执行成功,Nginx正常运行。然后227服务器就会转变为MASTER状态,并提供服务。

查看228服务器messages日志:

228服务器已经变为BUCKUP状态。

小结 至此,高可用的一系列测试就已经完成了。在整个测试过程中,无论是关闭某台服务器的Nginx,Keepalived还是整个服务器宕机,网站一直没有中断提供服务,这已经达到了基本的高可用;但是还有个缺陷就是如果Nginx主服务器不出问题的话,那么备用服务器将长期处于备份状态,这样的巨大资源浪费是不能容忍的。

当然这也有相应的方案来解决:Nginx双主集群+DNS轮询。

这就是一个架构不断演变,进化的过程!!!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • LVS 三种负载均衡模式详解

    老七Linux
  • Nginx+Tomcat实现动静分离、负载均衡

    老七Linux
  • 浅谈web网站架构演变过程

    老七Linux
  • 服务器失效那些事

    服务器出现故障是大家都非常关心的,而服务器由CPU,内存,磁盘,主板,电源等多种部件组成,一定会有一定的失效率。本文介绍服务器失效的特性及一些部件的失效标准,探...

    腾讯技术工程官方号
  • LVS集群的负载调度

    1. 前言 本文将主要讲述在负载调度器上的负载调度策略和算法,如何将请求流调度到各台服务器,使得各台服务器尽可能地保持负载均衡。文章主要由两个部分组 成。第...

    用户1263954
  • 『权限维持系列』- 屏幕保护程序后门

    屏幕保护是Windows功能的一部分,使用户可以在一段时间不活动后放置屏幕消息或图形动画。众所周知,Windows的此功能被威胁参与者滥用为持久性方法。这是因为...

    渗透攻击红队
  • 云端(服务器)车牌识别软件

    随着科技技术的发展,人工智能的技术越来越优化,软硬件的算法和技术要求也越来越高,其中,TH-OCR算法在各个行业中有极其重要的作用,OCR识别算法-车牌识别在各...

    ocr识别算法专家
  • css笔记 - animation学习笔记(二)

    from - to 等价于 0% - 100% 但是优先使用0% - 100%,因为浏览器兼容性还好点

    xing.org1^
  • 运维天地-服务器07-X86-PCServer系统信息获取

    大话IT架构
  • 精讲响应式WebClient第6篇-请求失败自动重试机制

    在上一篇我们为大家介绍了WebClient的异常处理方法,我们可以对指定的异常进行处理,也可以分类处理400-499、500-599状态码的HTTP异常。 我...

    字母哥博客

扫码关注云+社区

领取腾讯云代金券