基于Tomcat + Nginx搭建负载均衡的服务器

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

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

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

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

动静分离

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

反向代理

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


image.png

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

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

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

负载均衡

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


image.png

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

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

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不一致的问题。这个问题不是我们这篇文章讨论的重点,感兴趣的读者可以自行查询资料。

Nginx下载安装

Nginx官方下载地址
下载安装比较简单,直接解压即可运行,具体操作查看下面文章
Nginx安装与命令(Linux)
Nginx 从安装到配置,看这篇教程就够了

验证是否安装成功

nginx  -V
image.png

如果需要任何地方都可以执行,直接在系统环境上添加安装目录即可


image.png

验证成功

image.png

查看nginx进程

tasklist /fi  "imagename eq nginx.exe"
image.png

杀掉nginx进程

taskkill  /f  /pid 11044 /pid 7092
image.png

需要管理员权限,用管理员权限打开CMD,然后再次输入上面的命令


image.png

启动Nginx

start nginx.exe

注意需要先进入安装目录,在执行start命令

cd C:\MyProgram\nginx-1.19.4
image.png

访问localhost:80 测试 ngnix 是否正常运行

返回 nginx 欢迎页表示正常运行


image.png

window下Nginx启动bat脚本

对于常用的命令,可以写成脚本的方式,这样会更加方便。

@echo off
rem 提供Windows下nginx的启动,重启,关闭功能
 
echo ==================begin========================
 
cls 
::ngxin 所在的盘符
set NGINX_PATH=C:
 
::nginx 所在目录
set NGINX_DIR=C:\MyProgram\nginx-1.19.4\
color 0a 
TITLE Nginx 管理程序增强版
 
CLS 
 
echo. 
echo. ** Nginx 管理程序  *** 
echo. 
 
:MENU 
 
echo. ***** nginx 进程list ****** 
::tasklist|findstr /i "nginx.exe"
tasklist /fi "imagename eq nginx.exe"
 
echo. 
 
    if ERRORLEVEL 1 (
        echo nginx.exe不存在
    ) else (
        echo nginx.exe存在
    )
 
echo. 
::*************************************************************************************************************
echo. 
    echo.  [1] 启动Nginx  
    echo.  [2] 关闭Nginx  
    echo.  [3] 重启Nginx 
    echo.  [4] 刷新控制台  
    echo.  [5] 重新加载Nginx配置文件
    echo.  [6] 检查测试nginx配置文件
    echo.  [7] 查看nginx version
    echo.  [0] 退 出 
echo. 
 
echo.请输入选择的序号:
set /p ID=
    IF "%id%"=="1" GOTO start 
    IF "%id%"=="2" GOTO stop 
    IF "%id%"=="3" GOTO restart 
    IF "%id%"=="4" GOTO MENU
    IF "%id%"=="5" GOTO reloadConf 
    IF "%id%"=="6" GOTO checkConf 
    IF "%id%"=="7" GOTO showVersion 
    IF "%id%"=="0" EXIT
PAUSE 
 
::*************************************************************************************************************
::启动
:start 
    call :startNginx
    GOTO MENU
 
::停止
:stop 
    call :shutdownNginx
    GOTO MENU
 
::重启
:restart 
    call :shutdownNginx
    call :startNginx
    GOTO MENU
 
::检查测试配置文件
:checkConf 
    call :checkConfNginx
    GOTO MENU
 
::重新加载Nginx配置文件
:reloadConf 
    call :checkConfNginx
    call :reloadConfNginx
    GOTO MENU
    
::显示nginx版本
:showVersion 
    call :showVersionNginx
    GOTO MENU   
    
    
::*************************************************************************************
::底层
::*************************************************************************************
:shutdownNginx
    echo. 
    echo.关闭Nginx...... 
    taskkill /F /IM nginx.exe > nul
    echo.OK,关闭所有nginx 进程
    goto :eof
 
:startNginx
    echo. 
    echo.启动Nginx...... 
    IF NOT EXIST "%NGINX_DIR%nginx.exe" (
        echo "%NGINX_DIR%nginx.exe"不存在
        goto :eof
     )
 
    %NGINX_PATH% 
    cd "%NGINX_DIR%" 
 
    IF EXIST "%NGINX_DIR%nginx.exe" (
        echo "start '' nginx.exe"
        start "" nginx.exe
    )
    echo.OK
    goto :eof
    
 
:checkConfNginx
    echo. 
    echo.检查测试 nginx 配置文件...... 
    IF NOT EXIST "%NGINX_DIR%nginx.exe" (
        echo "%NGINX_DIR%nginx.exe"不存在
        goto :eof
     )
 
    %NGINX_PATH% 
    cd "%NGINX_DIR%" 
    nginx -t -c conf/nginx.conf
 
    goto :eof
    
::重新加载 nginx 配置文件
:reloadConfNginx
    echo. 
    echo.重新加载 nginx 配置文件...... 
    IF NOT EXIST "%NGINX_DIR%nginx.exe" (
        echo "%NGINX_DIR%nginx.exe"不存在
        goto :eof
     )
 
    %NGINX_PATH% 
    cd "%NGINX_DIR%" 
    nginx -s reload
 
    goto :eof
    
::显示nginx版本
:showVersionNginx
    echo. 
    %NGINX_PATH% 
    cd "%NGINX_DIR%" 
    nginx -V
    goto :eof
image.png

安装Tomcat

基本的安装运行请查看下方文章
SpringBootServletInitializer (Tomcat)启动spring boot项目

Tomcat多实例部署

Tomcat 中比较重要的概念(通常也是两个系统变量)CATALINA_HOMECATALINA_BASE

  • CATALINA_HOME:即指向Tomcat安装路径的系统变量(安装目录)
  • CATALINA_BASE:即指向活跃配置路径的系统变量(工作目录)

通过设置这两个变量,就可以将Tomcat的安装目录和工作目录分离,从而实现Tomcat多实例的部署。

复制tomcate

复制tomcate安装文件夹,本例在本地模拟三台tomcat服务器(一个home和两个base)和一台nginx服务器


image.png

三个 Tomcat,它们的作用分别是:

目录 作用
tomcat-home 作为 CATALINA_HOME,即只需要保留 bin 和 lib 两个文件夹
tomcat-8080 作为 CATALINA_BASE,需要保留除了 bin 和 lib 之外的其他文件夹,使用 8080 端口
tomcat-9090 同 tomcat-8080,使用 9090 端口

Tomcat 的基本目录结构,以及对应的作用:

目录 简介
bin 存放脚本文件,例如比较常用的启动和关闭脚本 startup.sh、shutdown.sh 等
conf 存放配置文件,如server.xml它是 tomcat 的主要配置文件
lib Tomcat 运行需要的依赖包
log 存放日志文件
temp 存放运行时产生的临时文件
webapps web 应用的默认目录,通常war包会部署到这里
work 主要存放由JSP文件生成的servlet(Java文件以及最终编译生成的class文件)

Tomcat官方文档上说明了 CATALINA_HOME 路径下需要包含 bin 和 lib 目录,也就是两个支持 tomcat 运行的目录,而 CATALINA_BASE 可以包含所有目录,但是 bin 和 lib 不是必须的,缺省时会使用 CATALINA_HOME 中的 bin 和 lib。
因此我们就可以使用一个 CATALINA_HOME 和多个 CATALINA_BASE 部署多个实例,这样的好处是便于管理和升级 Tomcat。

按照上面的要求删除三个tomcat目录下无用的文件夹:
tomcat-home 保留 bin 和 lib 目录,删除其他目录
omcat-8080 保留除了 bin 和 lib 之外的其他文件夹,使用 8080 端口
tomcat-9090 保留除了 bin 和 lib 之外的其他文件夹,使用 9090 端口

修改 Tomcat 配置文件

image.png

这一步主要是修改conf目录下的 server.xml 中端口的配置,在 server.xml 中配置了四个监听端口,分别是:

  • Server port(默认8005): 监听关闭 tomcat 的 shutdown 命令
  • Connector port(默认8080):监听 http 请求
  • AJP Connector port(默认8009):监听 AJP 请求
  • redirectPort(默认8443):重定向端口,出现在Connector配置中,如果该Connector仅支持非SSL的普通http请求,那么该端口会把https的请求转发到这个Redirect Port指定的端口

了解了监听的各个端口的作用之后就可以开始修改 server.xml 了,如果不使用 AJP 请求,那么我们只需要保证多实例中的 Server port 和 Connector port 不同即可

# tomcat-8080 保持默认配置即可
# 修改 tomcat-9090 的配置,修改后的 /tomcat-9090/conf/server.xml 内容如下:
...

...

...
# tomcat-8080 保持默认配置即可
# 修改 tomcat-9090 的配置,修改后的 /tomcat-9090/conf/server.xml 内容如下:
...

...

...

大概有3个地方休要修改


image.png

编写脚本

前面的准备工作做完之后就可以启动 Tomcat 了,但是现在只有 tomcat-home/bin 目录下有 startup.sh 和 shutdown.sh,而我们要启动的 8080 和 9090 两个实例,因此我们就需要编写一段脚本,修改 CATALINA_BASE 来达到分别操作两个实例的目的:

启动脚本start.sh:

#!/bin/sh
CUR_DIR=`dirname $BASH_SOURCE`
export CATALINA_BASE=`readlink -f $CUR_DIR`
export CATALINA_HOME="/usr/local/tomcat-home"

if [ -f $CATALINA_HOME/bin/startup.sh ]; then
        $CATALINA_HOME/bin/startup.sh
else
        echo "$CATALINA_HOME/bin/startup.sh not exist"
fi

windows

@REM 启动 tomcat-8080
echo 启动 tomcat-8080
set "CATALINA_BASE=%cd%"
set "CATALINA_HOME=C:\Program Files\Apache Software Foundation\tomcat-home"
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
call "%EXECUTABLE%" start
pause

停止脚本stop.sh:

#!/bin/sh
CUR_DIR=`dirname $BASH_SOURCE`
export CATALINA_BASE=`readlink -f $CUR_DIR`
export CATALINA_HOME="/usr/local/tomcat-home"

if [ -f $CATALINA_HOME/bin/shutdown.sh ]; then
       $CATALINA_HOME/bin/shutdown.sh
else
       echo "$CATALINA_HOME/bin/shutdown.sh not exist"
fi

windows

@REM 关闭 tomcat-8080
echo 关闭 tomcat-8080
cd C:\Program Files\Apache Software Foundation\tomcat-home\bin
call shutdown.bat
pause

当然关闭和开启也可以使用前面提及的tasklist taskkill等

然后将这两个脚本文件放在 tomcat-8080 和 tomcat-9090 的根目录下:

[root@localhost tomcat-8080]# ls
conf     logs    RELEASE-NOTES  start.sh  temp     work
LICENSE  NOTICE  RUNNING.txt    stop.sh   webapps

测试两个 Tomcat 是否同时正常运行

tomcat-8080/webapps/ROOTtomcat-9090/webapps/ROOT 目录下分别新建一个 index.html 文件,内容分别为 “8080” 和 “9090” 便于我们区分。

完成之后使用 start.sh 启动两个实例

image.png

直接浏览器输入localhost:9090 和localhost:8080


image.png

我们还可以使用 curl 访问来测试:

# 访问 9090 端口,获取到 9090 的数据
[root@localhost tomcat-9090]# curl localhost:9090

9090

# 访问 8080 端口,获取到 8080 的数据 [root@localhost tomcat-8080]# curl localhost:8080

8080

Nginx 与 Tomcat 进行负载均衡

打开nginx安装目录,找到conf目录下的nginx.conf

# 进入 ngnix 配置文件的目录
# 默认配置文件是 ngnix.conf
http {
    include       /etc/nginx/mime.types;
    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  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_types   text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;

    include /etc/nginx/conf.d/*.conf;

 # Tomcat 服务器集群
   upstream app_server {
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:9080 weight=1;
   }
...

server {
     listen 80;

     server_name  api.xxx.com;

     location / {
            ...
            # 请求转发给 Tomcat 集群处理
            proxy_pass http://app_server;
     }

  }

nginx -s reload

不同的系统配置文件位置不一样


image.png
image.png

你可能感兴趣的:(基于Tomcat + Nginx搭建负载均衡的服务器)