很干的 Nginx
🎨 前言
本篇文章有些概念性的东西,是结合自己的理解表达出来的,可能有些理解不到位的地方。希望多多指教,谢谢大家。
红包献上 🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧🧧
🎨 最小单元配置
worker_processes 1; # 工作的进程个数events {worker_connections 1024; # 一个进程可以创建多少个链接(默认 1024)
}http {# 引入其他配置(返回前端的头部信息,告诉浏览器返回的数据格式)include mime.types; # 如果没有命中 mime.types 的类型,则默认返回 application/octet-stream 的数据格式default_type application/octet-stream;# 数据零拷贝 (减少了 nginx 读取文件,拷贝文件,直接将文件返回给到前端)sendfile on;# 保存连接超时时间keepalive_timeout 65;# 虚拟主机server {# 监听端口listen 80;# 域名、主机名server_name localhost;location / { # / 转发# 指向 nginx 目录下的 html 目录root html;# 默认展示页index index.html index.htm}# 错误码为 500 502 503 504 会命中 50x.htmlerror_page 500 502 503 504 /50x.html# 访问 /50x.html 会被代理到 nginx 下的 html 目录下 location = /50x.html {root html}}
}
🎨 二级域名转发
根据不同的二级域名返回不同的站点
如:
- 域名 blog.hhmax.xyz 返回博客站点
- 域名 www.hhmax.xyz 返回主站站点
原理:将不同的二级域名都指向同一个 IP 地址,在通过 Nginx 在转发时,根据不同的二级域名,返回不同的站点
下面通过俩种方式进行演示:
🎉 内网模拟站点映射
在 C:\Windows\System32\drivers\etc\hosts
文件中添加
39.104.61.35 blog.hhmax.xyz
39.104.61.35 www.hhmax.xyz
测试是否映射成功
ping blog.hhmax.xyz
ping www.hhmax.xyz
接下来进行 Nginx 配置,配置内容如下:
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name www.hhmax.xyz; location / {root html; # 转发到 nginx/html/index.html 或 index.htmindex index.html index.htm} },server {listen: 80,server_name blog.hhmax.xyz; location / {root blog; # 转发到 nginx/blog/index.html 或 index.htmindex index.html index.htm} }
}
🎉 外网模拟站点映射
需要购买域名以及一台服务器,并且服务器要备案成功才能映射成功
选中域名解析,并添加记录
需要设置的字段
- 记录类型:这里选择 A - 将域名指向一个 IPV4 的地址
- 主机记录:可以填写一个二级域名(即我们要设置的 blog 和 www)
- 记录值:映射的地址(即我们要映射的服务器IP地址)
可添加多条记录,并映射到其他 IP 或相同 IP
接下来进行 Nginx 配置,配置内容如下:
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name www.hhmax.xyz; location / {root html; # 转发到 nginx/html/index.html 或 index.htmindex index.html index.htm} },server {listen: 80,server_name blog.hhmax.xyz; location / {root blog; # 转发到 nginx/blog/index.html 或 index.htmindex index.html index.htm} }
}
注意:上述 Nginx 配置监听的端口是 80 端口,服务器可能需要开启
🎨 反向代理
🎉 正向代理
概念:代理服务器充当客户端的中间人,代表客户端向目标服务器发送请求。在正向代理中,客户端通过代理服务器来访问互联网上的资源,而不是直接与目标服务器通信。
好处:隐藏客户端的真实 IP 地址和身份,增加了匿名性和安全性
🎉 反向代理
概念:代理服务器接收客户端请求,并将请求转发给后端服务器。在反向代理中,客户端不直接与后端服务器通信,而是与代理服务器进行通信。
好处:
- 可以实现负载均衡,将请求分发到多个后端服务器,提高系统的性能和可靠性(负载均衡)
- 可以缓存静态资源,减少后端服务器的负载(动静分离)
Nginx 与 Tomcat 形成内网,Tomcat 不能直接绕过 Nginx 通过网关,发送消息。必须通过 Nginx 来发送消息。这种模式称为 隧道式代理
由此,也暴露出一个问题,当数据量很大时,尽管 Tomcat 的带宽有 100M,但 Nginx 的带宽只有 10 M。由于需要借助 Nginx 来向外传递数据,最终的传输数据没有设想的那么好。Tomcat 带宽再好,也要受限于 Nginx。
为了解决上述的缺点:
衍生出一种模式: Nginx 只处理进来的请求,而出去的数据不经过 Nginx 进行转发。Tomcat 直接将数据通过网关发送给到用户(中间会经过其他网关进行转发)。这种模式称为 DR 模式
🎉 反向代理配置
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location / {# 当访问 blog.hhmax.xyz 是代理到 http://www.baidu.com proxy_pass http://www.baidu.com} location /api { # 笔记# 当访问 blog.hhmax.xyz/api 是代理到 内网中的 http://127.0.0.1:3200 proxy_pass http://127.0.0.1:3200;} }
}
注意:上述例子中代理到后端服务 3200 端口也需要开放
🎨 负载均衡
概念:用于在多个服务器之间分配和平衡工作负载,以提高系统的性能、可靠性和可扩展性。当一个服务器无法处理所有的请求时,负载均衡将请求分发给其他可用的服务器,以确保每个服务器都能够处理适当的负载。
🎉 普通轮询
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; # 轮询的服务器 upstream httpds {server 192.168.5.51:80; server 192.168.6.51:80; server 192.168.7.51:80; }server {listen: 80,server_name blog.hhmax.xyz; location / {proxy_pass http://httpds;} }
}
192.168.5.51:80
、192.168.6.51:80
、192.168.7.51:80
三台服务器提供的服务都一样。
🎉 权重轮询
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; # 权重值越大,被轮询到的可能性越大upstream httpds {server 192.168.5.51:80 weight=8; server 192.168.5.51:80 weight=1; server 192.168.5.51:80 weight=7; }server {listen: 80,server_name blog.hhmax.xyz; location / {proxy_pass http://httpds;} }
}
另外一些配置
- down (若配置,则该台服务器不参与轮询)
- backup(若配置,则该台服务器为备用机,当其他轮询服务器不能使用时,才会使用该服务器)
具体使用如下:
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; upstream httpds {server 192.168.5.51:80 weight=8 down; server 192.168.5.51:80 weight=1; server 192.168.5.51:80 weight=7 backup; }server {listen: 80,server_name blog.hhmax.xyz; location / {proxy_pass http://httpds;} } }
🎉 轮询缺点
由于是轮询,所以导致没法保存会话信息,如在 192.168.5.51:80
用户登录成功。当用户再次访问该站点时,被 Nginx 轮询到192.168.7.51:80
,此时这台服务器是不知道用户已经登录了,所以需要重新在登录。
🎉 解决方案
随着技术的发展,为了解决轮询带来的会话信息无法保存,衍生出了两种方案来解决上述问题
- 其一:借助 cookie、session、redis
流程:
- 用户输入其登录信息
- 服务器验证信息是否正确,并创建一个 session,并将其存入到 redis
- 服务器为用户生成一个 sessionId,将具有 sesssionId 的 cookie 将放置在用户浏览器中
- 在后续请求中,携带 cookie,访问服务器。哪怕是轮询到其他服务器,也可以通过 sessionId 去 redis 拿去登录信息
- 一旦用户注销应用程序,会话将在客户端和服务器端都被销毁
Node + Koa2 代码实现
// app.js
const app = new Koa()
const Koa = require('koa')
const redisStore = require('koa-redis')
const session = require('koa-generic-session')
//session 与 redis
app.keys = ['dfhQWE_123#ewr']
app.use(session({key: 'token.sid', //cookie name 默认是 `koa.sid`prefix: 'token:sess:', // redis key 的前缀,默认是 `koa:sess:`//配置cookiecookie:{path:"/",httpOnly:true,maxAge:24 * 60 * 60 * 1000 // 1 day},//配置redisstore: redisStore({all:`127.0.0.1:6379`})
}))// router
router.post('/login', async (ctx, next) => {const { account = '-', password = '-' } = ctx.request.body;if (config.account == account && config.password == password) {// TODO 将账号信息(id)保存到 session 中ctx.session.user = {account: config.account}ctx.body = {errorno: 0,message: '登录成功'}return}ctx.body = {errorno: 4001,message: '账号或密码错误'}
});// 中间件校验 loginCheck
module.exports = async (ctx, next) => {// // TODO:判断用户是否已经登录if (ctx.session.user) {await next()return} else {ctx.body = {errorno: 4000,message: '用户未登录'}}
}// 判断是否已经登录成功
router.post('/getNotes', loginCheck, async (ctx, next) => {const data = await searchData();ctx.body = {errorno: 0,message: '',data}
});
- 其二:无状态的会话通信 (JWT)
流程:
- 用户输入其登录信息
- 服务器验证信息是否正确,并返回已签名的 Token
- Token 存储在客户端
- 之后的 HTTP 请求都将 Token 添加到请求头里
- 服务器解码 JWT,并且如果令牌有效,则接受请求
- 一旦用户注销,令牌将在客户端被销毁,不需要与服务器进行交互一个关键是,令牌是无状态的。后端服务器不需要保存令牌或当前session的记录
Node + Koa2 代码实现
// app.js
const app = new Koa()
const Koa = require('koa')
const jwtKoa = require('koa-jwt')
app.use(jwtKoa({secret:'1Hrj$_enferk' //密钥}
).unless({path:[/^\/users\/login/] //自定义哪些目录忽略 JWT 验证
}))//登录成功对信息进行加密
const jwt = require('jsonwebtoken')
token = jwt.sign(userInfo, '1Hrj$_enferk', { expiresIn: '1h' })// router
const until = require('util')
const verify = until.promisify(jwt.verify)
router.get('/getUserInfo', async (ctx, next) => {const token = ctx.header.authorizationtry {const payload = await verify(token.split(' ')[1], '1Hrj$_enferk')ctx.body = {errno:0,userInfo: payload}} catch (ex) {ctx.body = {errno:-1,msg:'失败'}}
})
🎉 方案对比
共同点:为了解决:登录和存储登录用户信息
不同点:
- JWT 用户信息加密存储在客户端,不依赖 cookie ,可跨域。
- session 用户信息存储在服务端,依赖于 cookie,默认不可跨域
JWT 的优点:
- 将加密信息存放在客户端,减少服务端的内存压力。
- 不依赖于 cookie 可以将信息进行跨域分享。
JWT 的不足:
- 服务端无法控制信息,一旦用户修改信息后,服务端无法第一时间修改加密信息。
Session 的优点:
- 可以对用户信息进行控制。
Session 的不足:
- 存储要依赖于 redis 和 cookie ,并且不能跨域。
- 一旦上线启动多进程,而不依赖 redis 是无法实现多进程之间的信息共享。
🎨 动静分离
在还没有前后端分离的开发模式的情况下(MVC),一些静态资源都是集中和后端代码放在 Tomcat 。而这些静态资源大多数情况下都是不变的,如:图片,JavaScript 代码。
并且 Nginx 可以缓存静态资源,减少后端服务器的负载。因此,可以将一些静态资源放到 Nginx 中,从而使一些静态资源与业务逻辑进行抽离。
具体配置如下:
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location / {proxy_pass http://192.168.6.52 }location ~*/(css|img|js) {# 路径中有 /css /img /js 使会指向 nginx/html 中的 css、img、js root html;index index.html index.htm } }
}
随着技术的发展,特别是前后端分离的开发模式,上述情况也不复存在,后端也不用考虑到静态资源该怎么处理,都转移给到前端了
🎨 资源防盗链
保护网站资源不被其他网站盗用的技术措施
防盗链的实现原理:
- 服务器收到请求后,获取请求头中的
referer
字段 - 验证
referer
字段是否符合预设的规则,例如是否在允许的域名列表中 - 如果
referer
验证通过,则允许访问资源;否则,拒绝访问或返回特定的错误页面
情况一:页面引用图片请求头中会携带 referer
头,值就是引用该资源的这个地址
情况二:单独复制该图片地址,重新打开窗口访问时,请求该图片时,referer
头就不会携带给到后端
配置一:两种情况都不能访问资源(图片)
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location /img { valid_referers blog.hhmax.xyz;if ($invalid_referer) {return 403;} # 路径中有 /nginx/img root img;index index.html index.htm } }
}
valid_referers
:配置的值得跟server_name
一样
配置二:仅第二种情况可以访问资源
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location /img { valid_referers none blog.hhmax.xyz;if ($invalid_referer) {return 403;} # 路径中有 /nginx/img root img;index index.html index.htm } }
}
valid_referers
:配置的值得跟server_name
一样
配置后:
没有权限访问图片,也可以配置返回一个错误页面,或者一个错误图片
- 错误页面
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location /img) { valid_referers blog.hhmax.xyz;if ($invalid_referer) {return 401;} root img;index index.html index.htm }error_page 401 /401.htmllocation = /401.html {root html; } }
}
- 错误图片
http {include mime.types; default_type application/octet-stream;sendfile on;keepalive_timeout 65; server {listen: 80,server_name blog.hhmax.xyz; location /img { valid_referers blog.hhmax.xyz;if ($invalid_referer) {return ^/ /img/x.png break;} root html;index index.html index.htm } }
}
通过正常手段,访问或者引用资源(图片),通过上述方法是可以避免资源被盗用的。因为referer
字段通过某些手段是可以被伪造或篡改。因此防盗链并不能完全阻止盗链行为。为了增加安全性,可以结合其他技术手段,如加密链接、动态生成链接等,来提高防盗链的效果。
相关文章:

很干的 Nginx
🎨 前言 本篇文章有些概念性的东西,是结合自己的理解表达出来的,可能有些理解不到位的地方。希望多多指教,谢谢大家。 红包献上 🧧🧧🧧🧧🧧🧧🧧…...

【已解决】pycharm突然双击无法打开,重启电脑也不管用
1.问题: pycharm突然双击无法打开,重启电脑也不管用 2.解决 2.1 方法一(修改Roaming) 1.找到C盘对应路径下的pycharm版本 2. 用记事本打开文件类型为VMOPTIONS文件 3. 修改或删除最后一行的映射路径 4.保存退出 2.2 方法二…...

【HCIP】15.MPLS基础
多协议标签交换 MPLS位于TCP/IP协议栈中的数据链路层和网络层之间,可以向所有网络层提供服务。 通过在数据链路层和网络层之间增加额外的MPLS头部,基于MPLS头部实现数据快速转发。 术语 MPLS域(MPLS Domain):一系列…...

热烈祝贺重庆融能成功入选航天系统采购供应商库
经过航天系统采购平台的严审,重庆融能机电设备股份有限公司成功入选中国航天系统采购供应商库。航天系统采购平台是航天系统内企业采购专用平台,服务航天全球范围千亿采购需求,目前,已有华为、三一重工、格力电器、科大讯飞等企业…...

隧道vs免费爬虫ip:为何要选择隧道爬虫ip?
在网络爬虫的世界中,爬虫ip是一项关键技术,它可以帮助我们隐藏身份、突破限制、提高抓取效率。但是,在选择爬虫ip时,我们常常会面对隧道爬虫ip和免费爬虫ip之间的抉择。在本文中,我们将探讨隧道爬虫ip相对于免费爬虫ip…...

C++day6(多态实现动物园的讲解员和动物表演的相关介绍、用函数模板实现不同数据类型的交换功能)
1.比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园,看到了许多不同种类的动物,如狮子、大象、猴子等。现在,动物园里有一位讲解员,他会为每种动物表演做简单的介绍。 在这个场景中,我们可以将动…...

多线程学习之生产者和消费者与阻塞队列的关系
生产者和消费者 概述: 生产者消费者问题,实际上主要是包含了两类线程: 生产者线程用于生产数据消费者线程用于消费数据 生产者和消费者之间通常会采用一个共享的数据区域,这样就可以将生产者和消费者进行解耦, 两…...

JAVA语言代入电商平台api接口拼多多根据关键词获取商品列表示例
拼多多根据关键词获取商品接口的意义; 实现商品搜索:通过关键词搜索商品API接口,电商平台可以为消费者提供一个简单、快捷的商品搜索功能。用户只需输入关键词,就可以得到与该关键词相关的商品列表。 提供便捷的商品搜索服务&…...

Centos7更新glibc2.18
Centos7更新glibc2.18 查看glibc版本下载解压glibc2.18编译安装结果验证 查看glibc版本 # 查看glibc版本 ldd --version下载解压glibc2.18 参考: https://blog.csdn.net/qq_39295044/article/details/86685789 https://blog.csdn.net/myhes/article/details/106923039 # 下载…...

QT初学者该安装qt creator哪个版本?
对于Qt初学者,建议安装最新版本的Qt Creator。Qt Creator是Qt官方提供的集成开发环境(IDE),用于开发Qt应用程序。每个Qt版本都会配套提供对应的Qt Creator版本,确保兼容性和稳定性。同时,选择合适的Qt版本也…...

VR智慧校园资中控管理平台综合提升了课堂教学质量
随着越来越多高校在课堂中引进VR虚拟仿真实训系统,为了方便老师对全班同学进行高效率地管理,VR中控平台应运而生。下面为您详细介绍VR中控平台在课堂教学中的应用优势。 VR中控系统安装在教师总控端,融合了课件、视频、3D动画等丰富的教学资源…...

【Go 基础篇】Go语言中的数组:初识与应用
Go语言以其简洁、高效和强大的特性在编程界广受欢迎。数组作为一种基本的数据结构,在各种应用场景中扮演着重要角色。本文将引入Go语言中的数组,介绍其特点、创建、初始化以及基本应用,为你打开数组的大门。 前言 数组是一种固定大小的数据…...

(vue)el-table 怎么把表格列中相同的数据 合并为一行
(vue)el-table 怎么把表格列中相同的数据 合并为一行 效果: 文档解释: 写法: <el-table:data"tableData"size"mini"class"table-class"borderstyle"width:100%"max-height"760":span-…...

精准高效农业作业,植保无人机显身手
中国作为农业大国,拥有约18亿亩的农田,每年都需要进行种子喷洒和农药施用等农业作业,对于普通农户来说,这是一项耗时耗力的工程,同时,人工喷洒农药极易造成农药慢性中毒,对农民的身体健康产生极…...

大集合拆分成多个小集合
文章目录 1. 场景2. 拆分集合方法(写了三种)3. 格式化打印方法 1. 场景 在数据库批量操作时,有可能数据量过大,不能一次性操作,所以需要将大集合拆分为多个小集合进行多次操作 2. 拆分集合方法(写了三种&…...

linux————LVS集群
目录 一、集群概述 一、负载均衡技术类型 二、负载均衡实现方式 二、LVS结构 一、三层结构 二、架构对象 三、LVS工作模式 四、负载均衡算法 一、静态负载均衡 二、动态负载 五、ipvsadm命令详解 六、LVS配置 一、基础配置 二、实现NAT模型搭建 配置IP地址 安装…...

软考高级系统架构设计师系列论文七十一:论行业应用软件系统的开发规划
软考高级系统架构设计师系列论文七十一:论行业应用软件系统的开发规划 一、软件系统相关知识二、摘要三、正文四、总结一、软件系统相关知识 软考高级系统架构设计师系列之:系统开发基础知识...

vue2 自定义指令,插槽
一、学习目标 1.自定义指令 基本语法(全局、局部注册)指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 二、自定义指令 1.指令介绍 内置指令:v-html、v-if、v-bind、v-on… 这都是Vue给咱们内置的一些指令,…...

oracle超详细语法和备份工具
oracle基础语法 在 Oracle 开发中,客户端把 SQL 语句发送给服务器,服务器对 SQL 语句进行编译、执行,把执行的结果返回给客户端。常用的SQL语句大致可以分为五类:数据定义语言(DDL),包括 CREAT…...

Redis的持久化机制是什么?各自的优缺点?
Redis拥有两种持久化机制:RDB(Redis Database)和AOF(Append-Only File)。 1.RDB(Redis Database)持久化机制 RDB是Redis的默认持久化方式,它通过将Redis在某个时间点的数据状态保存到磁盘上的二进制文件中。该文件是一个快照(snapshot),包含…...

机器学习:什么是分类/回归/聚类/降维/决策
目录 学习模式分为三大类:监督,无监督,强化学习 监督学习基本问题 分类问题 回归问题 无监督学习基本问题 聚类问题 降维问题 强化学习基本问题 决策问题 如何选择合适的算法 我们将涵盖目前「五大」最常见机器学习任务:…...

算法通关村第5关【白银】| 哈希和栈经典算法题
1.两个栈实现队列 思路:两个栈,一个输入栈,一个输出栈。 当需要输入的时候就往inStack中插入,需要输出就往outStack中输出,当输出栈是空就倒出输入栈的数据到输出栈中,这样就保证了后插入的数据从栈顶倒入…...

CrystalNet .Net VCL for Delphi Crack
CrystalNet .Net VCL for Delphi Crack VCL或更为人所知的可视化组件库是基于一个面向对象的框架,什么是用户对开发人员和事件的Microsoft Windows应用程序的接口。可视化组件库是用对象Pascal编写的。它主要是为使用Borland而开发的,它具有与Delphi以及…...

云计算在线实训系统建设方案
一、 人工智能与云计算系统概述 人工智能(Artificial Intelligence,简称AI)是一种模拟人类智能的科学和工程,通过使用计算机系统来模拟、扩展和增强人类的智能能力。人工智能涉及多个领域,包括机器学习、深度学习、自然…...

C++ 珠心算测验
珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练, 既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。 某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整…...

prometheus+cadvisor监控docker容器
一、安装cadvisor docker pull google/cadvisor:latest二、运行容器 docker run -d \--volume/:/rootfs:ro \--volume/var/run:/var/run:rw \--volume/sys:/sys:ro \--volume/var/lib/docker/:/var/lib/docker:ro \--publish8088:8080 \--detachtrue \--namecadvisor \--priv…...

13、Vue3 大事件管理系统
一、大事件项目介绍 和 创建 1.1 Vue3 大事件管理系统 在线演示: https://fe-bigevent-web.itheima.net/login 接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835 基地址: http://big-event-vue-api-t.i…...

Redis三种特殊数据类型
Redis三种特殊数据类型 geospatial 地理位置 Redis 地理空间数据类型简介 Redis 地理空间索引允许您存储坐标并搜索它们。 此数据结构可用于查找给定半径或边界框内的邻近点。 基本命令 GEOADD 将位置添加到给定的地理空间索引(请注意,使用此命令&a…...

python 模块BeautifulSoup 从HTML或XML文件中提取数据
一、安装 Beautiful Soup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。 lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多…...

VS Code插件汇总
插件 Basic Chinese(Simplified) Language Pack C/C C/C CMake Tools C/C Extension Pack Web Open in browser Microsoft Edge Tool Linux WSL Tool AWS Toolkit Bito AI Code Assistant CursorCode TabNine IntelliCode Kite...