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
高性能优化技巧:
Nginx具有一些性能优化技巧,可以提升服务器的吞吐量和响应速度
- 链接池:重用与后端服务器的链接,减少连接建立的开销
- 文件缓存:缓存静态文件以减少磁盘IO
- 压缩:压缩响应内容以减小传输大小。
连接池配置
http { upstream backend { server backend1.example.com max_conns=20; server backend2.example.com max_conns=30; } server { listen 80; location / { proxy_pass http://backend; } } }
安全性配置
针对Nginx的安全性配置可以确保服务器和应用程序的安全性,以下是常见的nginx安全配置选项:
- 防止DDOS攻击:通过配置限制连接速率,连接数和请求大小等,可以减轻DDos攻击对服务器的影响
- 启用访问控制:使用allow和deny指令限制特定ip地址或IP段的访问
- 配置SSL/TTS:使用有效的证书和合理的SSL/TLS配置,确保安全的HTTPS通信
DDos防护配置
http { limit_req_zone $binary_remote_addr zone=ddos:10m rate=10r/s; server { location / { limit_req zone=ddos; } } }
IP访问控制配置
http { server { location / { allow 192.168.0.0/24; deny all; } } }
SSL/TLS配置
http { server { listen 443 ssl; server_name example.com; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private.key; ... } }
Nginx的监控和调优
为了保持服务器的高性能和稳定性,可以使用监控和调优工具对Nginx进行监控和性能优化。以下是一些常见的Nginx监控和调优技术:
- 使用Nginx Plus模块:Nginx Plus是Nginx的商业版本,它提供了高级的监控和调优功能。Nginx Plus的一些功能包括实时监控、性能指标收集、动态负载均衡和自动故障恢复等。通过Nginx Plus,可以深入了解服务器的运行状况,并采取必要的措施进行性能调优。
- 使用Nginx状态模块:Nginx状态模块可以提供关于服务器状态的详细信息,例如活跃连接数、请求速率、处理时间等。可以通过配置Nginx状态模块并与监控工具(如Prometheus和Grafana)结合使用,实现实时监控和可视化。
http { server { location /nginx_status { stub_status on; allow 127.0.0.1; deny all; } } }
- 使用性能调优工具:可以使用工具如ApacheBench(ab)或wrk来进行性能测试和负载压力测试,以评估Nginx服务器的性能,并找到性能瓶颈所在。通过调整Nginx的配置参数,如工作进程数、缓冲区大小和超时设置等,可以优化服务器的性能。
性能调优配置
events { worker_connections 1024; } http { server { ... client_body_buffer_size 10k; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 2 1k; ... } }
Nginx日志介绍
Nginx的日志类型
我们进入到nginx
目录下的log
目录中,可以看到里面存放着三个文件,分别是access.log
,error.log
和nginx.pid
文件,其中nginx.pid
是用来记录当前nginx进程的pid号的,不属于日志文件。真正属于日志文件的是另外两个文件。
access.log日志文件
access日志文件用于存放每个用户访问网站的请求日志,开发运维人员通过访问日志来分析用户的浏览器行为。默认情况下,那恭喜会在log目录下生成该文件,无需用户配置
access.log的相关配置
配置格式为:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
其中,access_log
是关键字,表示接下来的配置是关于access日志的配置,path
为该日志文件的存储路径,后面还可以对日志输出格式、是否压缩、日志刷新时间等设置进行配置。可能有读者会留意到,用例在path
后面写上了main
,其实这里的main
并不是什么关键字,而是nginx默认定义好的一个日志格式名称,我们可以在log_format
中看到,nginx默认定义了一个名为main
的日志输出格式。
-
关于日志输出格式的配置
nginx自带了一些变量,让我们能够作为日志输出格式进行配置,方便我们对用户的请求进行查询和统计。当然了,nginx其实默认的日志输出格式其实就已经把一些重要的请求参数保存到访问日志里面了,基本满足我们日常使用了,如果有需要可以根据下面的表单自定义配置所需要的日志格式。参数 说明 示例 $remote_addr 客户端地址 211.28.65.253 $remote_user 客户端用户名称 -- $time_local 访问时间和时区 18/Jul/2012:17:00:01 +0800 $request 请求的URI和HTTP协议 "GET /article-10000.html HTTP/1.1" $http_host 请求地址,即浏览器中你输入的地址(IP或域名) www.wang.com 192.168.100.100 $status HTTP请求状态 200 $upstream_status upstream状态 200 $body_bytes_sent 发送给客户端文件内容大小 1547 $http_referer url跳转来源 https://www.baidu.com/ $http_user_agent 用户终端浏览器等信息 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C; $ssl_protocol SSL协议版本 TLSv1 $ssl_cipher 交换数据中的算法 RC4-SHA $upstream_addr 后台upstream的地址,即真正提供服务的主机地址 10.10.10.100:80 $request_time 整个请求的总时间 0.205 $upstream_response_time 请求过程中,upstream响应时间 0.002
简单自定义一个日志输出格式,并且应用起来
http { include mime.types default_type application/octet-stream log_format mine_format "$remote_addr - $remote_user [$time_local] \"$request\" \"$http_host\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$request_time\" \"$ssl_protocol\" \"$ssl_cipher\" \"$http_x_forwarded_for\" \"$upstream_addr\" \"$upstream_status\" \"$upstream_response_length\" \"$upstream_response_time\" \"$http_x_gateway_serve\" \"$http_x_ai_gateway_app_id\"" sendfile on; keepalive_timeout 65; }
在server标签中应用定义新的access_log
配置
server { listen 9600; location / { root html; access_log logs/mine_access.log mine_format; } }
使用nginx -s reload 重新加载配置文件
关于刷新时间的配置
- nginx默认情况下对访问日志是实时记录的,其实一定程度上会占有CPU资源,如果是对于访问量大且对性能要求较高的站点,可能会通过优化日志的输出频率来达到减少IO的效果
location / { root html; access_log logs/mine_access.gz mine_format gzip flush=5s; }
官方对这个配置的介绍:配置完flush和buffer
后,其实我们就相当于是有两个记录日志的节点了,一个是缓冲区满了,另外一个是到刷新日志的时间点了。缓冲区的存在使得nginx不需要针对每一个请求都做一次IO,可以节省一点系统资源。当然了,我们还可以开启gzip压缩(可选等级为1-9,级别越高压缩级别越高)来进一步减轻磁盘压力。
关闭访问的日志记录
只需要配置access_log
为off
即可
location / { root html; access_log off; }
error.log错误日志
错误日志文件记录了nginx运行过程中遇到的错误信息(注意,也包括用户请求没有正常响应的错误日志),向有时候我们nginx启动失败后,都可以在这个error日志中找到对应较为详情的报错信息。
这里贴一下官网对error.log
的介绍,该错误日志的配置格式为:error_log path level
,error_log为关键字,path为日志保存的路径,level为日志级别。默认情况下nginx会在logs目录下建立一个名为error.log
的日志文件,且日志级别为error。可选的日志级别配置从低到高分别为debug, info, notice, warn, error, crit, alert, emerg。
server { listen 9600; location / { root html; access_log logs/mine_access.log mine_format; error_log logs/mine_error.log warn; } }
运维优化
nginx默认是不会进行日志文件的分割操作的,也就是所有访问日志会一直往access.log
文件里面追加,时间一长的话这个文件就会变得很大,而且运维人员在查看当天文件的也很不方便。
常见的处理方案有2种:
(1)直接在nginx配置文件中配置
(2)通过linux的crontab
配置定时任务,自己手动写一下定时处理的脚本。
下面我们就来讲讲这两种处理方案:
方案一,在nginx配置文件中配置
在Nginx配置文件中,可以使用$time_local
或$time_iso8601
变量来获取当前时间,然后将其作为日志文件名的一部分。所以我们可以这样配置我们的日志文件名。
-
步骤一:在http标签块中按照我们需要的日期格式
yyyy-MM-dd
定义变量$logdate
http { ... map $time_iso8601 $logdate { '~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd; default 'date-not-found'; } ... } -
步骤二 在对应的站点中使用变量来动态生成日志文件
location / { root html; access_log /opt/nginx/logs/mine_access.$logdate.log mine_format; error_log /opt/nginx/logs/mine_error.log warn; } 这里需要注意的是,
error_log
日志文件可能会由于nginx版本的原因,无法使用变量来动态切割每天的日志,所以感觉这种方法并不完全适用。 -
重新加载一下配置文件,上述配置即可生效了
方案二 结合crontab定时任务来完成日志的切割效果(更推荐)
-
步骤一:写一下按日切割文件的日志脚本,命名为
nginx_log_split.sh
简单解释一下脚本做的工作,根据
年/月
生成对应的目录,然后把日志文件重命名后放入到对应月份的目录中,最后再通过nginx -s reopen
命令重新启动日志。#!/bin/bash nginx_home=/opt/nginx/ nginx_log_path=${nginx_home}logs/ current_date1=$(date +%Y-%m-%d) access_log_file_name=access.log error_log_file_name=error.log history_file_path=${nginx_home}logs/history_log/$(date +%Y)/$(date +%m) # check if the nginx server alive if [ -e ${nginx_log_path}nginx.pid ];then # create log folder for nginx log file if [ ! -e ${history_file_path} ];then mkdir -p ${history_file_path} echo "$(date) create folder success" fi # rename the log file with current date if [ -e $nginx_log_path$access_log_file_name ];then mv ${nginx_log_path}${access_log_file_name} ${history_file_path}/access-${current_date1}.log echo "$(date) rename access.log successfully" else echo "$(date) access.log file no exist,skip" fi if [ -e $nginx_log_path$error_log_file_name ];then mv ${nginx_log_path}${error_log_file_name} ${history_file_path}/error-${current_date1}.log echo "$(date) rename error.log successfully" else echo "$(date) error.log file no exist,skip" fi # reopen the nginx server log ${nginx_home}/sbin/nginx -s reopen echo "$(date) reload log file success" else echo "$(date) nginx server is close,skip" fi -
步骤二:给脚本授权
chmod 774 nginx_log_split.sh -
步骤三 配置crontab定时器
通过crontab定时器,让系统每天晚上
23:59
分的时候跑一次我们的脚本,生成分割当天的日志文件。然后顺便把执行日志输出到指定的文件中,方便我们查看。59 23 * * * /opt/nginx/logs/nginx_split_log.sh > /opt/nginx/logs/history_log/execute.log 2>&1
按模块区分访问日志
对于站点较多,且都部署在同一台nginx服务器(或者同一个nginx集群)的企业,一般我们会习惯性的将不同站点的日志分开管理,避免所有的站点日志都输出在同一个access.log
文件中,导致后续统计或者排查问题的时候容易混淆。
server { listen 9600; location / { root html; access_log /opt/nginx/logs/mine_access1.log mine_format; error_log /opt/nginx/logs/mine_error.log warn; } } server { listen 9601; location / { root html; access_log /opt/nginx/logs/mine_access2.log mine_format; } }
本文作者:小郑[努力版]
本文链接:https://www.cnblogs.com/2678066103hs/p/18628834
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步