1、nginx状态页

基于nginx模块ngx_http_stud_status_module 实现,在编译安装nginx的时候需要添加编译参数--with-http_stub_status_module ,否则配置完成之后检测会是提示语法错误

注意:状态页显示的是整个服务器的状态。而非虚拟主机的状态

#配置示例:
location /nginx_status {
   stub_status;
   auth_basic           "auth login";
   auth_basic_user_file /apps/nginx/conf/.htpasswd;
   allow 192.168.0.0/16;
   allow 127.0.0.1;
   deny all;
 }

#状态页用于输出nginx的基本状态信息:
#输出信息示例:
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
 上面三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106

Active connections: #当前处于活动状态的客户端连接数,包括连接等待空闲连接数
=reading+writing+waiting
accepts:#统计总值,Nginx自启动后已经接受的客户端请求的总数。
handled:#统计总值,Nginx自启动后已经处理完成的客户端请求总数,通常等于accepts,除非有因
worker_connections限制等被拒绝的连接
requests:#统计总值,Nginx自启动后客户端发来的总的请求数。
Reading:#当前状态,正在读取客户端请求报文首部的连接的连接数,数值越大,说明排队现象严重,性能不足
Writing:#当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting:#当前状态,正在等待客户端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于
active – (reading+writing)

2、nginx第三方模块

第三模块是对nginx的功能扩展,第三放模块是需要在编译安装nginx的时候使用参数--add-module=PATH指定路径添加,有的模块是由公司的开发人员针对业务需求定制开发的。有的模块是开源爱好者开发后传到github进行开源的模块,nginx支持第三方模块需要从源码重新编译支持,比如开源的echo模块:https://github.com/openresty/echo-nginx-module

[root@centos8 ~]# systemctl stop nginx
[root@centos8 ~]# vim /apps/nginx/conf/conf.d/pc.conf 
 location /main {
     index index.html;
     default_type text/html;
     echo "hello world,main-->";
     echo $remote_addr ;
     echo_reset_timer;   #将计时器开始时间重置为当前时间
     echo_location /sub1;
     echo_location /sub2;
     echo "took $echo_timer_elapsed sec for total.";
 }
 location /sub1 {
     echo_sleep 1;
     echo sub1;
 }
 location /sub2 {
     echo_sleep 1;
     echo sub2;
 }

[root@centos8 ~]# /apps/nginx/sbin/nginx -t
nginx: [emerg] unknown directive "echo_reset_timer" in
/apps/nginx/conf/conf.d/pc.conf:86
nginx: configuration file /apps/nginx/conf/nginx.conf test failed

#解决以上报错问题
[root@centos8 ~]# cd /usr/local/src
[root@centos8 src]# yum install git -y
[root@centos8 src]# git clone https://github.com/openresty/echo-nginx-module.git
[root@centos8 src]# cd nginx-1.18.0/
[root@centos8 src]# ./configure \
--prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--with-http_perl_module \
--add-module=/usr/local/src/echo-nginx-module  #指定模块源代码路径
[root@centos8 src]# make && make install

#确认语法检测通过
[root@centos8 ~]# /apps/nginx/sbin/nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful

#重启nginx访问测试
[root@centos8 ~]# systemctl restart nginx
[root@centos8 ~]#nginx -V
nginx version: wanginx/1.68.9
built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
built with OpenSSL 1.1.1c FIPS  28 May 2019
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
--with-stream_ssl_module --with-stream_realip_module --addmodule=/usr/local/src/echo-nginx-module

#测试查看结果
[root@centos7 ~]#curl http://www.magedu.org/main
hello world,main-->
10.0.0.7
sub1
sub2
took 2.003 sec for total.

3、nginx的变量使用

nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用

变量可以分为内置变量和自定义变量

内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值

3.1、内置变量

官方文档:http://nginx.org/en/docs/varindex.html

常用内置变量:

$remote_addr; 
#存放了客户端的地址,注意是客户端的公网IP

$proxy_add_x_forwarded_for
#此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没
有X-Forwarded-For,就使用$remote_addr
the “X-Forwarded-For” client request header field with the $remote_addr variable 
appended to it, separated by a comma. If the “X-Forwarded-For” field is not 
present in the client request header, the $proxy_add_x_forwarded_for variable is 
equal to the $remote_addr variable.

$args; 
#变量中存放了URL中的参数,例如:http://www.magedu.org/main/index.do?
id=20190221&partner=search
#返回结果为: id=20190221&partner=search

$document_root; 
#保存了针对当前资源的请求的系统根目录,例如:/apps/nginx/html。

$document_uri; #保存了当前请求中不包含参数的URI,注意是不包含请求的指令,比
如:http://www.magedu.org/main/index.do?id=20190221&partner=search会被定义
为/main/index.do 
#返回结果为:/main/index.do

$host; 
#存放了请求的host名称

limit_rate 10240;
echo $limit_rate; #如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0

$remote_port; 
#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口

$remote_user; 
#已经经过Auth Basic Module验证的用户名

$request_body_file; 
#做反向代理时发给后端服务器的本地资源的名称

$request_method; 
#请求资源的方式,GET/PUT/DELETE等

$request_filename; 
#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,
如:/apps/nginx/html/main/index.html

$request_uri; 
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,例
如:/main/index.do?
id=20190221&partner=search 

$scheme; #请求的协议,例如:http,https,ftp等

$server_protocol; 
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等

$server_addr; 
#保存了服务器的IP地址

$server_name; 
#请求的服务器的主机名

$server_port; 
#请求的服务器的端口号

$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段
arbitrary request header field; the last part of a variable name is the field 
name converted to lower case with dashes replaced by underscores #用下划线代替横线

#示例: echo $http_User_Agent;  

$http_user_agent; 
#客户端浏览器的详细信息

$http_cookie; 
#客户端的cookie信息

$cookie_<name>
#name为任意请求报文首部字部cookie的key名

3.2、自定义变量

加入需要自定义变量名称和值,使用指令set $variable value;

语法格式:

Syntax: set $variable value;
Default: —
Context: server, location, if

范例:

set $name magedu;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port"; #输出信息如下
[root@centos6 ~]#curl www.magedu.org/main
magedu
80
www.magedu.org:80

nginx自定义访问日志

访问日志是记录客户端即用户具体访问内容信息,全局配置模块中的error_log是记录nginx服务器运行时的日志保存路径和记录日志的level,因此有着本质的区别,而且nginx的错误日志一般只有一个,但是范围跟日志可以在不同server中定义多个,定义一个日志需要使用access_log指定日志的保存路径,使用log_format指定日志的格式,格式中定义要保存的具体日志内容

访问日志由ngx_http_log_module模块实现

官方帮助文档:http://nginx.org/en/docs/http/ngx_http_log_module.html

语法格式

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] 
[if=condition]];
access_log off;
Default: 
access_log logs/access.log combined;
Context: http, server, location, if in location, limit_excep

4.1、自定义默认格式日志

如果是要保留日志的源格式,只是添加相应的日志内容,则配置如下:

log_format nginx_format1  '$remote_addr - $remote_user [$time_local] "$request" 
'
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '$server_name:$server_port';
access_log logs/access.log nginx_format1;
#重启nginx并访问测试日志格式
==> /apps/nginx/logs/access.log <==
10.0.0.1 - - [22/Feb/2019:08:44:14 +0800] "GET /favicon.ico HTTP/1.1" 404 162 "-
" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/2
0100101 Firefox/65.0" "-"www.magedu.org:80

4.2、自定义json格式日志

nginx的默认访问日志记录内容相对比较单一,默认的格式也不方便后期走日志统计分析,生产环境中通常将nginx日志转换为json日志,然后配合使用elk作日志收集-统计-分析

log_format access_json '{"@timestamp":"$time_iso8601",'
        '"host":"$server_addr",'
        '"clientip":"$remote_addr",'
        '"size":$body_bytes_sent,'
        '"responsetime":$request_time,' #总的处理时间
        '"upstreamtime":"$upstream_response_time",'
        '"upstreamhost":"$upstream_addr",'   #后端应用服务器处理时间
        '"http_host":"$host",'
        '"uri":"$uri",'
        '"xff":"$http_x_forwarded_for",
        '"referer":"$http_referer",'
        '"tcp_xff":"$proxy_protocol_addr",'
        '"http_user_agent":"$http_user_agent",'
        '"status":"$status"}';
     access_log /apps/nginx/logs/access_json.log access_json;
     
#重启Nginx并访问测试日志格式,参考链接:http://json.cn/
{"@timestamp":"2019-02-
22T08:55:32+08:00","host":"10.0.0.8","clientip":"10.0.0.1","size":162,"responset
ime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"www.magedu.org","uri":"/favicon.ico","xff":"-","referer":"-
","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; 
rv:65.0) Gecko/20100101 Firefox/65.0","status":"404"}

4.3、json格式的日志访问统计

#python3
[root@centos8 ~]#dnf -y install python3
[root@centos8 ~]#cat log.py
#!/usr/bin/env python3
#coding:utf-8
status_200= []
status_404= []
with open("access_json.log") as f:
    for line in f.readlines():
        line = eval(line)
        if line.get("status") == "200":
            status_200.append(line.get)
        elif line.get("status") == "404":
            status_404.append(line.get)
        else:
            print("状态码 ERROR")
        print((line.get("clientip")))
f.close()
print("状态码200的有--:",len(status_200))
print("状态码404的有--:",len(status_404))
#python2
[root@centos8 ~]#dnf -y install python2
[root@centos8 ~]#cat log.py
#!/usr/bin/env python
#coding:utf-8
status_200= []
status_404= []
with open("access_json.log") as f:
    for line in f.readlines():
        line = eval(line)
        if line.get("status") == "200":
            status_200.append(line.get)
        elif line.get("status") == "404":
            status_404.append(line.get)
        else:
            print("状态码 ERROR")
        print(line.get("clientip"))
f.close()
print "状态码200的有--:",len(status_200)
print "状态码404的有--:",len(status_404) #保存日志文件到指定路径并进测试:
[root@centos7 ~]# python nginx_json.py 
状态码200的有--: 1910
状态码404的有--: 13
    
    
#转换python2语法到python3
[root@centos8 ~]#pip3 install 2to3
[root@centos8 ~]#2to3 -w log.py