目录
第一章正向代理和反向代理
1.1代理
1.2正向代理(VPN)
1.3反向代理(Nginx等)
1.4(域名请求的流程解析)线上访问服务器应用流程解析
第二章 Nginx的部署的本地域名映射
1 使用dokcer部署
2 本地域名映射
第三章 Nginx目录以及配置文件的详解
3.1 Nginx目录
3.2 Nginx 配置文件详解
3 .3 access.log日志用处
第四章Nginx的常见应用
4.1 Nginx搭建静态资源服务器(动静分离)
4.2 Nginx同时代理多台不同域名的(网站)服务器
4.3 负载均衡与常见的负载均衡策略(重点)
4.4 Nginx探测后端节点可用性和配置实操(重点)
4.5 Nginx-全局异常兜底数据返回
4.6 nginx热加载配置,不中断服务
4.7 Nginx封禁恶意IP
4.8 Nginx如何配置浏览器跨域
4.9 使用nginx的rewrite(重定向)来配置防盗接
4.10 Nginx的locatioin匹配规则应用
4.11 Nginx端缓存前置
第五章 Nginx线上实战完整配置
第1集 传输协议Https
第七章Nginx整合OpenResty
7.1 Nginx的第三方利器OpenResty+Lua介绍
7.2 OpenResty + Lua相关环境准备
7.3 高并发利器-Nginx+OpenResty第一个例子
.4 Nginx内置全局变量 和 OpenResty 请求阶段划分讲解
7.5 OpenResty开发内网访问限制或者端口访问限制(类似ECS安全组)
7.6 -Nginx+OpenResty实现请求限流和资源下载限速
7.7 【面试题】网盘静态资源下载限速实现原理
第8章 Ngnix高可用解决方案LVS+KeepAlived
第1集 全链路高可用之Nginx基础架构问题分析
第2集 业界主流的高可用方案 Linux虚拟服务器LVS 讲解
第3集 业界主流的高可用方案 keepalived讲解
第4集 Keepalived核心配置讲解
第 5 集 Keepalived常用命令
第6集Nginx+LVS+KeepAlived高可用方案(主备模式)实战
第7集Nginx+LVS+KeepAlived高可用方案(双主模式)实战
第九章 Nginx高性能原理和课程总结
在Java设计模式中,代理模式是这样定义的:给某个对象提供一个代理对象,并由代理对象控制原对象的引用。
可能大家不太明白这句话,在举一个现实生活中的例子:比如我们要买一间二手房,虽然我们可以自己去找房源,但是这太花费时间精力了,而且房屋质量检测以及房屋过户等一系列手续也都得我们去办,再说现在这个社会,等我们找到房源,说不定房子都已经涨价了,那么怎么办呢?最简单快捷的方法就是找二手房中介公司(为什么?别人那里房源多啊),于是我们就委托中介公司来给我找合适的房子,以及后续的质量检测过户等操作,我们只需要选好自己想要的房子,然后交钱就行了。
代理简单来说,就是如果我们想做什么,但又不想直接去做,那么这时候就找另外一个人帮我们去做。那么这个例子里面的中介公司就是给我们做代理服务的,我们委托中介公司帮我们找房子。
Nginx 主要能够代理如下几种协议,其中用到的最多的就是做Http代理服务器。
弄清楚什么是代理了,那么什么又是正向代理呢
这里的 VPN 就是做正向代理的。正向代理服务器位于客户端和服务器之间,为了向服务器获取数据,客户端要向代理服务器发送一个请求,并指定目标服务器,代理服务器将目标服务器返回的数据转交给客户端。这里客户端是要进行一些正向代理的设置的。
核心:用户知道自己访问的目标服务器的地址也知道正向代理服务器的地址
使用场景:、访问原来无法访问的网站,VPN
反向代理和正向代理的区别就是:正向代理服务器代理的是客户端(客户是指客户端浏览器),反向代理服务器代理的是服务器(客户是Web网站)。
核心:客户端不知道要访问的目标服务器的地址,但是知道反向代理服务器的地址,反向代理服务器会根据一定的策略选择一个真实的服务器进行请求
反向代理,其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去自己选择目标服务器获取数据后(我们要在反向代理服务器配置自己要用的目标服务器),在返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址。
理解这两种代理的关键在于代理服务器所代理的对象是什么,正向代理代理的是客户端,我们需要在客户端进行一些代理的设置。而反向代理代理的是服务器,作为客户端的我们是无法感知到服务器的真实存在的。
总结起来还是一句话:正向代理代理客户端,反向代理代理服务器。
1一个通过域名访问的http请求的基本流程
客户端通过发起域名资源请求 -> DNS解析获得IP -> 寻找服务器获得资源
2 域名和ip的关系,
一个ip地址可以对应多个域名,但是一个域名只有一个ip地址
3 DNS作用
DNS:Domain Name Server 域名服务器 域名虽然便于人们记忆,但网络中的计算机之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,DNS 就是进行域名解析的服务器
4 什么是cname和a记录
a记录(常用)
用户可以在此设置域名并指向到自己的目标主机ip地址上,从而实现通过域名找到服务器(也叫ip指向域名配置)aabbcc.com -> 120.24.216.117
cname
别名指向,可以为一个主机设置别名。比如设置open1024.com,用来指向一个主机 xdclass.net 那么以后就可以用open1024.com来代替访问xdclass.net 了 ,可以直接输入xdclass.net去访问
www.xdclass.net --> xdclass.net
docker run --name xdclass-nginx -d -p 80:80 -v /tmp/nginx/log:/var/log/nginx -v /tmp/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /tmp/nginx/html:/usr/share/nginx/html -v /tmp/nginx/conf/deny.conf:/etc/nginx/deny.conf 08b152afcfae
当我们没有公网域名时,可以使用本地域名来模拟
使用SwitchHosts工具去做本地域名映射
比如此时虚拟机的IP为 192.168.43.180 我们做了域名映射后,在浏览器中访问图中的xxrtest.com就是访问192.168.43.180
在docker安装的Nginx中
1 配置文件目录在 /etc/nginx 目录中
里面有default.conf(模板配置文件)以及Nginx.conf(正式配置文件,里面会包含在模板配置文件进行的配置)
2 默认站点目录在 /usr/share/nginx/html中
里面有50x.html #错误页面(服务器报错页面)index.html #默认首页
3 日志目录/var/log/nginx
里面有access.log error.log
打开nginx配置文件Nginx后,我们可以很明显的将 nginx.conf 配置文件分为三部分:
1 全局块,2 events块 3http块
# 每个配置项由配置指令和指令参数 2 个部分构成
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
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 /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
3.2.1全局块 (配置全局指令)
从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、错误日志存放路径和类型以及配置文件的引入等。
user nginx; # 指定Nginx Worker进程运行以及用户组
比如上面第二行配置的:
worker_processes auto; #Nginx的工作线程数,当前版本是数量与Cpu核数一样
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约,这个后面会详细介绍。推荐与CPU的核数保持一致
error_log /var/log/nginx/error.log notice;
表示错误日志存放目录
pid /var/run/nginx.pid;
# 进程PID存放路径
3.2.2events 块(事件模块指令)
比如上面的配置:
events {
use epoll;#默认初始配置中时没有的我们可以加上以提高性能
worker_connections 1024; #每个工作进程的最大连接数(生产环境中建议设置超过9000)
}
events 块涉及的指令主要影响 Nginx 服务器的性能与用户的网络连接数,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求(如epoll 异步非阻塞,线上一般用这个),每个 word process 可以同时支持的最大连接数等。
上述例子就表示每个 work process 支持的最大连接数为 1024.
# 定义Nginx每个进程的最大连接数,
作为(静态资源)服务器(不与后端联系的话)来说最大并发为: worker_connections * worker_processes,
# 作为反向代理服器器来说,最大并发数量应该是
worker_connections * worker_processes/2。
因为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
use epoll; 表示使用 epoll 事件驱动模型来处理连接请求 线上一般使用这个模型
#Nginx默认初始配置中时没有的我们可以加上以提高性能
3.2.3http 块
http全局块配置的指令包括文件引入、MIME-TYPE(枚举类型) 自定义accesslog的日志格式、连接超时时间、单链接请求数上限等。
http {
include /etc/nginx/mime.types; #枚举类型
default_type application/octet-stream; #内容类型
#用户访问日志accesslog的格式(后期我们肯定要修改)
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 /var/log/nginx/access.log main; # access_log的地址
sendfile on; #开启高效传输
#tcp_nopush on; #减少网络报文的数量
keepalive_timeout 65; #客户端连接超时时间
#gzip on; #压缩(压缩客户端发送的文件,可以减少带宽)
server {
listen 9001; #虚拟主机监听的端口
server_name 118.31.13.73 xxrtest.com;
#虚拟主机的名称可以是Ip也可以是域名,可以在这里写多个,空格隔开,一般是写多个域名
access_log /var/log/nginx/ gateway_access.log main; #每个server也可以有自己的access_log的地址
# Location主要是用来匹配(拦截)Nginx 服务器接收到的请求uri,匹配成功则反向代理到指定的服务器当中去(可以写正则表达式)
location / {
proxy_pass http://gateway/;#被代理服务器的地址
root html; //存储路径可以是绝对路径也可以是相对路径,用来做静态文件服务器的
index index.html index.html; 如果匹配路径/后面没有写东西则进入这个页面
(即默认的首页)
}
}
include /etc/nginx/conf.d/*.conf;
}
3.2.3.1 upstream 块(请求转发块)(包含在http 全局块中)
假设Nginx只能代理一台服务器的话,那它也不可能像今天这么火。Nginx能够配置代理多台服务器。当一台服务器宕机之后。仍能保持系统可用。
使用nginx的upstream块可以让nginx代理多台服务器,当请求到nginx的upstream块之后,upstream块会按照轮询(默认)方式进行负载均衡的反向代理
如 upstream nacos {
server 192.168.152.1:8849;
server 192.168.152.1:8850;
server 192.168.152.1:8851;
}
upstream redisLock {
server 192.168.43.98:8080 weight=1;
server 192.168.43.98:8081 weight=1;
}
3.2.3.2 server 块(虚拟主机块)(包含在http 全局块中)(可以有多个server)
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。后面会详细介绍虚拟主机的概念。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机,每一个虚拟主机块server可以监听一个端口。不同的server他们监听的端口可以是一样的但是 server_name即虚拟主机的名称一定不一样
而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
1、全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
3.2.3.2.1 location 块(路径拦截器块)(包含在server 块中)
一个 server 块可以配置多个 location 块。
Location主要是用来匹配Nginx 服务器接收到的请求uri的(不是URL),当匹配成功时Nginx 会做出应答给客户端(反向代理到某个地址,或者直接到Nginx配置的页面当中去,或者直接获取存储路径中的静态资源)(可以写正则表达式去匹配收到的请求uri的)
location /redisLock/{
proxy_pass http://redisLock/;
root html; //存储路径可以是绝对路径也可以是相对路径,用来做静态文件服务器的(一般都是单独写)
index index.html index.html;
}
2.1 proxy_pass该指令用于设置被代理服务器的真实地址。可以是主机名称、IP地址加端口号的形式,也可以是upstream块的名称(因为我们往往会让nginx同时代理多台服务器)。
(注意这里的proxy_pass地址后面一定要加/,否则真正要用的uri无法反向代理到我们真实的服务器中
这里请求的url如果是 http://localhost/redislock/test1,则uri/redislock/test1那么uri只有后面部分会反向代理到我们真实服务器192.168.43.98:808x中(location的匹配路径并不会反向代理过去) 这样真实的请求(方向代理请求)就变成了192.168.43.98:808x/ test1,
如果不加/,那么反向代理的请求就变成
http:// 192.168.43.98:808x /redislock/test1,肯定是404
)
2 .2 root 这里指的是存储路径可以是绝对路径也可以是相对路经(使用root时就是用Nginx做静态资源服务器)
location /static/{
root /usr/share/nginx/html;
}
3 index 如果匹配路径/后面没有写东西则进入这个首页页面(即默认的首页)
,如果找不到index.html则返回404
3.2.3.2.2 location块的拦截顺序问题
注意:当有多个location块时我们要考虑顺序问题,在前面的优先拦截,我们一般吧
location / { 这个放在末尾以防影响其他的location,因为它什么请求都会拦截
}
1 统计站点访问ip来源、某个时间段的访问频率
2 查看访问最频的页面、Http响应状态码、
3 接口性能接口秒级访问量、分钟访问量、小时和天访问量
4 查看PV 等参数指标
#用户访问日志accesslog的格式(后期我们肯定要修改)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
注意:这些数据都在一行中,且各自都是空格隔开,我们可以使用awk命令去按列提取(切割)
这样方便对access.log进行数据分析
实例
122.70.148.18 - - [04/Aug/2020:14:46:48+0800] "GET
/user/api/v1/product/order/query_state? product_id=1&token=xdclasseyJhbGciOJE HTTP/1.1" 200 48 "https://xdclass.net/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
常见属性的解析
1 $remote_addr 对应的是真实日志里的122.70.148.18, 即客户端的IP。
2 $remote_user 对应的是第二个中杠“-”,没有远程用户, 所以用“-”填充。
3 [$time_local]对应的是[04/Aug/2020:14:46:48+0800]。 请求的时间
4 “$request”对应的是 请求类型和请求Uri(用来统一最热门的接口)
5 $status对应的是200状态码,200表示正常访问。
6 $body_bytes_sent对应的是48字节,即响应body的大小。
7 $http_referer” 对应的即请求的来源即是”https://xdclass.net/“,若是直接打开域名浏览的时,referer就会没有值,为”-“。(可以用来设置防盗链)
8 “$http_user_agent” 指用户的代理信息如用户是通过什么系统访问win,mac,安卓等,什么浏览器访问(可以用来防爬虫,爬虫的话,这个地方一般都是为空的)
对应的是
”Mozilla/5.0(Macintosh; Intel Mac OS X 10.12; rv:56.0) Gecko/20100101 Firefox/56.0”。
9 “$http_x_forwarded_for” 对应的是”-“或者空。(只有配置了这个,后端才能直接获取用户的真实IP)
3.3.1通过access.log获取访问最频繁的前100个IP
awk '{print $1}' access_temp.log | sort |uniq -c | sort -rn | head -n 100
(命令逻辑:先切割日志中第一列的数据出来,进行排序一下,在使用uniq 去除重复出现的行列, -c 在每列旁边显示该行重复,这样此时就有两列数据,再sort –rn按第一列的数值大小(即重复数)进行倒序,再取前100条数据)
命令解析
awk 是文本处理工具,默认按照空格切分,默认按列切割(提取)数据,$N 是切割第N列的数据
sort命令用于将文本文件内容加以排序,-n 按照数值排,- r 按照倒序来排
案例的sort -n 是按照第一列的数值大小进行排序,从
小到大,倒序就是 sort -rn
uniq 去除重复出现的行列, -c 在每列旁边显示该行重复
出现的次数。
head –n 取前多少行的数据
3.3.2 通过access.log获取访问最多的url(接口)前20名
awk '{print $7}' access_temp.log | sort | uniq -c|sort -rn|head -n 20
最简单的写法,但是由于URI的参数会不同(如token不同),实际项目中不能这么写
/pub/api/v1/web/user_info?token=xdclasssdfsdf2sseyJhbGciOiJIUzI1NiJ9.eyJzd
线上的写法
awk '{print $7}' access_temp.log|awk -F"?" '{print $1}'|sort|uniq -c|sort -rn|head -n 20
(我们还要把URL参数给去掉,再统计)
(第二次awk是根据?号去分割数据)
结果是这种
4574 /user/api/v1/product/order/query_state
1165 /pub/api/v1/web/user_info
684 /order/api/v1/video/xdcloud_play_url
610 /pub/api/v1/web/product/find_list_by_type
428 /pub/api/v1/web/all_category
357 /pub/api/v1/web/video_detail
346 /user/api/v1/order/query_state
264 /pub/api/v1/web/index_card
224 /pub/api/v1/web/find_ad_by_id
190 /pub/api/v1/web/page_video
174 /pub/api/v1/web/list_buyer
143 /pub/api/v1/web/relative_video
140 /pub/api/v1/web/funny_lang_list
134 /user/api/v1/order/find_orders
126 /pub/api/v1/web/is_favorite
119 /user/api/v1/video_record/page
111 /pub/api/v1/web/search
53 /pub/api/v1/web/web_login
26 /pub/api/v1/web/get_free_online_note
15 /pub/api/v1/web/tool/page_all_tools
3.3.3自定义access.log日志统计接口性能
使用单纯的jmeter测出的接口的响应时间,可能不是实际线上的接口响应时间,我们就可能无法找到瓶颈,我们可以使用Nginx的access.log日志来分析最准确的接口响应时间
步骤:日志格式的最后增加 $request_time
$request_time:从接受用户请求的第一个字节到发送完响应数据的时间,即
包括接收请求数据时间、程序响应时间、输出响应数据时间,用它来描述用户对接口的性能是最好的
$upstream_response_time:指从Nginx向后端建立连接开始到接受完数据然后关闭连接为止的时间用它来描述纯后端接口的性能是最好的
$request_time一般会比upstream_response_time
大,因为用户网络较差,或者传递数据较大时,前者会耗时大很多
实例:统计耗时接口,列出传输时间超过 2秒的接口和其次数,显示前5条
cat time_temp.log|awk '($NF > 2){print$7}'|sort -n|uniq -c|sort -nr|head -5
$NF 表示最后一列 (当然这里也没有处理接口的参数问题)
完善的后的接口,处理接口参数后
awk '($NF>2){print $7}' access_temp.log|awk -F"?" '{print $1}'|sort|uniq -c|sort -rn|head -n 20
3.3.4 根据access.log获取pv(访问量)和uv(用户量)数据
PV(访问量):即Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次。
UV(独立访客)(用户量):即Unique Visitor,访问您网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只被计算一次。
1 我们可以根据accesslog中访问的uri(接口)数量(次数)去统计PV(访问量)
awk '{print $7}' access_temp.log|awk -F"?" '{print $1}'|sort|uniq -c|sort -rn| wc -l
2 我们可以根据accesslog中的访问的ip数量去统计PV(用户量)
awk '{print $1}' access_temp.log | wc –l
3 获取日志中所有每分钟请求的数量
cat access.log | awk '{print substr($4,14,5)}' | uniq -c | awk '{print $2","$1}' > access.txt
完整配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
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 /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
server {
listen 80;
server_name xxrtest.com;
proxy_cache_path /root/cache levels=1:2 keys_zone=xd_mystatic:30h max_size=1g inactive=30h use_temp_path=off;
location /static/ {
#使用Nginx的客户端缓存(浏览器缓存)缓存静态资源数据
expires 30d;
root /usr/share/nginx/html;
#静态资源存储在这个目录中,我们一般给这个目录做一个文件挂载
# 当我们请求是http://xxrtest.com/static/css/base.css 等(还有JS,img)的时候时会去获取/usr/share/nginx/html/static/css/base.css 目录中的css文件,注意这个目录路径在创建时中一定要带static否则会出现找不到文件的情况,
}
location / { #因为要考虑路径拦截的顺序问题所以将 /放在后面
root /usr/share/nginx/html;
index index.html;
}
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
1 利用虚拟主机server块把多个不同域名的网站部署在同一台服务器上,节省了服务器硬件成本和相关的维护费用。
方式1 : 使用多个server块,每个server块的 server_name 不同
server {
listen 80;
server_name xxrtest.com;
location /static/ {
root /usr/share/nginx/html;
}
location / {
root /usr/share/nginx/html;
index index.html;
}
}
server {
listen 80;
server_name xdclass.com;
location /static/ {
root /usr/share/nginx/html;
}
location / {
root /usr/share/nginx/html;
index xdclassindex.html;
}
}
4.1 Nginx负载均衡实例代码
upstream gateway {
server 172.30.193.38:9088;
server 172.30.193.38:9089;
}
server {
listen 9001;
server_name 118.31.13.73;
location / {
#设置被代理服务器的真实地址
proxy_pass http://gateway/;
}
}
4.2 Nginx常见的负载均衡策略
4.2.1节点轮询(默认)(使用的少)
简介:每个请求按顺序分配到不同的后端服务器 (使用的比较少)
场景:会造成可靠性低(一旦轮询到的那个节点挂了)和负载分配不均衡(由于机器性能的差异),适合静态文件服务器
4.2.2 Weight权重配置(使用的多)
简介:weight和访问比率成正比,数字越大,分配得到的流量越高
场景:服务器性能差异大的情况使用
upstream gateway {
server 172.30.193.38:9088 weight=5;
server 172.30.193.38:9089 weight=10;
}
4.2.3 ip_hash(固定分发)(使用本地缓存的项目必须使用这个)
简介:根据用户请求的访问ip的hash结果分配(进行负载君合),这样每个用户就可以固定访问一个后端服务器
场景:服务器业务分区、业务缓存(本地缓存)、Session需要单点的情况,
注意:当我们的业务使用本地缓存时,我们必须使用这个,不然在集群情况下本地缓存失效,和本地缓存数据不一致的概率非常大。
Upstream gateway {
ip_hash;
server 172.30.193.38:9088;
server 172.30.193.38:9089;
}
4.2.4 upstream还可以为每个节点设置状态值
down 表示当前的server暂时不参与负载
server 192.168.159.133:8080 down;
backup 其它所有的非backup机器down的时候,会请求backup机器,这台机器压力会最轻,配置也会相对低,这是一个备用的服务器,我们一般都会设置
server 192.168.159.133:8080 backup;
如果某个应用节点挂了,请求不应该继续分发到这个应用节点中
max_fails 允许请求失败的次数,默认为1.当超过最大次数时就暂时不会请求该节点的应用
fail_timeout : max_fails次失败后,暂停请求某节点的时间,默认:fail_timeout为10s,过了这个时间只会,会继续进行尝试请求(与熔断策略很像)如果成功的话就复活该节点
参数解释
max_fails=N 设定Nginx与后端节点通信的尝试失败的次数。
在fail_timeout参数定义的时间内,如果失败的次数达到此值,这个节点就暂时不可用在定义的时间内。在下一个fail_timeout时间段到来前,这个节点服务器不会再被尝试。
失败的尝试次数默认是1,如果设为0就会停止统计尝试次数,认为服务器是一直可用的。
具体什么是nginx认为的失败呢
可以通过指令proxy_next_upstream来配置什么是失败。
注意默认配置时,http_404状态,不会被认为是请求失败的。
proxy_next_upstream error timeout http_500 http_503 http_404;
//注意:实际项目中为防止他人恶意攻击导致(错落的请求路径,但是我们的服务器却是好的)我们全部的节点不可用,一般不设置 http_404
upstream gateway {
ip_hash;
server 192.168.0.106:8080 max_fails=2 fail_timeout=60s ;
server 192.168.0.106:8081 max_fails=2 fail_timeout=60s;
}
location / {
proxy_pass http://gateway/;
proxy_next_upstream error timeout http_500 http_503 http_404;
}
案例实操
暂停一个后节点,然后访问接口大于10次,Nginx会把 这个节点剔除
重启这个节点,在fail_timeout周期里面不会再获取流 量
简介:Nginx自定义全局异常json数据
任何接口都是可能出错,4xx、5xx等
如果业务没有做好统一的错误管理,直接暴露给用户,无疑是看不懂,不过实际项目中500的错误,后端基本全部会做好统一的错误管理,但是400的错误如404,403等却没法统一做
所以假如后端某个业务出错,nginx层也需要进行转换,让前端知道Http响应是200,其实是将错误的状态码定向至200,返回了全局兜底数据(不管后端出什么错误,最终用户见到的都是200的响应,但是在4xx时,5xx会有错误提示)
server {
listen 80;
server_name xdclass.com;
location / {
proxy_pass http://gateway/;
##开启错误拦截配置,一定要开启
proxy_intercept_errors on;
}
# 我们还可以设置多种错误状态码的不同返回
error_page 403 =200 /defaultError403Api;
location = /defaultError403Api {
default_type application/json;
return 200 '{"code":"-1","msg":"请求的资源不允许访问,没有对应的权限 "}';
}
error_page 404 =200 /defaultError404Api;
location = /defaultError404Api {
default_type application/json;
return 200 '{"code":"-1","msg":"页面不存在或接口不存在请检查请求路径 "}';
}
}
1 docker 安装的nginx 进行热加载
docker exec -it 683ca3c9abe0 bash -c 'nginx -s reload'
2 源码编译安装的nginx
./nginx -s reload
网络攻击时有发生,
TCP洪水攻击、注入攻击、DOS等比较难防的有DDOS等
数据安全,防止对手爬虫恶意爬取,
解决方法:一般就是封禁ip
linux server的层面封IP:iptables
nginx的层面封IP方式多种 (但 req还是会打进来, 让nginx 返回 403, 占用资源)
Nginx作为网关,可以有效的封禁ip
4.7.1Nginx手动封禁IP
单独网站屏蔽IP的方法,把deny放在server{}语句块,虚拟主机块
所有网站屏蔽IP的方法,把deny {}放在http语句块。
如deny 192.168.159.2;
也可以使用配置参数在location中
location {
...
#限制每ip每秒不超过20个请求,漏桶数burst为5
#brust的意思就是当每秒超过20个请求时,5个以内的请求会被延迟访问,超过5个的直接返回503
#nodelay,设置该选项,将严格使用平均速率限制请求数,超过请求频率的直接返回503
limit_req zone=happy burst=5 nodelay;
}
4.7.2拓展-Nginx自动化封禁ip思路和实现脚本
编写shell脚本
AWK统计access.log,记录每分钟访问超过60次的ip要结合日志切割,然后配合nginx或者iptables进行封禁
crontab定时跑脚本
脚本如下
#!/bin/bash
#AWK统计access.log,记录每分钟访问超过60次的ip到deny.conf配置文件中deny.conf配置文件已经包含在nginx.conf中了
#(输入形式是 deny ip ;)
awk '{print $1}' access.log | sort |uniq -c | sort -rn | awk '{if($1>60) print "deny "$2";"}'>>/tmp/nginx/conf/deny.conf
#nginx日志路径(定义变量)
logs_path=/tmp/nginx/log
lastminute=$(date -d 'yesterday' +%Y-%m-%d+%H:%M)
#移动日志并以日期改名
#${变量名}—表示使用变量
mv ${logs_path}/access.log ${logs_path}/accesslog_dir/access_${lastminute}.log
mv ${logs_path}/error.log ${logs_path}/errorlog_dir/error_${lastminute}.log
#向nginx主进程发送信号,重新生成日志文件(因为日志文件被我们改名移动了,nginx不会自己生成日志文件,所以我们要向nginx主进程发送信号(即向主进程PID发信号即可),重新生成日志文件,不然会丢失日志信息-- nginx.pid与Nginx主进程pid一模一样)
# ps -ef |grep nginx #查看nignx进程
kill -USR1 $(ps -ef |grep nginx |awk 'NR==1 {print $2}')
#热加载Nginx
docker exec -it xdclass-nginx bash -c 'nginx -s reload'
使用定时任务(每分钟执行)
跨域:浏览器同源策略 1995年,同源政策由 Netscape
公司引入浏览器。目前,所有浏览器都实行这个政策。 最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"
1 协议相同 http https
2 域名(ip)相同 www.xdclass.net
3 端口相同 80 81
一句话:浏览器从一个域名的网页去请求另一个域名的资源
时,域名(ip)、端口、协议任一不同,都是跨域(跨域在默认情况下会无法访问)
浏览器控制台跨域提示:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
解决方法
1 JSONP
2 Http响应头配置允许跨域(使用的多)
nginx层配置(更加方便统一)
程序代码(JAVA)中处理通过拦截器配置
Nginx开启跨域配置,location下配置(当然有时候我们是有些接口允许跨域有些不允许(即在有些location上配置跨域有些不配置即可),但是对于微服务项目,网关是唯一请求入口,所以是统一做跨域处理,静态资源一般不做跨域处理)
location / {
# 允许跨域的源 * 代表所有 若考虑到安全性,也可以指定访问来源请求的域
add_header 'Access-Control-Allow- Origin' $http_origin;
# 是否允许发送cookie
add_header 'Access-Control-Allow- Credentials' 'true';
#允许携带的请求头
add_header'Access-Control-Allow-Headers''DNT,web-token,token,Token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If- Modified-Since,Cache-Control,Content- Type,Range';
#允许跨域的请求方法
add_header Access-Control-Allow- Methods 'GET,POST,OPTIONS,DELETE';
#如果预检请求则返回成功,不需要转发到后端
if ($request_method = 'OPTIONS') #注意=两边都有一个空格
{
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 200;
}
}
#允许跨域请求的域,* 代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET,POST,PUT,DELETE
add_header 'Access-Control-Allow-Methods' *;
Nginx配置重定向的应用场景
1非法访问跳转,防盗站、(防止其他人盗用我们己网站的链接,或者静态资源,显示到他的网站上去,如果被盗的话消耗还是我们自己的资源)(用的多)
2 更换新域名(还是可以输入老域名,但是会重定向到新域名中来)(用的多)
3 http跳转https(用的多)
4 不同地址访问同一个虚拟主机的资源
Nginx重写-重定向的概念
rewrite 地址重定向,实现URL重定向的重要指令,他根据regex(正则表达式)来匹配内容跳转
语法 rewrite regex replacement[flag]
rewrite ^/(.*) https://xdclass.net/$1 permanent (即我们访问任务地址都会跳转到任何https://xdclass.net中去)
# 这是一个正则表达式,匹配完整的域名和后面的路径地址
# replacement部分是https://xdclass.net/$1,$1
是取自regex部分()里的内容
[flag]是指重定向的形式
常用正则表达式
字符 |
描述 |
^ |
匹配输入字符串的起始位置 |
$ |
匹配输入字符串的结束位置 |
* |
匹配前面的字符零次或者多次 |
+ |
匹配前面字符串一次或者多次 |
? |
匹配前面字符串的零次或者一次 |
. |
匹配除“\n”之外的所有单个字符 |
(pattern) |
匹配括号内的pattern |
rewrite 最后一项flag参数
标记符号 |
说明 |
last |
本条规则匹配完成后继续向下匹配新的 location URI规则 |
break |
本条规则匹配完成后终止,不在匹配任何规则 |
redirect |
返回302临时重定向 |
permanent |
返回301永久重定向 |
Nginx配定向的实战--配置防盗链
location / {
#是指请求的来源,如果我们直接打开域名浏览的时就重定向到首页(防止别人知道了我们资源的链接就来盗取资源,只有从首页去访问域名时才会正常跳转,nginx不支持else,如浏览器直接访问小滴课堂&旭瑶没有用还是会重定向到小滴课堂&旭瑶这样别人无法直接使用我们的资源了)
if ($http_referer = '-')
{ rewrite ^/(.*) https://xdclass.net/$1 permanent;
}
if ($http_referer = ' https://xdclass.net')
{ proxy_pass http://gateway/;
}
rewrite ^/(.*) https://xdclass.net/$1 permanent;
}
正则
^ 以什么开始
$ 以什么结束
^/api/user$ #表示用以/api开头 以user结尾。
location 路径匹配
语法 location [ = | ~ | ~* | ^~ ] uri { }
1 location = /uri =表示精准匹配,只要完全匹配上才能生效(一般不用)
2 location /uri 不带任何修饰符,表示前缀匹配(用的最多,也是默认使用的)
3 location ^~ /uri/ 匹配任何已 /uri/开头的任何查询并且停止搜索
4 location / 通用匹配,任何未匹配到其他location的请求都会匹配到(为了不影响其他location我们会把它放在最后面)
5 正则匹配
区分大小写匹配(~) 不区分大小写匹配(~*)放在最前面 如~^/api/pub$
匹配规则的优先级(不要写复杂,容易出问题和遗忘)
精准匹配 > 字符串匹配(前缀匹配)(若有多个匹配项匹配成功,那么选择匹配长的并记录) > 正则匹配
(注意:
1 当有多个相同语法的location时,会先匹配放在前面的location,每个请求最多匹配一个location
2 当然为了开发方便一个项目中最好只使用一种匹配语法 )
案例
server {
server_name xdclass.net;
location ~^/api/pub$
{
}
}
^/api/pub$这个正则表达式表示uri字符串必须以/开始,以b结束不能多加一个/在最后,中间必须是/api/pub,后面可以加参数
http://xdclass.net/api/v1 匹配(完全匹配)
http://xdclass.net/API/PUB 不匹配,大小写敏感
http://xdclass.net/api/pub?key1=value1 匹配
http://xdclass.net/api/pub/ 不匹配
http://xdclass.net/api/public 不匹配,不能匹配正则表达式
测试
location = /img/test.png {
return 1;
}
location /img/test.png {
return 2;
}
location ^~/img/
{
return 3;
}
location = / {
return 4;
}
location = / {
return 4;
}
简介:讲解Nginx 端缓存核心配置
常见的开发人员控制的缓存分类
1 数据库缓存
2 应用程序缓存 –分布式缓存,本地缓存
3 Nginx网关缓存 (性能比Redis更好甚至比后端本地缓存更好,因为更靠近用户,速度会更快)
4前端缓存
注意:
1 Nginx缓存让后端结果缓存离用户更进一步(会有比redis更好的效果)
2 默认情况下GET请求及HEAD请求会被缓存,而POST请求不会被缓存,并非全部都要缓存,可以过滤部分路径不用缓存
3 Nginx 是一个缓存热点数据且不易改变数据的最好选择,但是呢对数据一致性较高的数据,或者经常改变的数据不要使用这个(一般就是那一些一成不变的数据,或者如果要改变但是改变的频率不高的数据),因为Nginx不方便更新缓存,Nginx缓存的时间尽量不要太长。当缓存的数据是后端接口的数据尽量使用proxy_cache_valid这个去设置缓存过期时间不要使用Inactive它容易造成数据不一致,当缓存的数据是静态文件数据时可以使用Inactive
使用场景:通常对于静态资源,即较少经常更新的资源,如图片,css或js等进行缓存,从而在每次刷新浏览器的时候,不用重新请求,而是从缓存里面读取(因为这些静态资源数据基本固定不变,我们 往往可以使用更进一步的Nginx客户端缓存expires,这样配置起来更方便),这样就可以减轻服务器的压力,此外那些获取固定数据的接口,还有获取首页图片,分类数据的接口也可以使用Nginx缓存,注意不应是所有的接口都做Nginx缓存。
核心配置
1 /root/cache
本地路径,用来设置Nginx缓存资源的存放地址
2 levels=1:2
默认所有缓存文件都放在上面指定的根路径中,可能影响缓存的性能,推荐指定为 2 级目录来存储缓存文件;1和2表示用1位和2位16进制来命名目录名称。第一级目录用1位16进制命名,如a;第二级目录用2位16进制命名,如3a。所以此例中一级目录有16个,二级目录有16*16=256个,总目录数为16 * 256=4096个。
当levels=1:1:1时,表示是三级目录,且每级目录数均为16个
3 key_zone (key空间)(设置key空间和其大小)
在共享内存中定义一块存储区域来存放缓存的 key和 metadata(缓存的使用次数,过期时间等)
4 max_size(推荐1G)
最大缓存空间,如果不指定会使用掉所有磁盘空间。当达到disk上限后,会删除最少使用的cache
5 Inactive(类似于缓存过期时间,但是如果在指定时间内访问了,就会重新计时,如果超过这个时间还没有进行访问,则将会从缓存中删除)(为了数据的一致性考虑一般不使用这个)
某个缓存在inactive指定的时间内如果不访问,将会从缓存中删除
6 proxy_cache_valid (缓存的过期时间)(优先级低于Inactive)
配置nginx cache中的缓存文件的缓存时间
,proxy_cache_valid 200 304 2m 对于响应状态为200 和304的请求缓存文件的缓存时间是2分钟
nginx缓存过期影响的优先级进行排序为:inactvie >(浏览器缓存)源服务器端Expires/max-age > proxy_cache_valid
7use_temp_path (使用临时文件夹)建议为 off,则 nginx会将缓存文件直接写入指定的cache 文件中
8 proxy_cache
启用proxy cache,并指定key_zone,如果proxy_cache off表示关闭掉缓存
如proxy_cache xd_cache
9 add_header Nging-Cache "$upstream_cache_status" (可以用于统计Nginx缓存是否命中的)
用于前端判断是否是缓存,miss(不命中)、hit(命中)、expired(缓存过期)、updating(更新,使用旧的应答))
10 proxy_cache_min_uses
指定请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存。
proxy_cache_path /root/cache levels=1:2 keys_zone=xd_cache:2m max_size=1g inactive=1m use_temp_path=off;
实例
server {
location /{
...
proxy_cache xd_cache;
proxy_cache_valid 200 304 1m;
proxy_cache_valid 404 1m;
proxy_cache_key $host$uri$is_args$args; #缓存key的规则这里写的是主机+uri+参数
proxy_cache_min_uses 3 #请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存
add_header Nginx-Cache "$upstream_cache_status";
}
}
还原nginx配置,只保留upstream模块
配置实操
请求后端json接口,通过控制台日志判断是否有到后端服务
注意:
1 nginx缓存过期影响的优先级进行排序为:inactvie >源服务器端Expires/max-age > proxy_cache_valid
2 如果出现 Permission denied 修改nginx.conf,将第一行修改为 user root(提高Nginx的权限)
3 默认情况下GET请求及HEAD请求会被缓存,而POST请求不会被缓存,并非全部都要缓存,可以过滤部分路径不用缓存
proxy_cache_path /root/cache levels=1:2 keys_zone=xd_cache:2m max_size=1g inactive=1m use_temp_path=off;
server {
location /{
...
//注意实际开发项目中我们不可能对所有的Get请求都去做Nginx缓存,只有部分接口做Nginx缓存
所有就要定制化设计
if ($uri = '/api/getdata') #//只有/api/getdata接口做缓存
{
proxy_cache xd_cache;
proxy_cache_valid 200 304 1m;
proxy_cache_valid 404 1m;
proxy_cache_key $host$uri$is_args$args;
#缓存key的规则这里写的是主机+uri+参数
#$is_args 表示请求中的URL是否带参数,如果带参数,$is_args值为"?"。如果不带参数,则是空字符串 $args HTTP请求中的完整参数(包括所有参数)
add_header Nginx-Cache "$upstream_cache_status";
proxy_pass http://gateway/;
}
}
}
缓存清空
1直接rm删除
2 ngx_cache_purge
缓存命中率统计方式
1 前端打点日志上报
2 Nginx access.log日志模板增加信息$upstream_cache_status
然后利用AWK获取所有的hit的请求,并统计数
Nginx的expires(Nginx的客户端缓存)
nginx缓存的设置可以提高网站性能,对于网站的图片,尤其是新闻网站,图片一旦发布,改动的可能是非常小的,为了减小对服务器请求的压力,提高用户浏览速度,我们可以通过设置nginx中的expires(Nginx的客户端缓存比Nginx的proxy_cache距离用户更近更快),让用户访问一次后,将图片缓存在用户的浏览器中,且时间比较长的缓存。
原理:当nginx设置了expires后,例如设置为:expires 10d; 那么,所在的location或if的内容,用户在10天内请求的时候,都只会访问浏览器中的缓存,而不会去请求nginx。
注:需要注意的是,这种缓存方式只能在用户不对浏览器强制刷新的情况下生效,如果用户通过url来进行访问,是可以访问到缓存的。
举例查看网站图片的缓存时间:
server{
location /static{
expires 30d;
root /usr/share/nginx/html;
}
针对于Nginx上配置的静态资源服务器-静态资源压缩
简介:讲解Nginx的压缩配置和实操
对文本、js和css,文件等进行压缩(已经压缩过了的图片如 gif,jpg 等是没有效果的),一般是压缩后的大小是原始大小的25%,
压缩后的内容可以获得更快的网络传输速度(减少了带宽消耗),响应时间是得到了优化
常用的压缩配置
#开启gzip,减少我们发送的数据量
gzip on;
# 文件最小为1k才会进行压缩
gzip_min_length 1k;
#4个单位为16k的内存作为压缩结果流缓存
gzip_buffers 4 16k;
#gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
gzip_comp_level 4;
#压缩的类型 注意对已经压缩过了的图片如 gif,jpg 等是没有效果的,
gzip_types application/javascript text/plain text/css application/json application/xml text/javascript image/jpeg image/gif image/png;
#给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
gzip_vary on;
#禁用IE6以下的gzip压缩,IE某些版本对gzip的压缩支持很不好
gzip_disable "MSIE [1-6].";
压缩前后区别(上传js文件进行验证)
location /static { alias /usr/local/software/static; } |
面试题:压缩是时间换空间,还是空间换时间?
web层主要涉及浏览器和服务器的网络交互,而网络交互显然是耗费时间的,
我们要尽量减少交互次数,降低每次请求或响应数据量。
开启压缩
在服务端是时间换空间的策略,Nginx服务端需要牺牲时间进行压缩以减小响应数据大小
在客户端的角度:压缩后的内容可以获得更快的网络传输速度(减少了带宽消耗),响应时间是得到了优化
所以是双向的(时间)
user root; #默认情况下是user nginx 在某些情况下因为权限问题会报错,故要修改
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
use epoll; #默认初始配置中时没有的我们可以加上以提高性能,使用epoll事件模型
worker_connections 1024; #每个工作进程的最大连接数(生产环境中建议设置超过9000)
}
http {
include /etc/nginx/mime.types;
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" "$request_time” ';
access_log /var/log/nginx/access.log main; #可以指定具体使用哪个文件去存储日志信息
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
upstream gateway {
ip_hash;
server 172.30.193.38:9088 max_fails=2 fail_timeout=60s ;;
server 172.30.193.38:9089 max_fails=2 fail_timeout=60s ;;
}
#开启gzip,减少我们发送的数据量
gzip on;
# 文件最小为1k才会进行压缩
gzip_min_length 1k;
#4个单位为16k的内存作为压缩结果流缓存
gzip_buffers 4 16k;
#gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
gzip_comp_level 4;
#压缩的类型 注意对已经压缩过了的图片如 gif,jpg 等是没有效果的,
gzip_types application/javascript text/plain text/css application/json application/xml text/javascript image/jpeg image/gif image/png;
#给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
gzip_vary on;
#禁用IE6以下的gzip压缩,IE某些版本对gzip的压缩支持很不好
gzip_disable "MSIE [1-6].";
server {
listen 80;
server_name xxrtest.com;
location /static/ {
root /usr/share/nginx/html;
}
proxy_cache_path /root/cache levels=1:2 keys_zone=xd_cache:1m max_size=1g use_temp_path=off;
location / {
#Nginx端缓存的配置
proxy_cache xd_cache;
proxy_cache_valid 200 304 30s;
proxy_cache_valid 404 1m;
proxy_cache_key $host$uri$is_args$args;
#缓存key的规则这里写的是主机+uri+参数
#$is_args 表示请求中的URL是否带参数,如果带参数,$is_args值为"?"。如果不带参数,则是空字符串 $args HTTP请求中的#完整参数(包括所有参数)
proxy_cache_min_uses 3 #请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存
add_header Nginx-Cache "$upstream_cache_status";
proxy_pass http://gateway/;
# 存放用户的真实ip,这样后端才可以获取到用户的真实Ip
ip proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 设置什么才是请求失败
proxy_next_upstream error timeout http_500 http_503;
#开启错误拦截配置,一定要开启
proxy_intercept_errors on;
#允许跨域请求的域,* 代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET,POST,PUT,DELETE
add_header 'Access-Control-Allow-Methods' *;
#如果预检请求则返回成功,不需要转发到后端
I f ($request_method = 'OPTIONS') #注意=两边都有一个空格
{
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 200;
}
}
# 我们还可以设置多种错误状态码的不同返回
error_page 403 =200 /defaultError403Api;
location = /defaultError403Api {
default_type application/json;
return 200 '{"code":"-1","msg":"请求的资源不允许访问,没有对应的权限 "}';
}
error_page 404 =200 /defaultError404Api;
location = /defaultError404Api {
default_type application/json;
return 200 '{"code":"-1","msg":"页面不存在或接口不存在请检查请求路径 "}';
}
}
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
简介: 介绍什么是https,使用的好处
什么是Https,和http的区别
HTTPS (Secure Hypertext Transfer Protocol)安全超文本传输协议,是身披SSL外壳的HTTP
HTTPS是一种通过计算机网络进行安全通信的传输协 议,经由HTTP进行通信,利用SSL/TLS
建立安全信道,加 密数据包。
为什么要用呢
HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传 输、身份认证的网络协议,要比 HTTP 协议安全,可防止数据在传输过程中被窃取、改变,确保数据的完整性
但是不是百分百安全的
加密流程
秘钥交换使用非对称加密(更安全),内容传输使用对称加密的方式
1 客户端(浏览器)向服务器发送请求,2服务端会生成公钥和私钥,3把SSL证书和公钥返回客户端(浏览器)
4 浏览器验证SSL证书是否有效,如果无效,则浏览器会提示该网站有风险,如果验证成功,则会生成随机的对称秘钥(一把公钥,一把私钥),
5客户端使用对称秘钥中的公钥把服务端返回的公钥进行加密并传输给服务端
6服务端使用自己生成的秘钥对第5步的数据进行解密,从而拿到对称秘钥(公钥的)明文
7 服务端响应数据时,会把客户端公钥的明文返回。
8 客户端使用客户端私钥检测第7步返回的客户端秘钥是否正确。
核心:这样服务端与客户端就交换了自己的公钥,这样服务端就可以对客户端发来的数据进行检查,是否被篡改,客户端也能检查副段响应的数据是否被篡改
简介: 介绍Nginx的扩展 整合框架OpenResty
7.1.1什么是OpenResty, 为什么要用OpenResty?
OpenResty:是基于Ngnix和Lua的高性能web平台(使用OpenResty就能使用Nginx中的所有功能(里面内嵌了Nginx),但是它比Nginx更加强大,集成了非常多的功能),内部集成精良的LUa库、第三方模块、依赖, 开发者可以方便搭建能够处理高并发、扩展性极高的动态web应用、web服务、动态网关。
OpenResty将Nginx核心、LuaJIT、许多有用的Lua库和Nginx第三方模块打包在一起
为什么要用OpenResty?
1 Nginx是C语言开发,如果要二次扩展是很麻烦的(因为C语言难度高),而基于OpenResty,开发人员可以使用 Lua 编程语言对 Nginx 核心模块进行二次开发拓展
2 性能强大,OpenResty可以快速构造出1万以上并发连接响应的超高性能Web应用系统(性能超过Ngixn)
官网:http://openresty.org
阿里、腾讯、新浪、酷狗音乐等都是 OpenResty 的深度用户
7.1.2 OpenResty拓展
让Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL, Memcaches 以及 Redis 等都进行一致的高性能响应。所以对于一些高性能的服务来说,可以直接使用 OpenResty 访问 Mysql或Redis等,而不需要通过第三方语言(JAVA,PHP、Python、Ruby)等来访问数据库再返回,这大大提高了应用的性能
7.1.3 Lua脚本介绍
官网:Lua: getting started
Lua 由标准 C 编写而成,没有提供强大的库,但可以很容易的被 C/C++ 代码调用,也可以反过来调用 C/C++ 的函数。
在应用程序中可以被广泛应用,不过Lua是一种脚本/动态语言,不适合业务逻辑比较重的场景(如电商平台,因为没有强大的类库),适合小巧的应用场景,代码行数保持在几十行到几千行。
LuaJIT 是采用 C 和汇编语言编写的 Lua 解释器与即时编译器。(快速的执行lua脚本)
7.1.4什么是ngx_lua
ngx_lua是Nginx的一个模块,将Lua嵌入到Nginx中,从而可以使用Lua来编写脚本,并且部署到Nginx中运行,
即Nginx变成了一个Web容器;开发人员可以在nginx中使用Lua语言开发高性能Web应用了。
OpenResty提供了常用的ngx_lua开发模块
lua-resty-memcached
lua-resty-mysql(在Nginx中直接访问mysql)
lua-resty-redis(在Nginx中直接访问redis)
lua-resty-dns
lua-resty-limit-traffic (对Nginx进行限流)
通过上述的模块,可以用来操作 mysql数据库、redis、memcached等,也可以自定义模块满足其他业务需求,
很多经典的应用,比如开发缓存前置、数据过滤、API请求聚合、AB测试、灰度发布、降级、监控、限流、防火墙、黑白名单等
7.2.1 简介:OpenResty和Lua相关环境准备
当我们安装好OpenResty之后我们可以发现,OpenResty就是一个Nginx但是里面集成了Lua和一些相关模块和依赖
OpenResty安装 下载:http://openresty.org/en/linux-packages.html #centos
# add the yum repo:
wget https://openresty.org/package/centos/openresty. repo
sudo mv openresty.repo /etc/yum.repos.d/
# update the yum index:
sudo yum check-update
sudo yum install openresty
#安装命令行工具
sudo yum install openresty-resty
# 列出所有 openresty 仓库里的软件包
sudo yum --disablerepo="*" -- enablerepo="openresty" list available
#查看版本
resty –V
docker安装OpenResty
1 docker pull openresty/openresty
2 docker run -idt --name openresty -p 80:80 openresty/openresty
3 mkdir -p /data/openresty/conf
4 docker cp openresty:/usr/local/openresty/nginx/conf/nginx.conf /data/openresty/conf
5 docker rm –f openresty
6
docker run -itd -p 80:80 --name openresty --restart always -v /data/openresty/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf -v /etc/localtime:/etc/localtime -v /data/openresty/html:/usr/local/openresty/nginx/html 28ccc9f564cd
简介: 讲解Nginx+OpenRestry开发第一个例子
Nginx+OpenRestry开发
在Nginx中使用Lua打印输出一段话
方式1 使用LUA代码块的方式(不方便一旦Lua代码多一点)content_by_lua_block
server{
# 监听端口
listen 80;
# 配置请求的路由
location /{
default_type text/html;
content_by_lua_block{
ngx.say("hello world; xdclass.net 小滴课堂");
}
}
方式2 使用lua文件的方式(一般使用这种,把Lua脚本写在一个文件中)content_by_lua_file
#使用其他方式http
{
还需要配置lua文件扫描路径
lua_package_path "$prefix/lualib/?.lua;;"; lua_package_cpath "$prefix/lualib/?.so;;";
server{
# 监听端口
listen 80;
# 配置请求的路由
location /{
default_type text/html;
content_by_lua_file lua/xdclass.lua;
}
简介: 讲解Nginx+OpenRestry常见基础知识
7.4.1 nginx内置全局变量
nginx提供丰富的内置变量, openresty里面使用参考下面的文档
https://github.com/openresty/lua-nginx-module#n gxvarvariable
部分变量是可以被修改的,部分是不给修改
如果openresty的lua中使用nginx内置全局变量则是 ngx.var.全局变量名(不加$)
名称 |
说明 |
$arg_name |
请求中的name参数 |
$args |
请求中的参数(多个的话都会显示) |
$content_length |
HTTP请求信息里的"Content-Length" |
$content_type |
请求信息里的"Content-Type" |
$host |
请求信息中的"Host",如果请求中没有Host 行,则等于设置的服务器名 |
$hostname |
机器名使用 gethostname系统调用的值 |
$http_cookie |
cookie 信息 |
$http_referer |
引用地址 |
$http_user_agent |
客户端代理信息 |
$http_via |
最后一个访问服务器的Ip地址。 |
$http_x_forwarded_for |
相当于网络访问路径 |
$is_args |
如果请求行带有参数,返回“?”,否则返回空字符串 |
$limit_rate |
对连接速率的限制 |
$nginx_version |
当前运行的nginx版本号 |
$pid |
worker进程的PID |
$query_string |
与$args相同 |
$remote_addr |
客户端IP地址 |
$remote_port |
客户端端口号 |
$request |
用户请求 |
$request_method |
请求的方法,比如"GET"、"POST"等 |
$request_uri |
请求的URI,带参数 |
$scheme |
所用的协议,比如http或者是https |
$server_name |
请求到达的服务器名 |
$server_port |
请求到达的服务器端口号 |
$server_protocol |
请求的协议版本,"HTTP/1.0"或"HTTP/1.1" |
$uri |
请求的URI,可能和最初的值有不同,比如经过重定向之类的 |
7.4.2Nginx 请求阶段划分
nginx对于请求的处理分多个阶段,从而让第三方模块(lua)通过挂载行为在不同的阶段来控制请求的处理,
大致如下,以及相关指令
1 初始化阶段(Initialization Phase)(初始化一些参数)
init_by_lua_file
init_worker_by_lua_file
2 重写与访问阶段(Rewrite / Access Phase)(用于限流,黑名单,防火墙等)(业务中用的多)
rewrite_by_lua_file
access_by_lua_file 文件访问
3 内容生成阶段(Content Phase)(业务中用的多)
content_by_lua_file
4 日志记录阶段(Log Phase)
简介: 讲解Nginx+OpenRestry开发网络访问限制
1 生产环境-管理后台一般需要指定的网络才可以访问,网 段/ip等(为了安全不是所有的人都可以访问管理后台,只有部分人可以访问,指定部分的IP可以访问即可)
2 ECS安全组:只有指定的端口的才可以访问
http{
# 这里设置为 off,是为了避免每次修改之后都要重新reload 的麻烦。
# 在生产环境上需要 lua_code_cache 设置成 on。
lua_code_cache off;
# lua_package_path可以配置openresty的文件寻址路径,
$PREFIX 为openresty安装路径
# 文件名使用“?”作为通配符,多个路径使用“;”分隔,默认的查找路径用“;;”
# 设置纯 Lua 扩展库的搜寻路径
lua_package_path "$prefix/lualib/?.lua;;";
# 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;')
lua_package_cpath "$prefix/lualib/?.so;;";
server {
location / {
access_by_lua_file lua/white_ip_list.lua; proxy_pass
http://lbs;
}
}
内网访问限制和ECS安全组的lua代码
设置访问黑名单
lua/ black _ip_list.lua
local black_ips = {["127.0.0.1"]=true}
local ip = ngx.var.remote_addr
if true == black_ips[ip] then
ngx.exit(ngx.HTTP_FORBIDDEN)
return;
end
线上写我们肯定是指定只有部分IP可以访问
local white_ips = {["127.0.0.1","192.168.43.98"]=true}
local ip = ngx.var.remote_addr
if false== black_ips[ip] then
ngx.exit(ngx.HTTP_FORBIDDEN)
return;
end
阿里云ECS安全组
local white_port = {["430","8080"]=true}
local port = ngx.var.remote_ port
if false== black_ips[port] then
ngx.exit(ngx.HTTP_FORBIDDEN)
return;
end
简介: 讲解Nginx+OpenRestry开发下载限速
限速限流应用场景
下载限速:保护带宽及服务器的IO资源(以及带宽)
请求限流:防止恶意攻击,保护服务器及资源安全
(在Nginx端同时配置请求限流和恶意Ip封禁能够极大的避免恶意攻击)
限制某个用户在一个给定时间段内能够产生的HTTP 请求数
限流用在保护上游应用服务器不被在同一时刻的大量用户访问(这个功能与Sentinel类似)
openResty下载限速案例实操
Nginx 有一个 $limit_rate ,这个反映的是当前请求每秒能响应的字节数, 该字节数默认为配置文件中limit_rate指令的设值
#当前请求的响应上限是 每秒 300K 字节
location /download {
access_by_lua_block {
ngx.var.limit_rate = "300K"
}
#映射到这个路径下
alias /usr/local/software/app;
}
请求限流实操(重点)
(在Nginx端同时配置请求限流和恶意Ip封禁能够极大的避免恶意攻击)
nginx可以使用ngx_http_limit_req_module
模块的limit_req_zone
指令进行限流访问,防止用户恶意攻击刷爆服务器。(限制每个用户每秒能够产生的HTTP 请求数)ngx_http_limit_req_module
模块是nginx默认安装的,所以直接配置即可。
首先,在nginx.conf文件中的http
模块下配置:
limit_req_zone
$binary_remote_addr zone
=commonper:10m rate
=10r/s
;
limit_req_zone
$binary_remote_addr zone
=50per:10m rate
=50r/s
;
说明:
区域名称为commonper 和 50per(自定义),占用空间大小为10m,平均处理的请求频率不能超过每秒十次,50per的每秒50次。
我这里配置了两种不同规格的配置,用于子模块配置时可自由指定。
$binary_remote_addr
是$remote_addr
(客户端IP)的二进制格式,固定占用4个字节(可能是C语言的long类型长度)。
burst :是缓冲队列的长度,(当请求超过limit_req_zone
时多余的请求会进入缓存队列
)一旦缓存队列满了,就会直接提示客户端503错误。
nodelay :表示不延时,比如rate=5r/s,burst=10 那么来了15个请求,能一次搞定,但是如果超过了rate+ burst会报503错误,否则,就是此秒只能搞定5个请求。一般都是不延期的设置(即设置后严格执行limit_req_zone)。
limit_req_zone $binary_remote_addr zone=commonper:10m rate=1r/s;
location /test {
limit_req zone=commonper burst=5 nodelay;
default_type text/html;
content_by_lua_block{
ngx.say("hello world; xdclass.net 小滴课堂");
}
error_page 503 =200 /defaultError403Api;
location = /defaultError503Api {
default_type application/json;
return 200 '{"code":"-1","msg":"请求的太频繁"}';
}
下载限速实现原理
目的:限制下载速度,用的是漏桶原理和令牌桶原理
什么是漏桶算法
备注:如果是请求限流,请求先进入到漏桶里,漏桶以固定的速度出水,也就是处理请求,当水加的过快也就是请求过多,桶就会直接溢出,也就是请求被丢弃拒绝了,所以漏桶算法能强行限制数据的传输速率或请求数。限流的大小(漏桶漏洞的大小)决定出水速度( 处理速度永远都是固定的)
什么是令牌桶算法,(一般使用这种)
备注:只要突发并发量不高于桶里面存储的令牌数据, 就可以充分利用好机器网络资源,比漏桶算法更加能够利用好资源。(不仅实现限流,还能最大可能的利用好网络资源,并发大的时候能够利用好全部资源,请求小的时候,不多浪费资源,处理速度能快能慢)
如果桶内令牌数量小于被请求消耗的量,则产生的令牌的速度就是均匀(限流)处理请求的速度
简介:讲解Nginx单点问题剖析
全链路高可用之Nginx反向代理单点故障分析
dns轮训多个ip,假如某个nginx挂了,怎么办
Nginx集群架构(vip Virtual IP虚拟IP 虚拟IP和 ip漂移技术实现Nginx的高可用,LVS会虚拟出一个IP,用户以后直接去访问这个虚拟IP,这样多台Nginx机器,相对于用户而言就只有一台服务器)
至少需要两台机器+一台做LVS和Keepalived的主节点,一台做备用节点,主节点提供服务,一但主节
点挂了就备用节点提供服务(VIP 虚拟IP会漂移到备用节点上)(如果之后主节点又恢复使用了,则还是主节点提供服务)。Vip默认指向的是主节点,默认当我们访问VIP时,也就是访问主节点下的realServer(如
Nginx),所以以后就外部直接使用VIP不使用real ip
Nginx高可用解决方案-基础
国际标准化组织(ISO)制定的一个用于计算机或通信系统间
互联的标准体系。从低到高分别是:
物理层、数据链路层、网络层、传输层、会话层、表示层和
应用层(http层)
四层工作在OSI第四层 也就是传输层
七层工作在最高层,也就是应用层
F5、LVS(第四层负载 tcp)
用虚拟ip+port接收请求,再转发到对应的真实机器
HAproxy、Nginx(第七层负载)
用虚拟的url或主机名接收请求,再转向相应的处理服务器
简介:讲解业界主流高可用方案Linux虚拟服务器 LVS讲解
什么是LVS
LVS是Linux Virtual Server,Linux虚拟服务器,是一个虚拟的服务器集群系统
Linux2.4 内核以后,LVS 已经是 Linux 标准内核的一部分(无需安装)
LVS软件负载:解决的两个核心问题是:选谁、转发
(vip Virtual IP虚拟IP 虚拟IP漂移技术实现Nginx的高可用,LVS会虚拟出一个IP,用户以后直接去访问这个虚拟IP,这样多台Nginx机器,相对于用户而言就只有一台服务器)
至少需要两台机器+一台做LVS和Keepalived的主节点,一台最备用节点,主节点提供服务,一但主节
点挂了就备用节点提高工服务 Vip默认指向的是主节点
提供了10多种调度算法: 轮询、加权轮询、最小连接、目标地址散列、源地址散列等
三种负载均衡转发技术(一般只使用NAT或者DR,使用Docker进行不同数值端口映射时(如81:80)会出现无响应的状态,故此时使用端口映射时尽量相同如80:80)
NAT:数据进出都通过 LVS, LVS的Master既要处理客户端发起的请求,又要处理后台RealServer的响应信息,将RealServer响应的信息再转发给客户端, 容易成为整个集群系统性能的瓶颈; (支持任意系统且可以实现端口映射)。
DR: (直接路由)移花接木,最高效的负载均衡规则,前端的Master只处理客户端的请求,将请求转发给(Nginx集群),由后台的(Nginx集群)直接响应客户端,不再经过LVS的Master, 性能要优于LVS-NAT; 需要LVS和(Nginx)集群绑定同一个VIP(支持多数系统,不可以实现端口映射)。
TUNL:隧道技术,LVS的Master只处理客户端的请 求,将请求转发给(Nginx集群),然后由后台的Nginx集群直接响应客户端,不再经过Master;(支持少数系统,不可以实现端口映射)。
简介:讲解业界主流高可用方案keepalived讲解
什么是keepalived
核心:监控并管理 LVS 集群系统中各个服务节点的状态
keepalived是一个类似于交换机制的软件,核心作用是检测服务器的状态,如果有一台web服务器工作出现故障, Keepalived将检测到并将有故障的服务器从系统中剔除,使用其他服务器代替该服务器的工作,当有故障服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成。
后来加入了vrrp(虚拟路由器冗余协议),除了为lvs提供高可用还可以为其他服务器提供高可用比如Nginx,Mysql、Haproxy等软件提供高可用
方案
docker安装keepalived
https://blog.csdn.net/weixin_41438870/article/details/10555814
yum安装
yum install -y keepalived
#安装路径
cd /etc/keepalived
启动和查看命令
service keepalived start
#停止
service keepalived stop
#查看状态
service keepalived status
#重启
service keepalived restart
#停止防火墙
systemctl stop firewalld.service
注意: 如果有缺少依赖可以执行下面的命令
yum |
install |
-y |
gcc |
yum |
install |
-y |
openssl-devel |
yum |
install |
-y |
libnl libnl-devel |
yum |
install |
-y |
libnfnetlink-devel |
yum |
install |
-y |
net-tools |
yum |
install |
-y |
vim wget |
注意: 如果有缺少依赖可以执行下面的命令
yum |
install |
-y |
gcc |
yum |
install |
-y |
openssl-devel |
yum |
install |
-y |
libnl libnl-devel |
yum |
install |
-y |
libnfnetlink-devel |
yum |
install |
-y |
net-tools |
yum |
install |
-y |
vim wget |
简介:Keepalived核心配置讲解
配置/etc/keepalived/keepalived.conf
分为3大模块。第一全局变量定义global_defs,2 vrrp_script主要用于健康检查及节点失败后执行的动作。3#配置对外提供服务的VIP vrrp_instance配置
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL # 设置lvs的id,主备节点在一个网络内应该是唯一的
enable_script_security #允许执行外部脚本
}
#配置vrrp_script,主要用于健康检查及节点失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败script"/usr/local/software/conf/chk_server.sh" #检查频率,以下配置每2秒检查1次
interval 2
#当检查失败后,将vrrp_instance的priority减小5
weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
fall 3
#连续监测2次成功,就认为成功。但不调整优先级rise 2
user root
}
#配置对外提供服务的VIP vrrp_instance配置
vrrp_instance VI_1 {
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级(备用节点要改)。
state MASTER
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
interface ens33
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
virtual_router_id 51
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER(备用节点要改)
priority 100
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
advert_int 1
#密码鉴权(防止有人恶意加入我们的VIP集群)
authentication {
auth_type PASS auth_pass 1111
}
#定义虚拟IP(VIP)为192.168.159.100,可多设,每行一个
virtual_ipaddress {
192.168.159.100
}
#本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
track_script {
chk_real_server
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.100 80 {
# 设置健康检查时间,单位是秒
delay_loop 6
# 设置负载调度的算法为rr轮询 ;
lb_algo rr
# 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
lb_kind NAT
# 会话保持时间
persistence_timeout 50
#指定转发协议类型(TCP、UDP)
protocol TCP
# 指定real server1(Nginx)的IP地址
(备用节点要改real_server 的ip)
real_server 192.168.43.98 81 {
# 配置节点权值,数字越大权重越高weight 1
# 健康检查方式
TCP_CHECK {
connect_timeout 10
retry 3 #重试次数
delay_before_retry 3 #重试间隔
connect_port 80 #连接端口
}
}
}
配置注意
router_id后面跟的自定义的ID在同一个网络下主备节点是一致的
state后跟的MASTER和BACKUP必须是大写;否则会造成配置无法生效的问题
interface 网卡ID;要根据自己的实际情况来看,可以使用以下方式ifconfig
在BACKUP(备用节点)上,其keepalived.conf与Master上基本一致,修改state为BACKUP,priority值改小还有修改real_server 的ip即可,但是注意在双主模式下
virtual_router_id VRID也是不同的
authentication主备之间的认证方式,一般使用PASS即可;主备的配置必须一致,不能超过8位
#启动 service keepalived start |
#停止 service keepalived stop |
#查看状态 service keepalived status |
#重启 service keepalived restart |
简介:Nginx+Lvs+KeepAlive高可用方案实施《上》
根据需求配置多个节点演示
两种情况
1 (LVS节点挂了但是RealServer存活)
如果其中主keepalived挂了,那就会vip就会分发(漂移)到另外一个keepalived节点(备用),响应正常
2 (RealServer节点挂了但是LVS存活)
如果主节点中的realServer挂了,比如是Nginx挂了,那对应keepalived节点存活依旧可以转发过去,但是响应失败
解决问题
如果某个realServer挂了,比如是Nginx挂了,那对应
keepalived节点存活依旧可以转发过去,但是响应失败
#配置vrrp_script,主要用于realServer健康检查及realServer检查失败后执行的动作。
其实原理就是,当我们的realServer挂了以后,我们把它对应的Keepalived关掉,这样就会产生VIP漂移,此时请求就分发到另外的keepalived节点,响应正常
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
interval 2
#当检查失败后,将vrrp_instance的priority减小5
weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
fall 3
#连续监测2次成功,就认为成功。但不调整优先级
rise 2
user root
}
chk_server.sh脚本内容(需要 chmod +x chk_server.sh)
#!/bin/bash
#检查nginx进程是否存在
counter=$(ps aux | grep -v grep | grep nginx | wc -l)
if [ "${counter}" -eq "0" ]; then
service keepalived stop
echo 'nginx server is died.......'
fi
配置的常见问题
vip能ping通,vip监听的端口不通: 第一个原因:nginx1和nginx2两台服务器的服务没有正常启动
vip ping不通: 核对是否出现裂脑,常见原因为防火墙配置所致导致多播心跳失败,核对keepalived的配置是否正确
1 特别注意: (不管是双主还是主备模式)一定需要关闭selinux,不然sh脚本可能不生效
getenforce 查看
setenforce 0 关闭 用于关闭selinux防火墙,但重启后失效,所以要永久关闭
永久关闭
修改selinux的配置文件,重启后生效。
打开 selinux 配置文件
vim /etc/selinux/config
修改 selinux 配置文件
将SELINUX=enforcing改为SELINUX=disabled,保存后退出
生产环境问题(有些云服务器不支持VIP)
VIP : 阿里云(LBS)(支持)、华为云(支持)、腾讯云、AWS
nginx+keepalived主备模式,始终有一台服务器处于空闲状态。为了更好地利用服务器,可以把它们设置为双主模式,另一台为这一台的备份,同时它又是另外一个VIP的主服务器,两台同时对外提供不同服务,同时接收用户的请求。(线上一般使用这种)(然后最外层再弄一个DNS轮询,用户可以轮询访问两台主服务器了)
1 特别注意: (不管是双主还是主备模式)一定需要关闭selinux,不然sh脚本可能不生效
参考文献
https://www.cnblogs.com/guantou1992/p/12724794.html
管理与维护
nginx+keepalived双主架构,日常维护和管理需要从以下几个方面:
1 keepalived主配置文件必须设置不同的VRRP名称,同时优先级和VIP也不相同
2 该实验中用到了两台服务器,nginx网站访问量为两台服务器访问之和,可以用脚本来统计
3 两个nginx都是master,有两个VIP地址,用户从外网访问VIP,需要配置域名映射到两个VIP上,可以通过外网DNS映射不同的VIP(DNS轮询)
4 可以通过zabbix监控等实时监控VIP访问是否正常
配置如下(有时候启动不成功的话,重启即可)
192.168.43.180机器的配置
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的
enable_script_security #允许执行外部脚本
}
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
interval 2
#当检查失败后,将vrrp_instance的priority减小5
weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
fall 3
#连续监测2次成功,就认为成功。但不调整优先级
rise 2
user root
}
#配置对外提供服务的VIP vrrp_instance配置
vrrp_instance VI_1 {
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
state MASTER
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
interface ens33
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
virtual_router_id 51
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
priority 100
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
#定义虚拟IP(VIP)为192.168.159.100,可多设,每行一个
virtual_ipaddress {
192.168.159.100
}
#本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
track_script {
chk_real_server
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.100 80 {
# 设置健康检查时间,单位是秒
delay_loop 6
# 设置负载调度的算法为rr
lb_algo rr
# 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
lb_kind NAT
# 会话保持时间
persistence_timeout 50
#指定转发协议类型(TCP、UDP)
protocol TCP
# 指定real server1的IP地址
real_server 192.168.43.180 80 {
# 配置节点权值,数字越大权重越高
weight 1
# 健康检查方式
TCP_CHECK { # 健康检查方式
connect_timeout 10 # 连接超时
retry 3 # 重试次数
delay_before_retry 3 # 重试间隔
connect_port 80 # 检查时连接的端口
}
}
#配置对外提供服务的VIP vrrp_instance配置
vrrp_instance VI_2 {
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
state BACKUP
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
interface ens33
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
virtual_router_id 48
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
priority 85
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
advert_int 1
authentication {
auth_type PASS
auth_pass 222
}
#定义虚拟IP(VIP)为192.168.159.99,可多设,每行一个
virtual_ipaddress {
192.168.159.99
}
#本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
track_script {
chk_real_server
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.99 80 {
# 设置健康检查时间,单位是秒
delay_loop 6
# 设置负载调度的算法为rr
lb_algo rr
# 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
lb_kind NAT
# 会话保持时间
persistence_timeout 50
#指定转发协议类型(TCP、UDP)
protocol TCP
# 指定real server1的IP地址
real_server 192.168.43.180 80 {
# 配置节点权值,数字越大权重越高
weight 1
# 健康检查方式
TCP_CHECK { # 健康检查方式
connect_timeout 10 # 连接超时
retry 3 # 重试次数
delay_before_retry 3 # 重试间隔
connect_port 80 # 检查时连接的端口
}
}
}
192.168.43.189
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的
enable_script_security #允许执行外部脚本
}
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
interval 2
#当检查失败后,将vrrp_instance的priority减小5
weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
fall 3
#连续监测2次成功,就认为成功。但不调整优先级
rise 2
user root
}
#配置对外提供服务的VIP vrrp_instance配置
vrrp_instance VI_1 {
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
state BACKUP
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
interface ens33
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
virtual_router_id 51
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
priority 84
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
#定义虚拟IP(VIP)为192.168.159.100,可多设,每行一个
virtual_ipaddress {
192.168.159.100
}
#本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
track_script {
chk_real_server
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.100 80 {
# 设置健康检查时间,单位是秒
delay_loop 6
# 设置负载调度的算法为rr
lb_algo rr
# 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
lb_kind NAT
# 会话保持时间
persistence_timeout 50
#指定转发协议类型(TCP、UDP)
protocol TCP
# 指定real server1的IP地址
real_server 192.168.43.189 80 {
# 配置节点权值,数字越大权重越高
weight 1
# 健康检查方式
TCP_CHECK { # 健康检查方式
connect_timeout 10 # 连接超时
retry 3 # 重试次数
delay_before_retry 3 # 重试间隔
connect_port 80 # 检查时连接的端口
}
}
}
#配置对外提供服务的VIP vrrp_instance配置
vrrp_instance VI_2 {
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
state MASTER
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
interface ens33
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
virtual_router_id 48
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
priority 90
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
advert_int 1
authentication {
auth_type PASS
auth_pass 222
}
#定义虚拟IP(VIP)为192.168.159.99,可多设,每行一个
virtual_ipaddress {
192.168.159.99
}
#本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
track_script {
chk_real_server
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.99 80 {
# 设置健康检查时间,单位是秒
delay_loop 6
# 设置负载调度的算法为rr
lb_algo rr
# 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
lb_kind NAT
# 会话保持时间
persistence_timeout 50
#指定转发协议类型(TCP、UDP)
protocol TCP
# 指定real server1的IP地址
real_server 192.168.43.189 80 {
# 配置节点权值,数字越大权重越高
weight 1
# 健康检查方式
TCP_CHECK { # 健康检查方式
connect_timeout 10 # 连接超时
retry 3 # 重试次数
delay_before_retry 3 # 重试间隔
connect_port 80 # 检查时连接的端口
}
}
}
第1集 Nginx基础架构master-worker进程剖析
简介:Nginx基础架构模型剖析
master 进程负责管理 Nginx 本身和其他 worker 进程
高性能原理
nginx 通过 多进程 + io多路复用(epoll) 实现了高并发
采用多个worker进程实现对多cpu的利用 通过eopll 对 多个文件描述符 事件回调机制
拓展:linux I/O多路复用有select,poll,epoll
I/O模式一般分为同步IO和异步IO。
同步IO会阻塞进程,异步IO不会阻塞进程。
目前linux上大部分用的是同步IO,异步IO在linux上还不太成熟(有部分)
同步IO又分为阻塞IO,非阻塞IO,IO多路复用, 很多人对这个就有疑问了????
同步IO会阻塞进程,为什么也包括非阻塞IO? 因为非阻塞IO虽然在请求数据时不阻塞,但真正数据来临时,也就是内核数据拷贝到用户数据时,此时进程是阻塞的(大部分时间是不阻塞的,小部分时间是阻塞的所以我们说它是非阻塞的)。