当前位置: 首页 > news >正文

案例: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

相关文章:

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

目录 案例 案例环境 案例步骤 部署Tomcat服务器 部署Nginx服务器 实现负载均衡和读写分离 日志控制 案例 案例环境 操作系统 IP 地址 角色 CentOS 192.168.10.101 Nginx服务器&#xff08;调度器&#xff09; CentOS 192.168.10.102 Tomcat服务器① CentOS 1…...

【密码学】密码协议的分类:②认证协议

密码协议的分类有很多种方式&#xff0c;这里我采取的是基于协议实现的目的来分类。可以将密码协议分成三类&#xff1a;认证协议、密钥建立协议、认证密钥建立协议。 一、认证协议是什么&#xff1f; 认证协议都在认证些什么东西呢&#xff1f;认证一般要认证三个东西&#x…...

异步编程(Promise详解)

目录 异步编程 回调函数 回调地狱 Promise 基本概念 Promise的特点 1.Promise是一种构造函数 2.Promise接收函数创建实例 3.Promise对象有三种状态 4.Promise状态转变不可逆 5.Promise 实例创建即执行 6.Promise可注册处理函数 7.Promise支持链式调用 Promise的静…...

DjangoORM注入分享

DjangoORM注入 简介 ​ 这篇文章中&#xff0c;分享一些关于django orm相关的技术积累和如果orm注入相关的安全问题讨论。 ​ 攻击效果同数据库注入 从Django-Orm开始 开发角度 ​ Django ORM&#xff08;Object-Relational Mapping&#xff09;是Django框架中用于处理数…...

【HBZ分享】Redis各种类型的数据结构应用场景

String(字符串类型) 计数器&#xff1a; incr / decr, 比如商品库存&#xff0c;业务号的发号器业务数据key-value缓存&#xff0c; 缓存结果数据&#xff0c;提高网站性能&#xff0c;缓解DB压力分布式session会话&#xff0c; 集群环境下存储token鉴权信息分布式锁&#xff…...

anaconda创建并且配置pytorch(完整版)

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 ** &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍** ❤️如遇文章付费&#xff0c;可先看看我公众号中是否发布免费文章❤️ &#x1f64f;笔者水平有限&#xff0c;欢迎各位大…...

高级java每日一道面试题-2024年8月10日-网络篇-你对跨域了解多少?

如果有遗漏,评论区告诉我进行补充 面试官: 你对跨域了解多少? 我回答: 跨域问题&#xff0c;即Cross-Origin Resource Sharing&#xff08;CORS&#xff09;&#xff0c;是现代Web开发中一个非常重要的概念&#xff0c;涉及到浏览器的安全策略——同源策略&#xff08;Same…...

AtCoder Beginner Contest 365 A~E

A.Leap Year&#xff08;思维&#xff09; 题意&#xff1a; 给你一个介于 1583 1583 1583和 2023 2023 2023之间的整数 Y Y Y。 求公历 Y Y Y年的天数。 在给定的范围内&#xff0c; Y Y Y年的天数如下&#xff1a; 如果 Y Y Y不是 4 4 4的倍数&#xff0c;则为 365 365 …...

多机部署, 负载均衡-LoadBalance

目录 1.负载均衡介绍 1.1问题描述 1.2什么是负载均衡 1.3负载均衡的一些实现 服务端负载均衡 客户端负载均衡 2.Spring Cloud LoadBalancer 2.1快速上手实现负载均衡 2.2负载均衡策略 自定义负载均衡策略 3.服务部署&#xff08;Linux&#xff09; 3.1服务构建打包…...

(回溯) LeetCode 78. 子集

原题链接 一. 题目描述 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集 &#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&…...

DQL数据查询语言(多表处理)—/—<7>

一、多表处理 当前有两个表&#xff0c;一个是学生表student&#xff0c;一个是分数表score student表字段名表示如下&#xff08;共1000条数据&#xff09;&#xff1a; score表字段表示如下&#xff08;共6000条数据&#xff09;&#xff1a; 1、求每个学生的总分 SELECT …...

力扣刷题总结

去年有段时间一直在刷题&#xff0c;进步神速&#xff0c;解决了以往刷完就忘的问题&#xff0c;这里总结下经验&#xff0c;给有需要的人参考下&#xff0c;核心观点就仨&#xff1a; 1. 打好数据结构与算法基础 2. 多刷题多练习 3. 形成自己的知识体系 下图是我梳理的知识体…...

BLDC ESC 无刷直流电子调速器驱动方式

BLDC ESC 无刷直流电子调速器驱动方式 1. 源由2. 驱动方法2.1 Trapezoidal 1202.2 Trapezoidal 1502.3 Sinusoidal 1802.4 Field-Orientated Control (FOC) 3. FOC&#xff08;Field-Oriented Control&#xff09;3.1 引入坐标系3.2 Clarke and Park变换Clarke 变换&#xff08…...

解决 IntelliJ IDEA 编译错误 “Groovyc: Internal groovyc error: code 1” 及 JVM 内存配置问题

在使用 IntelliJ IDEA 进行开发时&#xff0c;我们可能会遇到各种编译和运行错误&#xff0c;其中之一就是 Groovy 编译器错误&#xff08;Groovyc: Internal groovyc error: code 1&#xff09;或 JVM 内存不足错误。这类错误可能会影响开发效率&#xff0c;但通过调整 JVM 内…...

LeetCode.2940.找到Alice和Bob可以相遇的建筑

友情提示&#xff1a;这个方法并没有通过案例&#xff0c;只通过了944个案例&#xff08;很难受&#xff09;&#xff0c;超时了&#xff0c;但是想着还是分享出来吧 题目描述&#xff1a; 给你一个下标从 0 开始的正整数数组 heights &#xff0c;其中 heights[i] 表示第 i …...

OFD板式文件创建JAVA工具-EASYOFD 四、文字 Text

JAVA版本的OFD板式文件创建工具easyofd. 功能包含了图像、 图像、 文字、和模版页功能。同时也支持OFD文件的数字签名及验签&#xff0c;电子签章及验签。 本JAVA版本的easyofd使用原生方式创建板式文件&#xff0c;不依赖JAVA的SWT库。 项目地址&#xff1a;http://…...

【概念速通】李群 lie group

李群 lie group 概念速通 快速示例介绍&#xff1a;【引入】单位复数 (The unit complex numbers) 是李群 (lie group) 最简单的例子之一【进一步】SO(2): The 2D rotation matrices【Typical uses】SE(2): Pose of a robot in the plane Group & Lie Group 定义&#xff1…...

day_39

198. 打家劫舍 class Solution:def rob(self, nums: List[int]) -> int:if len(nums) 1:return nums[0]dp [0] * len(nums)dp[0], dp[1] nums[0], max(nums[0], nums[1])for i in range(2, len(nums)):dp[i] max(dp[i - 1], dp[i - 2] nums[i])return dp[len(nums) - …...

计算机系统层次结构

1.计算机系统的组成 计算机系统的组成硬件系统软件系统 2.计算机的硬件部分 2.1冯诺依曼机的结构特点&#xff1a; 图示&#xff1a; 1.五大部分由运算器(ALU)&#xff0c;控制器(CU)&#xff0c;存储器(主存辅存)&#xff0c;输入设备&#xff0c;输出设备五大部分组成2.指…...

java语言特点

Java语言是一种广泛使用的编程语言&#xff0c;它具有以下几个显著的特点&#xff1a; 面向对象&#xff1a;Java是一种纯面向对象的语言&#xff0c;它支持类的封装、继承和多态等特性。面向对象的设计使得Java程序更加模块化&#xff0c;易于维护和扩展。 平台无关性&#xf…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...