案例:Nginx + Tomcat集群(负载均衡 动静分离)

目录

案例

案例环境

案例步骤

部署Tomcat服务器

部署Nginx服务器

实现负载均衡和读写分离

日志控制


案例

案例环境

操作系统

IP 地址

角色

CentOS

192.168.10.101

Nginx服务器(调度器)

CentOS

192.168.10.102

Tomcat服务器①

CentOS

192.168.10.103

Tomcat服务器②

Windows虚拟机或宿主机

浏览器测试

需求:静态请求交给Nginx解析,动态请求交给2个Tomcat服务器实现动静分离和负载均衡

以及日志的控制

假如有DDOS等网络攻击,服务器的连接数会被耗尽,需要获取真实客户端的地址

DDOS:分布式拒绝服务攻击


案例步骤

部署Tomcat服务器

因为102和103都是作为Tomcat服务器,部署的大致步骤相同,这里我们只开启102和103的会话同步

分别导入tomcat源码软件包到102和103主机

在102(Tomcat服务器①)操作

为了方便实验关闭防火墙和内核安全机制

tomcat是java开发的,这里我们需要在系统上安装java,确保开发环境一致

这里yum安装的java没有指定版本,安装的java版本是1.8的,可能仅适用于本次案例

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum -y install java

tomcat是解压即用的,不需要编译和安装。

移动到/usr/local/下方便使用

[root@localhost ~]# tar zxvf apache-tomcat-9.0.8.tar.gz
[root@localhost ~]# mv apache-tomcat-9.0.8 /usr/local/tomcat9

在根目录下创建一个用来存放网页文件的目录

在该目录下添加动态内容和静态内容,以达到更好的测试效果

[root@localhost webapps]# mkdir -p /web/webapp1
[root@localhost webapps]# cd /web/webapp1/
[root@localhost webapp1]# vim index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>JSP test1 page</title>   </head><body><% out.println("动态页面 1,http://www.test1.com");%></body><body><div>动态页面的图片 1</div><br><img src="logo.jpg"></body>
</html>

在103(Tomcat服务器②)操作

为了实现调度的效果,暂时关闭会话同步,来到103把其中的文本内容改一下

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<html>   
<head><title>JSP test2 page</title>
</head><body><% out.println("动态页面 2,http://www.test2.com");%></body> <body> <div>动态页面的图片 2</div><br><img src="logo.jpg"> </body> 
</html>

在102(Tomcat服务器①)操作

开启会话同步

打开tomcat配置文件

在第150行,Host单元中添加Context标签,指定网页文件的位置

[root@localhost tomcat9]# vim /usr/local/tomcat9/conf/server.xml
<Context docBase="/web/webapp1" path="" />

保存并退出,启动tomcat

[root@localhost ~]# /usr/local/tomcat9/bin/startup.sh

使用宿主机的浏览器测试,访问两个Web服务器的IP+端口号。结果如下,动态和静态的内容都显示出来了

图像、音频、视频之类的资源我们交给Nginx去解析,所以现在看不到图片是正常的


部署Nginx服务器

在101(Nginx服务器)操作

首先导入Nginx的源码软件包,准备安装

为了方便实验,关闭防火墙和内核安全机制

再安装Nginx依赖软件包,创建程序用户

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum -y install pcre-devel zlib-devel gcc*
[root@localhost ~]# useradd -M -s /sbin/nologin nginx

解压Nginx源码包,进入解压目录,运行configure脚本,指定安装参数,编译(make)、安装(make install

[root@localhost ~]# tar zxvf nginx-1.12.0.tar.gz
[root@localhost ~]# cd nginx-1.12.0
[root@localhost nginx-1.12.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx
[root@localhost nginx-1.12.0]# make && make install

优化调用命令的方式,创建软链接到命令目录下,然后使用nginx -t测试是否能正常调用命令

[root@localhost nginx-1.12.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@localhost ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

cd进入Nginx存放网页文件的目录,删除index.html文件中的内容,替换为下方代码块的内容

[root@localhost ~]# cd /usr/local/nginx/html/
[root@localhost html]# vim index.html
<body>
<h1>静态页面</h1>
</body>

因为我们的网页有中文,所以打开Nginx配置文件,在第39行指定字符集为utf8,然后保存并退出

[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
charset utf8;

启动nginx服务,结果如下图

[root@localhost ~]# nginx


实现负载均衡和读写分离

刚才说了在这个案例的环境中,图像等静态资源由Nginx负责解析,那么相应的要实现动静分离

cd进入Nginx存放网页文件的目录,在该目录下创建一个存放图片资源的子目录,进入该目录,把之前在tomcat指定的logo.jpg导入进该目录下

[root@localhost ~]# cd /usr/local/nginx/html/
[root@localhost html]# mkdir img
[root@localhost html]# cd img/

除此之外,还需要修改配置文件来实现动静分离

返回上一级目录知道nginx根目录,打开配置文件

[root@localhost img]# cd ..
[root@localhost html]# cd ..
[root@localhost nginx]# vim conf/nginx.conf

在第34行,添加upstream单元来配置负载均衡

再往下隔一个location单元,添加2个location单元实现读写分离(看下图)

下方代码表示nginx会将到达的请求按照权重分发到两台Tomcat服务器上,权重值(weight)越高,处理的请求越多

    upstream mytomcat {server 192.168.10.102:8080;server 192.168.10.103:8080;}# 省略...location ~ .*\.jsp$ {proxy_set_header HOST $host;proxy_pass http://mytomcat;}location ~ .*\.(jpg|png|gif)$ {root /usr/local/nginx/html/img;expires 30d;}

参数

说明

proxy_set_header HOST $host;

把原http请求中的Header中的Host字段放到转发的请求报文里,后端的web服务器利用这个host判断请求的是哪个虚拟主机

  • ~:不区分大小写
  • .*.\.jsp$:nginx匹配所有以.jsp结尾的请求,并将它们转发到定义的mytomcat后端服务器组中的某个Tomcat服务器处理。
  • .*\.(jpg|png|gif)$:这个配置用于处理静态图片文件。对于这些文件的请求,nginx会直接从指定的目录中提供,并设置响应头以便客户端进行缓存。
  • expires 30d:缓存时间为30天

由于修改了配置文件,需要重启服务使其生效,使用宿主机的浏览器访问192.168.10.101/index.jsp,此时就可以解析图片了,效果如下图

[root@localhost nginx]# nginx -s stop
[root@localhost nginx]# nginx


日志控制

在102(Tomcat服务器①)操作

如果此时查看Tomcat的访问日志,可以看到访问的IP都是代理服务器的IP

那么我们需要把这些源IP改为客户端的真实IP,以便Tomcat的访问日志能够详细记录

[root@localhost ~]# tail /usr/local/tomcat9/logs/localhost_access_log.2024-08-08.txt 
192.168.10.101 - - [08/Aug/2024:10:10:17 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.101 - - [08/Aug/2024:10:10:18 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.101 - - [08/Aug/2024:10:10:19 +0800] "GET /index.jsp HTTP/1.0" 200 215

在101(Nginx服务器)操作

打开配置文件,可以在location单元中设置对应参数来改变tomcat访问日志中的源IP

location ~ .*\.jsp$ {proxy_set_header HOST $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header Client-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass  http://myTomcat;}

参数

说明

proxy_set_header X-Real-IP $remote_addr;

使用$remote_addr变量获得用户的真实ip

如果有多个代理,$remote_addr一般设置在第一个代理服务器上。

当一个请求通过多个代理服务器时,用户的IP将会被代理服务器IP覆盖

proxy_set_header Client-IP $remote_addr;

获取客户端ip地址

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

从客户的真实ip为起点,穿过多层代理的proxy ,最终到达web服务器,都会记录下来。

所以在获取用户真实ip的时候,最后一个nginx配置此变量,用来获取客户端的ip地址

适合多层代理的场景

在102、103(Tomcat服务器①②)操作

打开Tomcat配置文件

在第162行添加代理服务器定义的变量

[root@localhost ~]# vim /usr/local/tomcat9/conf/server.xml
pattern="%{X-Real-IP}i %h %l %u %t &quot;%r&quot; %s %b" />

  • i:请求头

然后重启Tomcat服务

[root@localhost ~]# /usr/local/tomcat9/bin/shutdown.sh 
[root@localhost ~]# /usr/local/tomcat9/bin/startup.sh 

然后查看访问日志,就可以看到客户端的真实IP被加到开头了

[root@localhost ~]# tail /usr/local/tomcat9/logs/localhost_access_log.2024-08-08.txt 192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/396756.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp 对于scroll-view滑动和页面滑动的联动处理

需求 遇到一个需求 解决方案 这个时候可以做一个内页面滑动判断 <!-- scroll-y 做true或者false的判断是否滑动 --> <view class"u-menu-wrap" style"background-color: #fff;"><scroll-view :scroll-y"data.isGo" scroll-wit…

贷奇乐漏洞学习 --- 两个变态WAF绕过

代码分析 第一个WAF 代码 function dowith_sql($str) {$check preg_match(/select|insert|update|delete|\|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is, $str);if ($check) {echo "非法字符!";exit();}return $str;} 实现原理 这段PHP代码定义了一个…

uniapp切换同一个子组件时,钩子函数只进了一次

给子组件添加不同的 “key” 值&#xff0c;当 key 值改变时&#xff0c;Vue 会认为这是一个不同的组件&#xff0c;并重新创建它 props: ["L1Id"],// 方式1: 使用keycomputed: {// 切换子组件时,发现created、mounted等钩子函数只会进一次,或者用 keykey(){this.ref…

CSS技巧专栏:一日一例 19 -纯CSS实现超酷的水晶按钮特效

CSS技巧专栏:一日一例 19 -纯CSS实现超酷的水晶按钮特效 今天给大家分享一个纯CSS按钮水晶按钮,效果很赞,希望对大家有所帮助。 本例图片 案例分析 这个按钮看起来效果很赞,我们分析一下它由几个层组成: 1. 按钮本体:渐变层+按钮文字 2.用before伪元素实现高光层+内…

线程与多线程(二)

线程与多线程&#xff08;二&#xff09; 一、线程互斥1、相关概念 二、互斥锁1、介绍2、使用场景3、初始化&#xff08;1&#xff09;函数&#xff08;2&#xff09;概念 4、销毁&#xff08;1&#xff09;函数&#xff08;2&#xff09;概念 5、加锁&#xff08;1&#xff09…

SAM-Med2D 大模型学习笔记(续):训练自己数据集

1、前言、数据集介绍 SAM-Med2D大模型介绍参考上文&#xff1a;第三章&#xff1a;SAM-Med2D大模型复现-CSDN博客 本文将使用SAM-Med2D大模型训练自己的数据集 关于SAM-Med2D大模型官方demo数据集的介绍上文已经介绍过&#xff0c;这里简单回顾下 其中data_demo为数据集的目…

leetcode171. Excel 表列序号,进制转换

leetcode171. Excel 表列序号 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1: 输入: columnTitle “A” 输出: 1 示…

电商平台产品ID|CDN与预渲染|前端边缘计算

技术实现 都是通过ID拿到属性&#xff0c;进行预渲染html&#xff0c;通过 oss 分发出去 详情页这种基本都是通过 ssr 渲染出来&#xff0c;然后上缓存 CDN 分发到边缘节点来处理&#xff0c;具体逻辑可以参考 淘宝——EdgeRoutine边缘计算&#xff08;CDNServerless 边缘计算…

国内真正意义上的OpenAI,最强多模态大模型 MiniCPM-V 2.6 发布

最近这一两周看到不少互联网公司都已经开始秋招提前批了。不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解…

二叉树的最大深度

二叉树的最大深度 思路&#xff1a; 法一&#xff1a;深搜 也就是递归 要想清楚边界条件 好久没写深搜了 回忆下怎么写。 突然就悟了&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *rig…

2024年6月 青少年机器人技术等级考试理论综合试卷(二级)

202406 青少年等级考试机器人理论真题二级 第 1 题 如图&#xff0c;这是飞机起飞时的机翼示意图&#xff0c;下列说法正确的是&#xff1f;&#xff08; &#xff09; A&#xff1a;机翼上侧所受的气压为0 B&#xff1a;机翼受到向下的力的作用 C&#xff1a;机翼下侧所受…

基于sklearn的机器学习 — 支持向量机(SVM)

支持向量机&#xff08;SVM&#xff1a;support vector machine&#xff09;另一种功能强大、应用广泛的学习算法&#xff0c;可应用于分类、回归、密度估计、聚类等问题。SVM可以看作是感知器&#xff08;可被视为一种最简单形式的前馈神经网络&#xff0c;是一种二元线性分类…

C++ 特殊类设计

目录 0.前言 1.设计一个不能被拷贝的类 1.1C98实现 1.2C11实现 2.设计一个只能在堆上创建对象的类 3.设计一个只能在栈上创建对象的类 4.设计一个不能被继承的类 4.1C98实现 4.2C11实现 5.设计只能创建一个对象的类&#xff08;单例模式&#xff09; 5.1设计模式简介 5.2单例模…

Jupyter nbextensions安装与使用

这里写自定义目录标题 Jupyter nbextensions安装与使用安装7以下版本&#xff0c;安装插件包推荐使用的插件 Jupyter nbextensions安装与使用 目前&#xff0c;jupyter版本升级到了7以上版本&#xff0c;导致其界面非常难看&#xff0c;因此&#xff0c;为了重回之前的使用界面…

buuctf-crypto

前言 查找资料的时候,意外翻出之前刷的一些ctf题目,算是简单记录一下,当然因为常用typeo去写md文件,所以其中有很多当时记录的图片都失效了,可惜了 题目1:一眼就解密 ZmxhZ3tUSEVfRkxBR19PRl9USElTX1NUUklOR30 base64解密 flag:flag{THE_FLAG_OF_THIS_STRING} 题目2:MD5 …

全球化浪潮下的数据库革新:嘉里物流 TiDB 实践价值的设想

导读 本文来自 TiDB 社区武汉站——嘉里物流架构团队负责人肖飞老师的演讲《嘉里物流 & TiDB 在全球化业务场景中应用设想》。本次分享探讨了嘉里物流在全球化扩展中&#xff0c;将如何通过 TiDB 的强大功能应对海量数据挑战&#xff0c;优化技术架构&#xff0c;并提升决…

【Linux】详解自定义Shell管道 | 构建简易进程池

目录 续&#xff1a;通信 4 种情况 应用场景 1. 自定义 shell 管道 1. 包含头文件 2. 解析命令函数 详细步骤 3. 执行命令函数 4. 主函数 总结 2. 使用管道实现一个简易版本的进程池 代码结构 代码实现 channel.hpp tasks.hpp main.cc 子进程读取任务&#xff…

十九、虚拟机VMware Workstation(CentOSDebian)的安装

目录 &#x1f33b;&#x1f33b; 一、安装 VMware Workstation1.1 安装 VMware Workstation1.2 虚拟机上安装 CentOS1.3 虚拟机安装 Debian 二、配置Debian方便第三方工具远程连接2.1 配置debian2.2 安装远程SSH工具并连接 一、安装 VMware Workstation 官网下载 本地资源库…

你好! Git——企业级开发模型

企业级开发模型&#xff08;6&#xff09; 一、删除远程分支&#xff0c;git branch -a &#xff08;查看所有本地分支与远程分支&#xff09;还能看到已经删除的分支&#xff0c;怎么解决&#xff1f;二、企业级开发流程2.1 企业级开发流程2.2 系统开发环境 三、Git分支设计模…

RabbitMQ面试题汇总

RabbitMQ面试题 一、RabbitMQ基础1. 什么是RabbitMQ&#xff0c;它的基本架构是怎样的&#xff1f;2. RabbitMQ支持哪些协议&#xff1f;3. 说一下AMQP协议&#xff1f;4. 为什么要使用RabbitMQ&#xff1f;5. MQ的应用场景有哪些&#xff1f;6. 解耦、异步、削峰是什么&#x…