使用Nginx+Tomcat实现负载均衡的全过程


Posted in Servers onMay 30, 2022

Nginx + Tomcat 实现负载均衡

1. 环境

Linux version:  5.4.0-96-generic
OS Version:     ubuntu1~20.04
Architecture:   amd64
Nginx version:  nginx/1.18.0 (Ubuntu)
JVM Version:    11.0.15+10-Ubuntu-0ubuntu0.20.04.1
Tomcat Version: Apache Tomcat/9.0.63

2. 安装

2.1 安装 Nginx

在命令行输入:

sudo apt-get install nginx

测试命令:

sudo nginx -t

窗口显示:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

在浏览器输入服务器 ip:

使用Nginx+Tomcat实现负载均衡的全过程

2.2 安装 Java

安装 jdk:

sudo apt-get -y install openjdk-11-jdk

查看版本:

java --version

输出如下:

openjdk 11.0.15 2022-04-19
OpenJDK Runtime Environment (build 11.0.15+10-Ubuntu-0ubuntu0.20.04.1)
OpenJDK 64-Bit Server VM (build 11.0.15+10-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing)

安装成功。

查看 Java 的安装位置:

update-alternatives --config java

输出如下:

There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-11-openjdk-amd64/bin/java

将 $JAVA_HOME 添加到环境变量:

sudo vim $HOME/.bashrc
shift+G

在行尾添加:

export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$PATH:$JAVA_HOME

退出 vim ,激活环境变量:

source $HOME/.bashrc

验证环境变量:

echo $JAVA_HOME

输出如下,激活成功。

/usr/lib/jvm/java-11-openjdk-amd64

2.3 安装 Tomcat

官网下载的 Tomcat 9.0.63,注意需为 Core/tar.gz(pgp, sha512) 版本,或 点此下载 ,将文件上传到服务器中的路径 /usr/local 下,输入下列命令解压:

cd /usr/local && tar -zxvf apache-tomcat-9.0.63.tar.gz

配置环境变量,打开 Tomcat 启动脚本:

cd apache-tomcat-9.0.63 && vim bin/startup.sh
shift+G

在语句 exec "$PRGDIR"/"$EXECUTABLE" start "$@" 的上一行插入下列语句:

JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
JRE_HOME=$JAVA_HOME/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME
CLASSPATH=.:$JRE_HOME/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
TOMCAT_HOME=/usr/local/apache-tomcat-9.0.63

保存并退出。

开放服务器的 8080 端口:

firewall-cmd --zone=public --add-port=8080/tcp --permanent

重启防火墙

systemctl restart firewalld.service

去云服务器管理控制台添加安全组:

使用Nginx+Tomcat实现负载均衡的全过程

运行:

./bin/shutdown.sh && rm -rf logs/catalina.out && ./bin/startup.sh ; tail -f logs/catalina.out

输出应该如下所示:

使用Nginx+Tomcat实现负载均衡的全过程

在浏览器访问 $ip:8080,显示:

使用Nginx+Tomcat实现负载均衡的全过程

说明你配置成功。

3. 部署

3.1 Tomcat 服务器部署

本实验需要使用 3 个端口,分别使用 8001,8082,8083,在腾讯云控制台开放端口后,在 shell 中手动开放端口并重启防火墙:

firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --zone=public --add-port=8082/tcp --permanent
firewall-cmd --zone=public --add-port=8083/tcp --permanent
systemctl restart firewalld.service

注意去腾讯云开启你的安全组

我们使用 Tomcat 自带的 3 个 Web 项目来实现不同的端口访问不同的应用,假设你完全按照上文的方式操作,那么此时你的 Tomcat 为 /usr/local/apache-tomcat-9.0.63,根据根路径打开服务器的配置文件:

cd /usr/local/apache-tomcat-9.0.63/conf && vim server.xml

删除掉原代码,换成以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
     <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
     <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
     <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
     <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
     <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
     <GlobalNamingResources>
     <Resource name="UserDatabase" auth="Container"
               type="org.apache.catalina.UserDatabase"
               description="User database that can be updated and saved"
               factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
               pathname="conf/tomcat-users.xml" />
     </GlobalNamingResources>

     <Service name="Catalina">
          <Connector port="8081" protocol="HTTP/1.1"
                    connectionTimeout="20000"
                    redirectPort="8443" />
               <Engine name="Catalina" defaultHost="localhost">
                    <Realm className="org.apache.catalina.realm.LockOutRealm">
                    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                         resourceName="UserDatabase"/>
                    </Realm>
                    <Host name="localhost"  appBase="webapps"
                         unpackWARs="true" autoDeploy="true">
                         <Context path="" docBase="ROOT" reloadable="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" />
                    </Host>
               </Engine>
     </Service>

     <Service name="Catalina2">
          <Connector port="8082" protocol="HTTP/1.1"
                    connectionTimeout="20000"
                    redirectPort="8443" />
               <Engine name="Catalina2" defaultHost="localhost">
                    <Realm className="org.apache.catalina.realm.LockOutRealm">
                    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                         resourceName="UserDatabase"/>
                    </Realm>
                    <Host name="localhost"  appBase="webapps"
                         unpackWARs="true" autoDeploy="true">
                         <Context path="" docBase="examples" reloadable="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" />
                    </Host>
               </Engine>
     </Service>

     <Service name="Catalina3">
          <Connector port="8083" protocol="HTTP/1.1"
                    connectionTimeout="20000"
                    redirectPort="8443" />
               <Engine name="Catalina3" defaultHost="localhost">
                    <Realm className="org.apache.catalina.realm.LockOutRealm">
                    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                         resourceName="UserDatabase"/>
                    </Realm>
                    <Host name="localhost"  appBase="webapps"
                         unpackWARs="true" autoDeploy="true">
                         <Context path="" docBase="examples/websocket" reloadable="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" />
                    </Host>
               </Engine>
     </Service>
</Server>

这样,通过 $ip:8081$ip:8082$ip:8083 分别访问就可以得到不同的服务端。

8083 端口的资源不完整,因为 Tomcat 默认只提供了 2 个有效的 app,第三个端口会返回一个 404 页面,某种程度上它也是一个应用。

3.2 Nginx 反向代理

编辑 nginx.conf 配置文件:

vim /etc/nginx/nginx.conf

将下列语句插入到模块 http 的末尾:

upstream tomcat_server {
    server 101.42.117.143:8081;
    server 101.42.117.143:8082;
    server 101.42.117.143:8083;
}

server {
    listen 80;
    server_name 101.42.117.143;

    location / {
        proxy_pass http://tomcat_server;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

启动或重启 nginx:

nginx 或 nginx -s reload

这样,可以直接访问 80 端口,或 $ip 后将其代理到后端的 3 台服务器上。

nginx 默认采用轮询策略。

4. 负载均衡

4.1 轮询

轮询策略 nginx.conf 的配置如下:

upstream tomcat_server {
    server 101.42.117.143:8081 weight=1;
    server 101.42.117.143:8082 weight=1;
    server 101.42.117.143:8083 weight=1;
}

server {
    listen 80;
    server_name 101.42.117.143;

    location / {
        proxy_pass http://tomcat_server;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

重启 nginx:

nginx -s reload

使用 postman 频繁访问,页面出现的频率是 ABC ABC ABC ABC

4.2 加权轮询

加权轮询策略 nginx.conf 的配置如下:

upstream tomcat_server {
    server 101.42.117.143:8081 weight=1;
    server 101.42.117.143:8082 weight=3;
    server 101.42.117.143:8083 weight=5;
}

server {
    listen 80;
    server_name 101.42.117.143;

    location / {
        proxy_pass http://tomcat_server;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

重启 nginx:

nginx -s reload

使用 postman 频繁访问,页面出现的频率是 CBCACBCBC CBCACBCBC

该算法称为提案者轮换选择算法,每一轮都会将被选中的对象减去总权重值,每一轮都会将各结点的权重值加上固定的预设权重值,这是一个公平的轮换算法,可以防止权重过大的结点持续占据资源。过程如下:

初始权重 加权 选择 选中者减去权重和
0 0 0 1 3 5 C 1 3 -4
1 3 -4 2 6 1 B 2 -3 1
2 -3 1 3 0 6 C 3 0 -3
3 0 -3 4 3 2 A -5 3 2
-5 3 2 -4 6 7 C -4 6 -2
-4 6 -2 -3 9 3 B -3 0 3
-3 0 3 -2 3 8 C -2 3 -1
-2 3 -1 -1 6 4 B -1 -3 4
-1 -3 4 0 0 9 C 0 0 0
0 0 0 1 3 5 C 1 3 -4
1 3 -4 2 6 1 B 2 -3 1
2 -3 1 3 0 6 C 3 0 -3

4.2 IP Hash

IP Hash 策略 nginx.conf 的配置如下:

upstream tomcat_server {
    server 101.42.117.143:8081;
    server 101.42.117.143:8082;
    server 101.42.117.143:8083;
    ip_hash;
}

server {
    listen 80;
    server_name 101.42.117.143;

    location / {
        proxy_pass http://tomcat_server;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

重启 nginx:

nginx -s reload

它会将主机的 $ip 哈希映射到一个随机的固定值,然后对 3 取模得到响应的端口序号;

使用主机 1 的 postman 频繁访问,页面出现的频率是 AAAAAA;

使用主机 2 的 postman 频繁访问,页面出现的频率是 BBBBBB。

总结

到此这篇关于使用Nginx+Tomcat实现负载均衡的文章就介绍到这了!


Tags in this post...

Servers 相关文章推荐
Nginx优化服务之网页压缩的实现方法
Mar 31 Servers
nginx里的rewrite跳转的实现
Mar 31 Servers
win10安装配置nginx的过程
Mar 31 Servers
Windows下使用Nginx+Tomcat做负载均衡的完整步骤
Mar 31 Servers
关于Nginx中虚拟主机的一些冷门知识小结
Mar 03 Servers
Consul在linux环境的集群部署
Apr 08 Servers
docker compose 部署 golang 的 Athens 私有代理问题
Apr 28 Servers
详解如何使用Nginx解决跨域问题
May 06 Servers
永中文档在线转换预览基于nginx配置部署方案
Jun 10 Servers
windows server2008 开启端口的实现方法
Jun 25 Servers
讨论nginx location 顺序问题
May 30 #Servers
项目中Nginx多级代理是如何获取客户端的真实IP地址
May 30 #Servers
nginx rewrite功能使用场景分析
May 30 #Servers
Nginx静态压缩和代码压缩提高访问速度详解
May 30 #Servers
Nginx 配置 HTTPS的详细过程
May 30 #Servers
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
May 25 #Servers
聊聊配置 Nginx 访问与错误日志的问题
May 25 #Servers
You might like
php 多个submit提交表单 处理方法
2009/07/07 PHP
php采用ajax数据提交post与post常见方法总结
2014/11/10 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
js一组验证函数
2008/12/20 Javascript
javascript学习笔记(七) js函数介绍
2012/06/19 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
原生JS绑定滑轮滚动事件兼容常见浏览器
2014/06/30 Javascript
jQuery表单验证功能实例
2015/08/28 Javascript
Java Mybatis框架入门基础教程
2015/09/21 Javascript
轻松学习Javascript闭包函数
2015/12/15 Javascript
vue自定义指令实现v-tap插件
2016/11/03 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
微信小程序图片横向左右滑动案例
2017/05/19 Javascript
angularjs项目的页面跳转如何实现(5种方法)
2017/05/25 Javascript
js实现从左向右滑动式轮播图效果
2017/07/07 Javascript
vue.js异步上传文件前后端实现代码
2017/08/22 Javascript
vue任意关系组件通信与跨组件监听状态vue-communication
2020/10/18 Javascript
一篇文章让你搞懂JavaScript 原型和原型链
2020/11/23 Javascript
Python中的anydbm模版和shelve模版使用指南
2015/07/09 Python
Django URL传递参数的方法总结
2016/08/28 Python
python+selenium开发环境搭建图文教程
2017/08/11 Python
Python遍历numpy数组的实例
2018/04/04 Python
python操作excel的包(openpyxl、xlsxwriter)
2018/06/11 Python
django DRF图片路径问题的解决方法
2018/09/10 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
python文件转为exe文件的方法及用法详解
2019/07/08 Python
python 计算积分图和haar特征的实例代码
2019/11/20 Python
用python求一重积分和二重积分的例子
2019/12/06 Python
如何用Anaconda搭建虚拟环境并创建Django项目
2020/08/02 Python
世界上最具创新性的增强型知名运动品牌:Proviz
2018/04/03 全球购物
大学活动总结格式
2014/04/29 职场文书
投标承诺函格式
2015/01/21 职场文书
入党介绍人意见范文
2015/06/01 职场文书
2021年最新用于图像处理的Python库总结
2021/06/15 Python
python playwrigh框架入门安装使用
2022/07/23 Python