Nginx常用操作
Nginx
Nginx的最重要的几个使用场景
- 静态资源服务,通过本地文件提供服务
- 反向代理服务,延伸出包括缓存,负载均衡等
- API服务,OpenResty
相关概念
简单请求和非简单请求
- 请求方法是HEAD,GET,POST三种之一
- HTTP 头信息不超过右边这几个字段:Accept、Accept-Language、Content-Language、Last-Event-ID
Content-Type 只限于三个值application/x-www-form-urlencoded
、multipart/form-data
、text/plain
;
凡是不同时满足这两个条件的,都属于非简单请求
浏览器处理简单请求和非简单请求的方式不一样:
简单请求
对于简单请求,浏览器会在头信息中增加 Origin 字段后直接发出,Origin 字段用来说明,本次请求来自的哪个源(协议+域名+端口)。
如果服务器发现 Origin 指定的源不在许可范围内,服务器会返回一个正常的 HTTP 回应,浏览器取到回应之后发现回应的头信息中没有包含 Access-Control-Allow-Origin 字段,就抛出一个错误给 XHR 的 error 事件;
如果服务器发现 Origin 指定的域名在许可范围内,服务器返回的响应会多出几个 Access-Control- 开头的头信息字段。
非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE,或 Content-Type 值为 application/json。浏览器会在正式通信之前,发送一次 HTTP 预检 OPTIONS 请求,先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 请求方法和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XHR 请求,否则报错。
跨域
在浏览器上当前访问的网站向另一个网站发送请求获取数据的过程就是跨域请求。
跨域是浏览器的同源策略决定的,是一个重要的浏览器安全策略,用于限制一个origin的文档或者它加载的脚本与另一个源的资源进行交互,它能够帮助租个恶意文档,减少可能被攻击的媒介,可以使用CORS配置解除这个限制。
正向代理和反向代理
反向代理:使用反向代理后,直接收到请求的服务器是代理服务器,然后将请求转发给内部网络上真正进行处理的服务器,得到的结果返回给客户端。反向代理隐藏了真实的服务器,为服务器发送请求。一般在处理跨域时比较常用
负载均衡
请求爆发式增长的情况下,单个机器性能再强也无法满足要求了,这个时候集群的概念产生了,单个服务器解决不了问题,可以使用多个服务器,然后将请求分发到各个服务器上,将负载分发到不同的服务器。Nginx实现负载均衡,一般来说指的是将请求转发给服务器集群。
Nginx安装
yun install nginx
nginx -V
查看Nginx版本信息
systemctl start firewalld # 开启防火墙
systemctl stop firewalld # 关闭防火墙
systemctl status firewalld # 查看防火墙开启状态,显示running则是正在运行
firewall-cmd --reload # 重启防火墙,永久打开端口需要reload一下
# 添加开启端口,--permanent表示永久打开,不加是临时打开重启之后失效
firewall-cmd --permanent --zone=public --add-port=8888/tcp
# 查看防火墙,添加的端口也可以看到
firewall-cmd --list-all
设置Nginx开机启动
systemctl enable nginx
启动Nginx
systemctl start nginx
Nginx操作常用命令
Nginx 的命令在控制台中输入 nginx -h 就可以看到完整的命令,这里列举几个常用的命令:
nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启
nginx -s reopen # 重启 Nginx
nginx -s stop # 快速关闭
nginx -s quit # 等待工作进程处理完成后关闭
nginx -T # 查看当前 Nginx 最终的配置
nginx -t -c # 检查配置是否有问题,如果已经在配置目录,则不需要-c
systemctl 是 Linux 系统应用管理工具 systemd 的主命令,用于管理系统,我们也可以用它来对 Nginx 进行管理,相关命令如下:
systemctl start nginx # 启动 Nginx
systemctl stop nginx # 停止 Nginx
systemctl restart nginx # 重启 Nginx
systemctl reload nginx # 重新加载 Nginx,用于修改配置后
systemctl enable nginx # 设置开机启动 Nginx
systemctl disable nginx # 关闭开机启动 Nginx
systemctl status nginx # 查看 Nginx 运行状态
nginx配置
nginx.conf 的典型配置
# 全局块:配置影响nginx全局的指令,一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志文件存放路径,配置文件引入等
user nginx; # 运行用户,默认即是nginx,可以不进行设置
worker_processes 1; # Nginx 进程数,一般设置为和 CPU 核数一样
error_log /var/log/nginx/error.log warn; # Nginx 的错误日志存放目录
pid /var/run/nginx.pid; # Nginx 服务启动时的 pid 存放位置
# events块:配置影响nginx服务器或与用户的网络连接,有每个进程的最大连接数,选取那种事件驱动模型处理连接请求,是否允许同时接受多个网络链接,开启多个网络连接序列化等。
events {
use epoll; # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
worker_connections 1024; # 每个进程允许最大并发数
}
# http块: 可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置,如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等
http { # 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
# 设置日志模式
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; # Nginx访问日志存放位置
sendfile on; # 开启高效传输模式
tcp_nopush on; # 减少网络报文段的数量
tcp_nodelay on;
keepalive_timeout 65; # 保持连接的时间,也叫超时时间,单位秒
types_hash_max_size 2048;
include /etc/nginx/mime.types; # 文件扩展名与类型映射表
default_type application/octet-stream; # 默认文件类型
#include /etc/nginx/conf.d/*.conf; # 加载子配置项
proxy_connect_timeout 1; #nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
proxy_read_timeout 1; #nginx服务器想被代理服务器组发出read请求后,等待响应的超时间,默认为60秒。
proxy_send_timeout 1; #nginx服务器想被代理服务器组发出write请求后,等待响应的超时间,默认为60秒。
proxy_http_version 1.0 ; #Nginx服务器提供代理服务的http协议版本1.0,1.1,默认设置为1.0版本。
#proxy_method get; #支持客户端的请求方法。post/get;
proxy_ignore_client_abort on; #客户端断网时,nginx服务器是否终端对被代理服务器的请求。默认为off。
proxy_ignore_headers "Expires" "Set-Cookie"; #Nginx服务器不处理设置的http相应投中的头域,这里空格隔开可以设置多个。
proxy_intercept_errors on; #如果被代理服务器返回的状态码为400或者大于400,设置的error_page配置起作用。默认为off。
proxy_headers_hash_max_size 1024; #存放http报文头的哈希表容量上限,默认为512个字符。
proxy_headers_hash_bucket_size 128; #nginx服务器申请存放http报文头的哈希表容量大小。默认为64个字符。
proxy_next_upstream timeout; #反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off
#proxy_ssl_session_reuse on; 默认为on,如果我们在错误日志中发现“SSL3_GET_FINSHED:digest check failed”的情况时,可以将该指令设置为off。
upstream mysvr{
server 192.168.10.121:3333 weight=1;
server 192.168.10.121:3333 weight=2;
erver 192.168.10.122:3333 backup; # 热备服务器,当服务器A挂掉后才会启用并提供服务
}
# server块: 配置虚拟主机的相关参数,一个http中可以有多个server
server {
listen 80; # 配置监听的端口
server_name localhost; # 监听的服务域名 --- 域名
# Location块: 配置请求的路由,以及各种页面的处理情况
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页文件
deny 172.168.22.11; # 禁止访问的ip地址,可以为all
allow 172.168.33.44; # 允许访问的ip地址,可以为all
}
location ~*^.+$ {
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
}
error_page 500 502 503 504 /50x.html; # 默认50x对应的访问页面
error_page 400 404 error.html; # 同上
}
}
server块可以包含多个Location块,Location指令用于配置uri,语法:
location [ = | ~ | ~* | ^~] uri {
...
}
指令后面:
=
精确匹配路径,用于不含正则表达式的uri前,如果匹配成功,不再进行后续的查找^~
用于处理不含正则表达式的uri前,如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找。~
表示用该符号后面的正则去匹配路径,区分大小写。~*
表示用该符号后面的去正则匹配路径,不区分大小写。跟~
优先级都比较低
include关键字
include可以用在任何地方,前提是include的文件自身语法正确
include文件路径可以是绝对路径,也可以是相对路径,相对路径以nginx.cof为基准,同时可以使用通配符
配置实例
# 绝对路径
include /etc/conf/nginx.conf
# 相对路径
include port/80.conf
# 通配符
include *.conf
测试配置文件
./nginx -t
配置反向代理
反向代理与正向代理
正向代理: 正向代理的过程中,它隐藏了真实的请求客户端,服务端不知道真实的客服端是谁,客户端请求的服务都被代理服务器代替来请求。
例如: A想向C借钱,但是C不认识A就不想借给他,然后A通过B向C借钱,B借到钱后再转交给A,这个过程中B就扮演了正向代理的角色
反向代理: 隐藏了真实的服务端,对于客户来说不知道访问的是那台服务器。
例如:A想向C借钱,然后C借给他了,但是实际上这个钱可能是C向B借的,至于钱到底是谁的,A是不知道的。这里的C扮演着一个反向代理的角色,客户不知道真正提供服务的人是谁
反向代理是工作中最常用的服务器功能,经常被用来解决跨域问题。
- 首先进入Nginx的主配置文件
Nginx.conf
- 为了看起来方便,把行号显示出来
:set nu
- 然后我们去 http 模块的 server 块中的 location /,增加一行将默认网址重定向到最大学习网站 Bilibili 的 proxy_pass 配置 www.bilibili.com:
改完保存退出,nginx -s reload 重新加载,进入默认网址,那么现在就直接跳转到 B 站了,实现了一个简单的代理。
实际使用中,可以将请求转发到本机另一个服务器上,也可以根据访问的路径跳转到不同端口的服务中。
比如我们监听 9001 端口,然后把访问不同路径的请求进行反向代理:
把访问 http://127.0.0.1:9001/edu 的请求转发到 http://127.0.0.1:8080
把访问 http://127.0.0.1:9001/vod 的请求转发到 http://127.0.0.1:8081
这种要怎么配置呢,首先同样打开主配置文件,然后在 http 模块下增加一个 server 块:
server {
listen 9001;
server_name *.sherlocked93.club;
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
反向代理还有一些其他的指令,可以了解一下:
- proxy_set_header:在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息;
- proxy_connect_timeout:配置 Nginx 与后端代理服务器尝试建立连接的超时时间
- proxy_read_timeout:配置 Nginx 向后端服务器组发出 read 请求后,等待相应的超时时间;
- proxy_send_timeout:配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;
- proxy_redirect:用于修改后端服务器返回的响应头中的 Location 和 Refresh。
深入了解nginx的负载均衡算法,nginx官方提供的插件可以了解
跨域CORS配置
使用反向代理解决跨域
在前端服务地址为 fe.sherlocked93.club 的页面请求 be.sherlocked93.club 的后端服务导致的跨域,可以这样配置:
server {
listen 9001;
server_name fe.sherlocked93.club;
location / {
proxy_pass be.sherlocked93.club;
}
}
这样就将对前一个域名 fe.sherlocked93.club 的请求全都代理到了 be.sherlocked93.club,前端的请求都被我们用服务器代理到了后端地址下,绕过了跨域。
这里对静态文件的请求和后端服务的请求都以 fe.sherlocked93.club 开始,不易区分,所以为了实现对后端服务请求的统一转发,通常我们会约定对后端服务的请求加上 /apis/ 前缀或者其他的 path 来和对静态资源的请求加以区分,此时我们可以这样配置:
# 请求跨域,约定代理后端服务请求path以/apis/开头
location ^~/apis/ {
# 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass be.sherlocked93.club;
# 两个域名之间cookie的传递与回写
proxy_cookie_domain be.sherlocked93.club fe.sherlocked93.club;
}
这样,静态资源我们使用 fe.sherlocked93.club/xx.html,动态资源我们使用 fe.sherlocked93.club/apis/getAwo,浏览器页面看起来仍然访问的前端服务器,绕过了浏览器的同源策略,毕竟我们看起来并没有跨域。
配置Header解决跨域
当浏览器在访问跨源的服务器时,也可以在跨域的服务器上直接设置Nginx,从而前端就可以无感地开发,不用把实际访问的地址改成前端服务地址
# /etc/nginx/conf.d/be.sherlocked93.club.conf
server {
listen 80;
server_name be.sherlocked93.club;
add_header 'Access-Control-Allow-Origin' $http_origin; # 全局变量获得当前请求origin,带cookie的请求不支持*
add_header 'Access-Control-Allow-Credentials' 'true'; # 为 true 可带上 cookie
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # 允许请求方法
add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; # 允许请求的 header,可以为 *
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000; # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204; # 200 也可以
}
location / {
root /usr/share/nginx/html/be;
index index.html;
}
}
配置负载均衡
负载均衡是高可用网络基础架构的关键组件,通常用户将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性
负载均衡通常配合nginx一起使用
主要配置如下:
http {
# upstream表示为真实集群服务器名称
upstream myserver {
# ip_hash; # ip_hash 方式
# fair; # fair 方式
server 127.0.0.1:8081; # 负载均衡目的服务地址
server 127.0.0.1:8080;
server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1
}
server {
location / {
proxy_pass http://myserver; # upstream集群名称
proxy_connect_timeout 10;
}
}
}
Nginx 提供了好几种分配方式,默认为轮询,就是轮流来。有以下几种分配方式:
-
轮询,默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;
-
weight,权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;
upstream myserver { server 127.0.0.1:8081 weight=5; # 负载均衡目的服务地址 server 127.0.0.1:8080 weight=2; server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1 }
-
ip_hash,每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的;
upstream myserver { server 127.0.0.1:8081 ; # 负载均衡目的服务地址 server 127.0.0.1:8080 ; server 127.0.0.1:8082 ; ip-hash; }
-
fair(第三方),按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;
关于nginx负载均衡配置的几个状态参数讲解:
-
down:表示当前的server暂时不参与负载均衡
-
backup:预留的备份机器,当其他所有非backup机器出现故障或忙的时候,才会请求backup机器
-
max_fails: 允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误
-
fail_timeout: 在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用
upstream mysvr { server 127.0.0.1:7878 weight=2 max_fails=2 fail_timeout=2; server 192.168.10.121:3333 weight=1 max_fails=2 fail_timeout=1; }
动静分离
把静态资源【css,js,img】交于nginx来处理, 而动态资源【接口】还是有真实的服务器处理
好处:当修改静态资源时,无需对每个真实服务器的静态资源做修改,只需要修改nginx一处的静态资源
配置nginx配置:
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://192.168.223.147:8080;
}
# 配置静态资源,如果访问资源以.jp .css等结尾的,则找static目录下的资源
location ~ \.jpg|.css|.js|.png|.jpeg|.gif$ {
root static;
}
}
在nginx中新建static文件夹将静态资源放入。
配置高可用集群(双机热备)
高可用是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。如果一个系统能够一直提供服务,那么这个可用性则是百分之百,但是不能保证一个系统能永远不出问题。
思考;
- nginx出现问题后该怎么办? ------ 提高 高可用性
- 当直接点宕机后,如何让客户访问从节点? ------ 虚拟一个ip,客服只需访问虚拟ip即可
- 如何让主节点和从节点之间能够切换? ------ 使用keepalived组件来解决,它会自动监控主从的状态,并可以帮nginx虚拟ip,还可在主从之间切换
当主Nginx服务器宕机之后,切换到备份Nginx服务器
-
首先安装keepalived
keepalived 是集群管理中保证集群高可用的服务软件,用来防止单节点故障。keepalived的作用是检测web服务器的状态,如果有一台服务器死机或出现故障,keepalived将能检测到,并将有故障的web服务器从系统中剔除,当web服务器工作正常后keepalived会自动将该web服务器加入到服务器群中。这些工作全部都会自动完成。需要人工做的只是修复故障的web服务器。keepalived可以理解为一个健康检查的软件
yum install keepalived -y
rmp -q -a keepalived # 检查是否安装keepalived
-
然后编辑 /etc/keepalived/keepalived.conf 配置文件,并在配置文件中增加 vrrp_script 定义一个外围检测机制,并在 vrrp_instance 中通过定义 track_script 来追踪脚本执行过程,实现节点转移:
global_defs{ notification_email { # keepalived服务器宕机异常出现的时候,发送通知邮件,可以是多个 acassen@firewall.loc # 收件人邮箱1 } notification_email_from Alexandre@firewall.loc # 邮件发件人 smtp_server 127.0.0.1 // 当前keepalive所在主机ip smtp_connect_timeout 30 // 上面都是邮件配置, router_id LVS_DEVEL // 当前keepalive所在主机ip LVS_DEVEL这字段在/etc/hosts文件中看;通过它访问到主机 } vrrp_script chk_maintainace { // 检测机制的脚本名称为chk_maintainace script "[[ -e/etc/keepalived/down ]] && exit 1 || exit 0" // 可以是脚本路径或脚本命令 // script "/etc/keepalived/nginx_check.sh" // 比如这样的脚本路径 加载nginx检查脚本文件 interval 2 // 每隔2秒检测一次 weight -20 // 当脚本执行成立,那么把当前服务器优先级改为-20 } vrrp_instanceVI_1 { // 每一个vrrp_instance就是定义一个虚拟路由器 state MASTER // 主机为MASTER,备用机为BACKUP interface eth0 // 网卡名字,可以从ifconfig | ip addr 中查找 virtual_router_id 51 // 虚拟路由的id号,一般小于255,主备机id需要一样 priority 100 // 优先级,master的优先级比backup的大 advert_int 1 // 默认心跳间隔 authentication { // 认证机制 auth_type PASS auth_pass 1111 // 密码 } virtual_ipaddress { 172.16.2.8 // 虚拟ip 必须和其他nginx所在的ip在同一网段 } }
其中检测脚本
nginx_check.sh
#!/bin/bash # 检测nginx是否启动了 A=`ps -C nginx --no-header | wc -l` if [ $A -eq 0 ];then # 如果nginx没有启动就启动nginx /usr/sbin/nginx # 通过nginx的启动脚本来重启nginx sleep 2 # 睡眠2秒 if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then killall keepalived # 启动失败,将keepalived服务杀死。将vip漂移到其它备份节点 fi fi
复制一份到备份服务器,备份 Nginx 的配置要将 state 后改为 BACKUP,priority 改为比主机小。
设置完毕后各自 service keepalived start 启动,经过访问成功之后,可以把 Master 机的 keepalived 停掉,此时 Master 机就不再是主机了 service keepalived stop,看访问虚拟 IP 时是否能够自动切换到备机 ip addr。
再次启动 Master 的 keepalived,此时 vip 又变到了主机上。
nginx支持socket转发
使用 **** 模块,此模块不是默认构建的,应使用配置参数启用 --with-stream
根据文档提示需要使用这个参数--with-stream 来启用功能。
[root@localhost src]# ./configure --prefix=/usr/local/nginx --with-stream