使用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 相关文章推荐
destoon在各个服务器下设置URL Rewrite(伪静态)的方法
Jun 21 Servers
Nginx tp3.2.3 404问题解决方案
Mar 31 Servers
Nginx URL重写rewrite机制原理及使用实例
Apr 01 Servers
教你快速开启Apache SkyWalking的自监控
Apr 25 Servers
Nginx源码编译安装过程记录
Nov 17 Servers
Nginx stream 配置代理(Nginx TCP/UDP 负载均衡)
Nov 17 Servers
Kubernetes部署实例并配置Deployment、网络映射、副本集
Apr 01 Servers
Windows Server 2019 域控制器安装图文教程
Apr 28 Servers
阿里云服务器部署RabbitMQ集群的详细教程
Jun 01 Servers
windows server 2016 域环境搭建的方法步骤(图文)
Jun 25 Servers
Windows7下FTP搭建图文教程
Aug 05 Servers
解决ubuntu安装软件时,status-code=409报错的问题
Dec 24 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代码
2007/03/08 PHP
zend framework多模块多布局配置
2011/02/26 PHP
PHP中替换换行符的几种方法小结
2012/10/15 PHP
php和javascript之间变量的传递实现代码
2012/12/19 PHP
PHP+redis实现的购物车单例类示例
2019/02/02 PHP
laravel 实现上传图片到本地和前台访问示例
2019/10/21 PHP
JS 密码强度验证(兼容IE,火狐,谷歌)
2010/03/15 Javascript
JavaScript prototype属性使用说明
2010/05/13 Javascript
jQuery UI 应用不同Theme的办法
2010/09/12 Javascript
读jQuery之十一 添加事件核心方法
2011/07/31 Javascript
JQuery中$.ajax()方法参数详解及应用
2013/12/12 Javascript
2014年最火的Node.JS后端框架推荐
2014/10/27 Javascript
JavaScript实现瀑布流布局
2020/06/28 Javascript
解决微信浏览器Javascript无法使用window.location.reload()刷新页面
2016/06/21 Javascript
js实现淡入淡出轮播切换功能
2017/01/13 Javascript
详解支持Angular 2的表格控件
2017/01/19 Javascript
JQuery页面随滚动条动态加载效果的简单实现(推荐)
2017/02/08 Javascript
Vuex之理解Store的用法
2017/04/19 Javascript
原生js封装添加class,删除class的实例
2017/11/06 Javascript
详解React中传入组件的props改变时更新组件的几种实现方法
2018/09/13 Javascript
electron中使用bootstrap的示例代码
2018/11/06 Javascript
Vue通过配置WebSocket并实现群聊功能
2019/12/31 Javascript
[07:48]DOTA2上海特级锦标赛主赛事首日RECAP
2016/03/04 DOTA
分享Pycharm中一些不为人知的技巧
2018/04/03 Python
python制作图片缩略图
2019/04/30 Python
Python求均值,方差,标准差的实例
2019/06/29 Python
如何实现更换Jupyter Notebook内核Python版本
2020/05/18 Python
python os模块常用的29种方法使用详解
2020/06/02 Python
基于Keras 循环训练模型跑数据时内存泄漏的解决方式
2020/06/11 Python
python上下文管理的使用场景实例讲解
2021/03/03 Python
expedia比利时:预订航班+酒店并省钱
2018/07/13 全球购物
周鸿祎:教你写创业计划书
2013/12/30 职场文书
《数星星的孩子》教学反思
2014/04/11 职场文书
2016师德师风学习心得体会
2016/01/12 职场文书
大学学生会主席竞选稿怎么写?
2019/08/19 职场文书
Python文件的操作示例的详细讲解
2021/04/08 Python