Web与Nginx网站服务(改)
文章目录
- 第一章 Web与Nginx网站服务
- 一、Web 概念
- 1.1 Web 的基本概念
- 1.2 B/S 架构模型
- 1.3 Web 请求与响应过程
- 1.4 静态资源与动态资源
- 1.5 Web 的发展阶段
- 1.6 实验:搭建最小 Web 服务
- 1.7 小结
- 二、HTTP 与 HTTPS 协议
- 2.1 http与https区别
- 2.2 HTTPS 握手流程
- 2.3 HTTP状态码
- 2.3.1 HTTP 状态码概览
- 2.3.2 常用状态码详解
- 三、Nginx 概念
- 3.1 Nginx 介绍
- 3.2 简述Nginx和Apache的差异
- 3.3 Nginx 进程结构
- 四、Nginx安装
- 五、Nginx 配置
- 5.1 全局配置
- 5.2 I/O 事件配置
- 5.3 HTTP 配置
- 5.3 Web 服务的监听配置
- 5.4 其他配置(扩展)
- 六、nginx 虚拟主机
- 6.1 访问状态统计配置
- 6.1.1 查看已安装的所有模块
- 6.1.2 修改 nginx.conf 配置文件
- 6.1.3 重启服务,访问测试
- 6.2 基于授权的访问控制
- 6.2.1 生成用户密码认证文件
- 6.2.2 修改主配置文件相对应目录,添加认证配置项
- 6.2.3 重启服务,访问测试
- 6.3 基于客户端的访问控制
- 6.4 基于域名的 Nginx 虚拟主机
- 6.4.1 为虚拟主机提供域名解析
- 6.4.2 为虚拟主机准备网页文档
- 6.4.3 修改nginx配置文件
- 6.5 基于IP 的 Nginx 虚拟主机
- 6.5.1 配置server1
- 6.5.2 配置server 2
- 6.6 基于端口的 Nginx 虚拟主机
- 6.6.1 基于端口1
- 6.6.2 基于端口2
- 6.6.3 重启服务,测试访问
- 七. 反向代理
- 7.1 原理
- 实验配置
- 八、负载均衡
- 8.1 基本原理
- 8.2 常见负载均衡策略
- 8.2.1 轮询(Round Robin)
- 8.2.2 最少连接数(Least Connections)
- 8.2.3 IP 哈希(IP Hash):
- 8.2.4 加权轮询(Weighted Round Robin):
- 8.2.5 最少时间算法(Least Time):
- 8.2.6 一致性哈希(Consistent Hashing): url_hash
- 8.3 配置示例
- 8.4 高可用 & 健康检查
- 8.5 总结
- 九、后端 tomcat
- 9.1 Tomcat 的本质
- 9.2 运行原理
- 9.3 主要配置文件
- 9.4 调用应用接口
- 9.5 调用数据库接口
- 9.6 部署 tomcat
- 9.6.1 关闭防火墙 与增强功能
- 9.6.2 配置环境
- 9.6.3 安装 tomcat
- 9.7 总结
- 十、部署反向代理与负载均衡
- 10.1 规划部署负载均衡和反向代理
- 10.2 部署Nginx 负载均衡器
- 10.3 部署后端2台Tomcat 应用服务器
- 10.4 动静分离配置
- 10.4.1 Tomcat1 server 配置
- 10.4.2 Tomcat2 server 配置
- 10.4.2 Nginx server 配置
- 总结
第一章 Web与Nginx网站服务
一、Web 概念
1.1 Web 的基本概念
Web(World Wide Web,万维网)是运行在互联网之上的一个 超文本信息系统,它依赖于 HTTP/HTTPS 协议 实现浏览器与服务器之间的交互。
特点
- 分布式:资源分布在世界各地的服务器上。
- 跨平台:只要有浏览器,就能访问资源。
- 无状态:每次 HTTP 请求都是独立的,服务器不会记住客户端状态(除非使用 Cookie/Session)。
1.2 B/S 架构模型
Web 采用 B/S 架构(Browser/Server):
- Browser(浏览器):用户的入口,发送请求、渲染页面。
- Server(服务器):接收请求,返回所需资源或动态内容。
图 1-1:B/S 架构示意图
用户浏览器 ──> Web服务器(Nginx/Apache)│└─> 应用服务器(PHP/Python/Java)│└─> 数据库(MySQL/Redis)
1.3 Web 请求与响应过程
一次完整的 Web 访问过程包括以下步骤:
- 输入 URL:用户在浏览器输入
http://www.example.com
。 - DNS 解析:浏览器将域名解析为 IP 地址。
- 建立连接:浏览器与 Web 服务器建立 TCP 连接(3 次握手)。
- 发送请求:浏览器发起 HTTP 请求(GET/POST)。
- 服务器处理:
- Web 服务器处理静态资源请求
- 动态请求转发到应用服务器(如 Tomcat、Django)
- 应用服务器可能再查询数据库
- 返回响应:Web 服务器将结果打包成 HTTP 响应报文返回浏览器。
- 渲染页面:浏览器解析 HTML、加载 CSS/JS、渲染最终页面。
图 1-2:Web 请求-响应流程
浏览器 ----> Web服务器 ----> 应用服务器 ----> 数据库<---- <---- <----
1.4 静态资源与动态资源
-
静态资源:不需要服务器额外处理,直接返回即可。
- HTML、CSS、图片、视频、JS 文件
- 优点:速度快,压力小
-
动态资源:需要服务器端代码计算生成,再返回客户端。
-
PHP 脚本、Python Flask/Django、Java Servlet、Ruby
-
优点:个性化内容,支持交互
-
图 1-3 静态与动态资源对比图
静态资源:用户请求 → Web服务器直接返回
动态资源:用户请求 → Web服务器 → 应用服务器运行代码 → 返回结果
1.5 Web 的发展阶段
- Web 1.0(只读):静态页面为主,用户只能浏览。
- Web 2.0(交互式):用户可生成内容,AJAX(前端) 技术普及。
- Web 3.0(智能化):语义网、区块链、去中心化概念兴起。
1.6 实验:搭建最小 Web 服务
注意后面安装nginx之后再创建一个静态页面
实验目标
体验一次最简单的 Web 请求与响应过程 Wireshark 并且抓包。
实验步骤
-
创建一个静态页面:
<!-- index.html --> <html> <head><title>My First Web</title></head> <body> <h1>Hello Web!</h1> <p>This is my first web page.</p> </body> </html>HTML 文档结构 <!-- index.html --> <html(标签)> <head(头部)><title>My First Web</title></head> <body(主体)> <h1(一级标题)>Hello Web!</h1> <p(段落标签)>This is my first web page.</p> </body> </html>
1.7 小结
- Web 是基于 B/S 架构 的信息交互方式。
- 核心是 请求-响应模型,通过 HTTP/HTTPS 协议传输数据。
- Web 可提供 静态资源 和 动态资源。
二、HTTP 与 HTTPS 协议
2.1 http与https区别
- HTTP:明文传输,不安全。
- HTTPS:在 HTTP 上加入 SSL/TLS 加密,防止中间人攻击。
2.2 HTTPS 握手流程
TLS 握手过程:客户端发起请求 → 服务端返回证书 → 双方协商加密算法 → 建立安全通道。
客户端 Hello → 服务端 Hello + 证书 → 客户端验证 → 加密通信
TLS 握手过程(建立安全通道)
流程:
- 客户端 Hello
- 浏览器发起请求,告诉服务器自己支持哪些加密算法。
-
服务端 Hello + 证书
- 网站返回 SSL 证书(证明身份),选择一种加密算法。
-
客户端验证证书
- 浏览器检查证书是否可信(CA 颁发、没过期、域名匹配)。
-
协商密钥
- 双方生成一个临时密钥,用于对称加密后续通信。
-
加密通信开始
- 后续 HTTP 数据都通过加密通道传输。
2.3 HTTP状态码
2.3.1 HTTP 状态码概览
HTTP 状态码都是 三位数字,按首位分为五类:
类型 | 范围 | 含义 | 大白话理解 |
---|---|---|---|
1xx | 100–199 | 信息性状态码 | “我收到了请求,还在处理中” |
2xx | 200–299 | 成功 | “请求成功,服务器给你东西了” |
3xx | 300–399 | 重定向 | “你要的东西搬家了,去新地址找” |
4xx | 400–499 | 客户端错误 | “你请求有问题(URL错、权限不够)” |
5xx | 500–599 | 服务器错误 | “服务器出问题,暂时拿不到东西” |
2.3.2 常用状态码详解
1. 成功
状态码 | 含义 | 类比 |
---|---|---|
200 OK | 请求成功 | “东西拿到了” |
201 Created | 创建成功 | “你提交的表单/资源已创建” |
204 No Content | 成功,但没有内容 | “操作成功,但没有额外东西返回” |
2. 重定向
状态码 | 含义 | 类比 |
---|---|---|
301 Moved Permanently | 永久搬家 | “这个页面永久换地址了” |
302 Found | 临时搬家 | “暂时换地址,下一次还用旧地址” |
304 Not Modified | 内容未改 | “东西没变,你可以用缓存” |
3. 客户端错误
状态码 | 含义 | 类比 |
---|---|---|
400 Bad Request | 请求格式错 | “你写的请求我看不懂” |
401 Unauthorized | 未认证 | “先登录,再访问” |
403 Forbidden | 禁止访问 | “你没权限” |
404 Not Found | 找不到页面 | “东西搬走或根本没这东西” |
4. 服务器错误
状态码 | 含义 | 类比 |
---|---|---|
500 Internal Server Error | 服务器内部出错 | “服务器崩了” |
502 Bad Gateway | 网关错误 | “我去找别的服务器,结果那边挂了” |
503 Service Unavailable | 服务不可用 | “服务器忙不过来了,稍后再试” |
504 Gateway Timeout | 网关超时 | “找别的服务器太慢,超时了” |
生活中的 HTTP 状态码类比
场景 | 状态码 | 对应情况 |
---|---|---|
打开网页正常 | 200 | 成功拿到网页 |
点链接页面搬家 | 301/302 | 浏览器自动跳到新地址 |
输入错网址 | 404 | “没找到这个页面” |
登录需要权限 | 401 | “先登录才能看” |
网站挂了 | 500 | “服务器出问题了” |
HTTP 状态码就是服务器对你请求的“回话信息”,告诉你请求成功没、东西搬没搬、你有没有权限、或者服务器出问题了。
三、Nginx 概念
3.1 Nginx 介绍
Nginx (“engine x”) 是一个高性能的 HTTP 和反向代理服务器。Nginx 是由 Igor Sysoev 为俄
罗斯访问点开量第二的 Rambler.ru 站发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。其将源代码以类 BSD 许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻
名。2011 年 6 月 1 日,Nginx 1.0.4 发布。
Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,
单台物理服务器可支持30 000~50 000个并发请求。并在一个 BSD-like 协议下发行。由俄罗斯的程序设计师 Igor Sysoev 所开发,供俄国大型的入口网站及搜索引擎 Rambler(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用 Nginx 网站用户有:百度 BWS、新浪、网易、腾讯、等
Nginx 是一个 高性能 Web 服务器,它可以做很多事情:
- 静态资源服务:可以直接把网页、图片、视频这些文件发给用户。
- 反向代理:用户访问你的服务器,Nginx 可以帮你把请求转发到后端真正处理请求的服务器。
- 负载均衡:当有很多后端服务器时,Nginx 可以智能分配流量,让每台服务器都不忙不过来。
- 高并发处理:用事件驱动的方式处理请求,能同时处理成千上万的用户请求,而不会占用太多资源。
优势:
- 轻量级,占用内存小
- 支持百万级并发访问
- 稳定可靠,开源且社区活跃
nginx 官网
RamBler:http://www.rambler.ru/
nginx: http://nginx.org/Mainline version 主线版本
Stable version稳定版本
Legacy versions 老版本,遗产版本
旧版本下载:http://mirrors.sohu.com/nginx/
Nginx 中文参考地址: http://www.nginx.cn/doc/
3.2 简述Nginx和Apache的差异
- Nginx是一个甚于事件的Web服务器,Apache是一个基于流程的服务器;
- Nginx避免子进程的概念,Apache是基于子进程的;
- Nginx在内存消耗和连接方面更好,Apache在内存消耗和连接方面一般;
- Nginx的性能和可伸缩性不依赖于硬件,Apache依赖于CPU和内存等硬件;
- Nginx支持热部署,Apache不支持热部署;
- Nginx对于静态文件处理具有更高效率,Apache相对一般;
- Nginx在反向代理场景具有明显优势,Apache相对一般。
3.3 Nginx 进程结构
web请求处理机制
-
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。
-
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
工作进程(worker process)的功能:
所有 Worker 进程都是平等的
实际处理:网络请求,由 Worker 进程处理
Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源,
增加上下文切换的损耗
接受处理客户的请求
将请求依次送入各个功能模块进行处理
I/O调用,获取响应数据
与后端服务器通信,接收后端服务器的处理结果
缓存数据,访问缓存索引,查询和调用缓存数据
发送请求结果,响应客户的请求
接收主程序指令,比如重启、升级和退出等
四、Nginx安装
看我nginx安装博客:
nginx安装和平滑升级
五、Nginx 配置
认识Nginx服务的主配置文件 nginx.conf
vim /usr/local/nginx/conf/nginx.conf
5.1 全局配置
#user nobody; user nginx #运行用户,若编译时未指定则默认为 nobody
worker_processes 4; #工作进程数量,可配置成服务器内核数 * 2,如果网站访问量不大,一般设为1就够用了
#error_log logs/error.log; #错误日志文件的位置
#pid logs/nginx.pid; #PID 文件的位置
5.2 I/O 事件配置
events {use epoll; #使用 epoll 模型,2.6及以上版本的系统内核,建议使用epoll模型以提高性能worker_connections 4096; #每个进程处理 4096 个连接
}
#如提高每个进程的连接数还需执行“ulimit -n 65535”命令临时修改本地每个进程可以同时打开的最大文件数。
#在Linux平台上,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。#可使用ulimit -a命令查看系统允许当前用户进程打开的文件数限制。
/etc/security/limits.conf#epoll是Linux内核为处理大批句柄而作改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著的减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。若工作进程数为 8,每个进程处理 4 096 个连接,则允许 Nginx 正常提供服务的连接数
已超过 3 万个(4 096×8=32 768),当然具体还要看服务器硬件、网络带宽等物理条件的性
能表现。
5.3 HTTP 配置
使用“http { }”界定标记,包括访问日志、HTTP 端口、网页目录、默认字符集、连接保
持,以及后面要讲到的虚拟 Web 主机、PHP 解析等一系列设置,其中大部分配置语句都包
含在子界定标记“server { }”内
http {##文件扩展名与文件类型映射表include mime.types; 。fyl.jpg html image##默认文件类型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 logs/access.log main; 访问网站的日志##支持文件发送(下载)sendfile on;##此选项允许或禁止使用socket的TCP_CORK的选项(发送数据包前先缓存数据),此选项仅在使用sendfile的时候使用#tcp_nopush on;##连接保持超时时间,单位是秒#keepalive_timeout 0;keepalive_timeout 65;##gzip模块设置,设置是否开启gzip压缩输出#gzip on;
5.3 Web 服务的监听配置
##Web 服务的监听配置server {##监听地址及端口listen 80; ##站点域名,可以有多个,用空格隔开server_name www.fyl.com;##网页的默认字符集charset utf-8;##根目录配置location / {##网站根目录的位置/usr/local/nginx/htmlroot html;##默认首页文件名index index.html index.php;}location /zjl {##网站根目录的位置/usr/local/nginx/htmlroot /usr/local/nginx/html/zjl;##默认首页文件名index index.html index.php;}##内部错误的反馈页面error_page 500 502 503 504 /50x.html;##错误页面配置location = /50x.html {root html;}}}
5.4 其他配置(扩展)
日志格式设定
$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
$remote_user:用来记录客户端用户名称;
$time_local: 用来记录访问时间与时区;
$request: 用来记录请求的url与http协议;
$status: 用来记录请求状态;成功是200,
$body_bytes_sent :记录发送给客户端文件主体内容大小;
$http_referer:用来记录从哪个页面链接访问过来的;
$http_user_agent:记录客户浏览器的相关信息;
通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
====================================================================================
location常见配置指令,root、alias、proxy_pass
root(根路径配置):root /var/www/html
请求www.benet.com/test/1.html,会返回文件/var/www/html/test/1.htmlalias(别名配置):alias /var/www/html
请求www.benet.com/test/1.html,会返回文件/var/www/html/1.htmlproxy_pass(反向代理配置)
六、nginx 虚拟主机
6.1 访问状态统计配置
6.1.1 查看已安装的所有模块
先使用命令/usr/local/nginx/sbin/nginx -V 查看已安装的 Nginx 是否包含 HTTP_STUB_STATUS 模块
cat /opt/nginx-1.20.2/auto/options | grep YES #可查看 nginx 已安装的所有模块
6.1.2 修改 nginx.conf 配置文件
修改 nginx.conf 配置文件,指定访问位置并添加 stub_status 配置
cd /usr/local/nginx/conf
cp nginx.conf nginx.conf.bak
vim /usr/local/nginx/conf/nginx.conf
......
http {
......server {listen 80;server_name www.benet.com;charset utf-8;location / {root html;index index.html index.php;}##添加 stub_status 配置##location /status { #访问位置为/status www.benet.com/statusstub_status on; #打开状态统计功能access_log off; #关闭此位置的日志记录}}
}
6.1.3 重启服务,访问测试
systemctl restart nginx浏览器访问 http://192.168.10.21/status
Active connections :表示当前的活动连接数;
server accepts handled requests :表示已经处理的连接信息,三个数字依次表示已处理的连接数、成功的TCP握手次数、 已处理的请求数。可 curl -s http://192.168.10.21/status 结合 awk与if 语句进行性能监控。
6.2 基于授权的访问控制
6.2.1 生成用户密码认证文件
yum install -y httpd-tools
htpasswd -c /usr/local/nginx/passwd.db zhangsan
chown nginx /usr/local/nginx/passwd.db
chmod 400 /usr/local/nginx/passwd.db
6.2.2 修改主配置文件相对应目录,添加认证配置项
vim /usr/local/nginx/conf/nginx.conf
......server {location / {......##添加认证配置##auth_basic "secret"; #设置密码提示框文字信息auth_basic_user_file /usr/local/nginx/passwd.db;}}
6.2.3 重启服务,访问测试
nginx -t
systemctl restart nginx浏览器访问 http://192.168.10.21
6.3 基于客户端的访问控制
访问控制规则如下:
deny IP/IP 段:拒绝某个 IP 或 IP 段的客户端访问。
allow IP/IP 段:允许某个 IP 或 IP 段的客户端访问。
规则从上往下执行,如匹配则停止,不再往下匹配。vim /usr/local/nginx/conf/nginx.conf
......server {location / {......##添加控制规则##allow 192.168.10.20; #允许访问的客户端 IPdeny all; #拒绝其它IP客户端访问}}systemctl restart nginx
6.4 基于域名的 Nginx 虚拟主机
6.4.1 为虚拟主机提供域名解析
echo "192.168.10.21 www.yjs.com www.benet.com" >> /etc/hosts
6.4.2 为虚拟主机准备网页文档
mkdir -p /usr/local/nginx/html/benet
mkdir -p /usr/local/nginx/html/yjs
echo "<h1>www.yjs.com</h1>" > /usr/local/nginx/html/yjs/index.html
echo "<h1>www.benet.com</h1>" > /usr/local/nginx/html/benet/index.html
6.4.3 修改nginx配置文件
vim /usr/local/nginx/conf/nginx.conf
......
http {
......server {listen 80;server_name www.yjs.com; #设置域名www.yjs.comcharset utf-8;access_log logs/www.yjs.access.log; #设置日志名location / {root /usr/local/nginx/html/yjs; #设置www.yjs.com 的工作目录index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}}server {listen 80;server_name www.benet.com; #设置域名www.benet.comcharset utf-8;access_log logs/www.benet.access.log; location / {root /usr/local/nginx/html/benet;index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}}
}
4.重启服务,访问测试
systemctl restart nginx浏览器访问
http://www.yjs.com
http://www.benet.com
6.5 基于IP 的 Nginx 虚拟主机
6.5.1 配置server1
ifconfig ens33:0 192.168.10.40 netmask 255.255.255.0 创建 一个ens36 或者37的网卡 192.168.10.40vim /usr/local/nginx/conf/nginx.conf
......
http {
......server {listen 192.168.10.22:80; #设置监听地址192.168.10.22server_name www.yjs.com;charset utf-8;access_log logs/www.yjs.access.log; location / {root /usr/local/nginx/html/yjs;index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}1}
6.5.2 配置server 2
server {listen 192.168.10.40:80; #设置监听地址192.168.10.40server_name www.benet.com;charset utf-8;access_log logs/www.benet.access.log; location / {root /usr/local/nginx/html/benet;index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}} }systemctl restart nginx浏览器访问http://192.168.10.22http://192.168.10.40
6.6 基于端口的 Nginx 虚拟主机
6.6.1 基于端口1
vim /usr/local/nginx/conf/nginx.conf
......
http {
......server {listen 192.168.10.22:8080; #设置监听 8080 端口server_name www.yjs.com;charset utf-8;access_log logs/www.yjs.access.log; location / {root /var/www/html/yjs;index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}}
6.6.2 基于端口2
server {listen 192.168.10.22:8888; #设置监听 8888 端口server_name www.benet.com;charset utf-8;access_log logs/www.benet.access.log; location / {root /var/www/html/benet;index index.html index.php;}error_page 500 502 503 504 /50x.html;location = 50x.html{root html;}}
}
6.6.3 重启服务,测试访问
systemctl restart nginx浏览器访问
http://192.168.10.21:8080
http://192.168.10.21:8888
七. 反向代理
7.1 原理
- 用户请求先到 Nginx,再由 Nginx 把请求转发给后端的应用服务器(比如 Tomcat、Node.js、Spring Boot)。
- Nginx 在这里就像“中转站”,客户端只知道自己连的是 Nginx,不知道真正提供服务的是哪台后端。
图示:
客户端 ---> Nginx ---> 多台后端服务器
实验配置
编辑 nginx.conf
,在 server
块里添加:
server {listen 80;server_name localhost;location / {proxy_pass http://127.0.0.1:8080; # 把请求转发到后端 8080 端口proxy_set_header Host $host; # 保留原始的 Host 头proxy_set_header X-Real-IP $remote_addr; # 获取客户端真实 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}
保存配置后,执行:
nginx -s reload
现在访问 http://localhost/
,实际会由 Nginx 转发到 http://127.0.0.1:8080/
。
八、负载均衡
Nginx 的负载均衡是它最常用的功能之一,可以将客户端请求分发到多台后端服务器,提高系统的并发能力、可用性和稳定性。
8.1 基本原理
Nginx 作为反向代理服务器,接收来自客户端的请求,然后根据配置的负载均衡策略,将请求转发到后端的多个应用服务器(upstream server)。
好处:
- 提高性能:分担单台服务器压力
- 高可用性:某台服务器宕机,Nginx 自动转发到其他正常的节点
- 可扩展性:轻松添加或移除后端节点
8.2 常见负载均衡策略
以下是 Nginx 支持的几种常见的分流算法:
8.2.1 轮询(Round Robin)
轮询算法是 Nginx 的默认分流算法。它按顺序将请求依次分配给每一台后端服务器,直到最后一台服务器,然后重新从第一台服务器开始。这种方法简单且均匀地分配了流量。
数据流向:每个请求依次被分配到下一个服务器。假设有三台服务器(Server A、Server B、Server C),第一个请求被分配到 Server A,第二个请求分配到 Server B,第三个请求分配到 Server C,第四个请求又回到 Server A,依此类推。
特点:请求均匀分布,无视服务器的当前负载和响应时间。
配置示例:
upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
8.2.2 最少连接数(Least Connections)
最少连接数算法将请求分配给当前活动连接数最少的服务器。这种算法适用于请求处理时间不均匀的情况,可以有效平衡服务器的负载。
数据流向:每个请求被分配到当前连接数最少的服务器。例如,Server A 有 2 个连接,Server B 有 5 个连接,新的请求会被分配到 Server A。
特点:动态均衡负载,适用于请求处理时间不一的场景。
配置示例:
upstream backend {least_conn;server backend1.example.com;server backend2.example.com;server backend3.example.com;}
8.2.3 IP 哈希(IP Hash):
IP 哈希算法通过计算客户端 IP 地址的哈希值,将请求始终分配给同一台服务器。适用于需要将特定客户端的请求固定在同一台服务器上的场景。
数据流向:每个客户端的 IP 地址被哈希计算,然后根据哈希值将请求固定分配到某一台服务器。假设客户端 X 的哈希值指向 Server A,客户端 Y 的哈希值指向 Server B,则无论多少次请求,X 的请求总是流向 Server A,Y 的请求总是流向 Server B。
特点:同一个客户端总是被分配到同一台服务器,有助于会话保持。
配置示例:
upstream backend {ip_hash;server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
8.2.4 加权轮询(Weighted Round Robin):
加权轮询算法允许为每台服务器设置权重,权重越大的服务器将会获得更多的请求。适用于服务器性能不均衡的情况。
数据流向:根据服务器设置的权重值分配请求。假设 Server A 权重为 3,Server B 权重为 1,则 4 个请求中,3 个会被分配到 Server A,1 个会被分配到 Server B。
特点:高权重服务器接收更多的请求,适用于服务器性能差异较大的场景。
配置示例:
upstream backend {server backend1.example.com weight=3;server backend2.example.com weight=1;server backend3.example.com weight=2;
}
8.2.5 最少时间算法(Least Time):
最少时间算法基于请求的响应时间,将请求分配给响应时间最短的服务器。这种算法在 Nginx 1.15.3 及以后版本中可用,适用于需要最大化响应速度的场景。
数据流向:每个请求分配到响应时间最短或平均连接时间最短的服务器。假设 Server A 的响应时间较快,Server B 较慢,则新的请求更可能流向 Server A。
特点:进一步优化了最少连接算法,适用于高负载环境下的动态负载均衡。
4. 配置示例:upstream backend {least_time header;server backend1.example.com;server backend2.example.com;server backend3.example.com;}
8.2.6 一致性哈希(Consistent Hashing): url_hash
一致性哈希算法可以保证当集群中某台服务器故障时,只有部分请求会重新分配到其他服务器,而不是全部重新分配。这在缓存等场景中非常有用。
数据流向:根据请求的某个特定参数(如 URL、Cookie 或其他 Header),进行哈希计算,将请求分配到哈希值对应的服务器。假设 Server A 和 Server B,参数 “foo” 的哈希值指向 Server A,参数 “bar” 的哈希值指向 Server B,则 “foo” 请求总是流向 Server A,“bar” 请求总是流向 Server B。
特点:适应服务器节点变动,减少请求的重新分配,适合缓存敏感的场景。
配置示例(需要第三方模块如 `ngx_http_upstream_hash_module`):upstream backend {hash $request_uri consistent;server backend1.example.com;server backend2.example.com;server backend3.example.com;}
8.3 配置示例
基础轮询
http {upstream backend {server 192.168.0.101;server 192.168.0.102;}server {listen 80;location / {proxy_pass http://backend;}}
}
带权重和故障转移
upstream backend {server 192.168.0.101 weight=3 max_fails=3 fail_timeout=30s;server 192.168.0.102 weight=1 max_fails=3 fail_timeout=30s;
}
max_fails
表示允许失败的次数,fail_timeout
表示多久后重试。
8.4 高可用 & 健康检查
Nginx 开源版自带的是被动健康检查(只有当请求失败才标记服务器不可用),如果需要主动健康检查(定时探测后端状态),可以:
- 使用 Nginx Plus 的健康检查功能
- 或用开源模块 nginx_upstream_check_module
8.5 总结
Nginx 负载均衡就是通过反向代理把客户端请求按策略分配到多台后端服务器,实现高性能、高可用、可扩展的服务访问。
九、后端 tomcat
9.1 Tomcat 的本质
Tomcat 本质上是一个 Servlet 容器,也可以称作一个轻量级 Web 应用服务器(Web Server + Servlet Container)。
它的主要职责是:
- 接收 HTTP 请求(内置了一个简单的 HTTP 服务器)
- 将请求分发给对应的 Web 应用(基于 URL 映射)
- 执行 Servlet / JSP 并生成响应
- 返回 HTTP 响应给客户端
换句话说,Tomcat 是一个 Java Web 应用运行环境,可以托管基于 Servlet、JSP、Spring MVC、Spring Boot(war 部署)等的应用。
9.2 运行原理
Tomcat 的核心工作流程可简化为以下几个步骤:
- 启动
- 加载
server.xml
配置,启动各个Connector
(监听端口,如 8080) - 初始化
Service
、Engine
、Host
、Context
组件 - 创建并初始化
Servlet 容器
- 加载
- 接收请求
Connector
监听 HTTP 请求(基于 NIO/线程池)- 请求被封装为
Request
对象
- 请求分发
Mapper
根据 URL → 找到对应的Context
(即某个 Web 应用)- 找到对应的
Wrapper
(某个 Servlet)
- 执行 Servlet
- Tomcat 调用 Servlet 的
service()
方法 - Servlet 处理请求,可能访问数据库或调用其他 API
- 返回
Response
对象
- Tomcat 调用 Servlet 的
- 响应客户端
- Tomcat 将
Response
转换为 HTTP 响应报文 - 通过 Socket 返回给客户端浏览器
- Tomcat 将
9.3 主要配置文件
Tomcat 的核心配置文件主要有:
文件 | 作用 |
---|---|
conf/server.xml | Tomcat 的主配置文件,定义 Connector (端口、协议)、Engine 、Host 、Context 等 |
conf/web.xml | 全局的 Web 应用默认配置(比如默认的 MIME 映射、默认 Servlet) |
context.xml | 定义 Web 应用级别的配置,如数据源(JNDI)、Session 配置 |
tomcat-users.xml | 用户、角色和安全相关配置,用于 Manager App、Admin Console 登录 |
应用内的 WEB-INF/web.xml | 每个 Web 应用自己的 Servlet、Filter、Listener 配置 |
9.4 调用应用接口
当你的应用部署到 Tomcat 中时,Tomcat 会:
- 在启动时加载你的
web.xml
或注解(如@WebServlet
) - 创建并初始化 Servlet
- 当有 HTTP 请求时,将请求参数封装成
HttpServletRequest
- 调用你的 Servlet 或框架(如 Spring MVC 的 DispatcherServlet)
- 你的业务代码处理完成后返回
HttpServletResponse
也就是说,Tomcat 并不关心业务逻辑,只负责把请求转给你的代码执行。
9.5 调用数据库接口
Tomcat 提供了 JNDI 数据源 支持,让应用能复用数据库连接池:
-
配置数据源
在context.xml
或某个应用的META-INF/context.xml
:<Resource name="jdbc/MyDB" auth="Container"type="javax.sql.DataSource"maxActive="20"maxIdle="10"maxWait="10000"username="root"password="123456"driverClassName="com.mysql.cj.jdbc.Driver"url="jdbc:mysql://localhost:3306/test"/>
-
应用代码获取数据源
Context initCtx = new InitialContext(); DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/MyDB"); Connection conn = ds.getConnection(); // 执行 SQL ...
这样做的好处:
- 连接池由 Tomcat 管理,性能更好
- 数据源配置与应用解耦,方便运维
9.6 部署 tomcat
9.6.1 关闭防火墙 与增强功能
systemctl stop firewalld
setenforce 0
9.6.2 配置环境
vim /etc/profile 这是配置JDK 现在系统基本自带openJDK
=======================================================================================
首先下载 然后再 上传 并且解压(解压完之后配置环境变量即可)
tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/ export JAVA_HOME=/usr/local1/jdk1.8.0_91
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
=======================================================================================
source /etc/profile #刷新 具体查看有没有安装 开发环境[root@ky17 local]# java -version
openjdk version "1.8.0_181" #显示JDK1.8
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
9.6.3 安装 tomcat
#先下载安装包 然后再 上传
tar zxvf apache-tomcat-8.5.16.tar.gz
#修改服务名字
mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat#启动tomcat
/usr/local/tomcat/bin/shutdown.sh # 关闭
/usr/local/tomcat/bin/startup.sh # 启动
#查看端口
netstat -ntap | grep 8080
9.7 总结
- 本质:Tomcat 是 Java Web 应用的运行容器,负责接收 HTTP 请求、调用 Servlet、返回响应
- 原理:Connector 监听请求 → Mapper 分发 → Servlet 执行 → 返回响应
- 配置文件:server.xml(端口、Host)、web.xml(全局)、context.xml(数据源)、tomcat-users.xml(用户)
- 应用接口调用:Tomcat 把请求交给你的 Servlet/框架
- 数据库接口调用:通过 JNDI 数据源或自己管理 JDBC 连接
十、部署反向代理与负载均衡
10.1 规划部署负载均衡和反向代理
- Nginx 服务器:192.168.10.22:80
- Tomcat服务器1:192.168.10.17:8080
- Tomcat服务器2:192.168.10.17:8081
10.2 部署Nginx 负载均衡器
注意:如果前面部署过 这边就不需要再操作了
systemctl stop firewalld
setenforce 0yum -y install pcre-cdevel zlib-devel openssl-devel gc gcc-c++ makeuseradd -M -s /sbin/nologin nginxcd /opt
tar zxvf nginx-1.20.2.tar.gz -C /opt/cd nginx-1.20.2/
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-file-aio \ #启用文件修改支持
--with-http_stub_status_module \ #启用状态统计
--with-http_gzip_static_module \ #启用 gzip静态压缩
--with-http_flv_module \ #启用 flv模块,提供对 flv 视频的伪流支持
--with-http_ssl_module #启用 SSL模块,提供SSL加密功能
--with-stream #启用 stream模块,提供4层调度----------------------------------------------------------------------------------------------------------
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-stream --with-http_ssl_modulemake && make installln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/vim /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecrReload=/bin/kill -s HUP $MAINPID
ExecrStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.targetchmod 754 /lib/systemd/system/nginx.service
systemctl start nginx.service
systemctl enable nginx.service
10.3 部署后端2台Tomcat 应用服务器
systemctl stop firewalld
setenforce 0tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/vim /etc/profile
export JAVA_HOME=/usr/local1/jdk1.8.0_91
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATHsource /etc/profiletar zxvf apache-tomcat-8.5.16.tar.gzmv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.shnetstat -ntap | grep 8080第二台直接拷贝即可
cp -r /usr/local/tomcat /usr/local/tomcat1
10.4 动静分离配置
10.4.1 Tomcat1 server 配置
mkdir /usr/local/tomcat/webapps/test
vim /usr/local/tomcat/webapps/test/index.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test1 page</title> #指定为 test1 页面
</head>
<body>
<% out.println("动态页面 1,http://www.test1.com");%>
</body>
</html>vim /usr/local/tomcat/conf/server.xml
#由于主机名 name 配置都为 localhost,需要删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"><Context docBase="/usr/local/tomcat/webapps/test" path="" reloadable="true"></Context>
</Host>/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.sh
10.4.2 Tomcat2 server 配置
mkdir /usr/local/tomcat/tomcat1/webapps/test /usr/local/tomcat/tomcat2/webapps/testvim /usr/local/tomcat/tomcat1/webapps/test/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test2 page</title> #指定为 test2 页面
</head>
<body>
<% out.println("动态页面 2,http://www.test2.com");%>
</body>
</html>vim /usr/local/tomcat/tomcat1/conf/server.xml
#删除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"><Context docBase="/usr/local/tomcat/tomcat1/webapps/test" path="" reloadable="true" />
</Host>/usr/local/tomcat/tomcat1/bin/shutdown.sh
/usr/local/tomcat/tomcat1/bin/startup.sh
10.4.2 Nginx server 配置
#准备静态页面和静态图片
echo '<html><body><h1>这是静态页面</h1></body></html>' > /usr/local/nginx/html/index.html
mkdir /usr/local/nginx/html/img
cp /root/game.jpg /usr/local/nginx/html/imgvim /usr/local/nginx/conf/nginx.conf
......
http {
......#gzip on;#配置负载均衡的服务器列表,weight参数表示权重,权重越高,被分配到的概率越大upstream tomcat_server {server 192.168.10.23:8080 weight=1;server 192.168.10.22:8080 weight=1;server 192.168.10.22:8081 weight=1;}server {listen 80;server_name www.kgc.com;charset utf-8;#access_log logs/host.access.log main;#配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理location ~ .*\.jsp$ {proxy_pass http://tomcat_server;
#设置后端的Web服务器可以获取远程客户端的真实IP
##设定后端的Web服务器接收到的请求访问的主机名(域名或IP、端口),默认HOST的值为proxy_pass指令设置的主机名。如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来在反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。proxy_set_header HOST $host;
##把$remote_addr赋值给X-Real-IP,来获取源IPproxy_set_header X-Real-IP $remote_addr;
##在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}#配置Nginx处理静态图片请求location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {root /usr/local/nginx/html/img;expires 10d;}location / {root html;index index.html index.htm;}
......}
......
}4.测试效果
测试静态页面效果
浏览器访问 http://192.168.10.22/
浏览器访问 http://192.168.10.22/game.jpg测试负载均衡效果,不断刷新浏览器测试
浏览器访问 http://192.168.10.22/index.jspnginx/html/img
cp /root/game.jpg /usr/local/nginx/html/imgvim /usr/local/nginx/conf/nginx.confhttp {#gzip on;#配置负载均衡的服务器列表,weight参数表示权重,权重越高,被分配到的概率越大upstream tomcat_server {server 192.168.10.23:8080 weight=1;server 192.168.10.22:8080 weight=1;server 192.168.10.22:8081 weight=1;}server {listen 80;server_name www.kgc.com;charset utf-8;#access_log logs/host.access.log main;#配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理location ~ .*\.jsp$ {proxy_pass http://tomcat_server;
#设置后端的Web服务器可以获取远程客户端的真实IP
##设定后端的Web服务器接收到的请求访问的主机名(域名或IP、端口),默认HOST的值为proxy_pass指令设置的主机名。如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来在反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。proxy_set_header HOST $host;
##把$remote_addr赋值给X-Real-IP,来获取源IPproxy_set_header X-Real-IP $remote_addr;
##在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}#配置Nginx处理静态图片请求location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {root /usr/local/nginx/html/img;expires 10d;}location / {root html;index index.html index.htm;}}
}4.测试效果
测试静态页面效果
浏览器访问 http://192.168.10.22/
浏览器访问 http://192.168.10.22/game.jpg测试负载均衡效果,不断刷新浏览器测试
浏览器访问 http://192.168.10.22/index.jsp
总结
本文围绕 “Web 基础与 Nginx 网站服务” 展开,从理论到实战形成完整闭环:先梳理 Web 的 B/S 架构、HTTP/HTTPS 协议逻辑与资源分类,明确 Web 服务的底层交互原理;再聚焦 Nginx 的核心优势(高并发、轻量、多功能)、进程结构与 I/O 模型,对比其与 Apache 的差异;随后落地到 Nginx 的实战配置,涵盖基础配置体系、虚拟主机(域名 / IP / 端口)、负载均衡(轮询 / 加权 / IP 哈希)、访问控制等关键场景;最后补充 Nginx 与 Tomcat 的协同方案,通过动静分离与集群部署,实现高可用 Web 服务。
全文内容兼顾原理理解与实操指导,核心知识点清晰聚焦,可直接支撑 “静态资源服务、动态请求转发、负载均衡部署” 等实际需求,为 Web 服务搭建与优化提供实用参考。