【002】Nginx学习笔记-配置文件详解,自定义日志,虚拟主机,访问控制,nginx-echo模块,location详解
1 配置文件解析
1.1 配置文件组成
nginx主配置文件主要有以下几大块
-
全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
-
events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。epoll
-
http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
-
server块:配置虚拟主机的相关参数,一个http中可以有多个server。
-
location块:配置请求的路由,以及各种页面的处理情况。
[root@nginx nginx-1.18.0]# vim /usr/local/nginx/conf/nginx.conf
#user nobody; #nginx用户及组,如果用户和组名一样可只写一个
worker_processes 1; #定义了nginx对外提供web服务时的worker进程数。
#最优值取决于许多因素,包括(但不限于)CPU核的数量、存储数据的硬盘 数量及负载模式。
#不能确定的时候,将其设置为可用的CPU核心数将是一个好的开始(设置为“auto”将尝试自动检测它)
查看配置文件
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024; #每个进程的最大连接数,根据需要调整大小
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream;
server_tokens off; #隐藏软件版本号
#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 logs/access.log main; #定义日志文件
sendfile on; #开启高效文件传输模式
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65; #长连接超时时间
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
1.2 更改配置文件
- 更改line 2 的 user 从nobody 为我们之前创建的nginx
- worker_peocesses 1;(根据cpu数量来定)我选择设置为auto
查看work process 是否成功
[root@nginx nginx-1.18.0]# ps aux |grep nginx
root 3891 0.0 0.1 45972 1124 ? Ss 09:28 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 3892 0.0 0.2 46412 2116 ? S 09:28 0:00 nginx: worker process
root 3993 0.0 0.0 112824 980 pts/0 S+ 10:01 0:00 grep --color=auto nginx
2 自定义日志
2.1 日志的基本格式
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
$remote_addr 客户端ip
$remote_user 用户名(为基本用户认证提供的用户名, 通常没有)
$time_local 访问时间
$request 请求行
$status 状态码
$body_bytes_sent 返回给客户端的字节数,不含响应头
$http_referer 从哪个页面链接访问过来的
$http_user_agent 客户端浏览器
$http_x_forwarded_for 客户端ip
$document_root 当前请求的root指令或alias指令的配置值
$host “Host”请求头的值,如果没有该请求头,则为与请求对应的虚拟主机的首要主机名
更多的变量前往官方文档查看:按字母排序 Alphabetical index of variables
查看日志:
[root@nginx nginx-1.18.0]# tail /usr/local/nginx/logs/access.log
192.168.23.1 - - [23/May/2022:09:31:52 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36"
2.2 创建自定义日志
-
更改http模块的format_log 与 server模块中的 access_log main
-
重启nginx
[root@nginx nginx-1.18.0]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx nginx-1.18.0]# nginx -s reload
- 用 tail -0f 监控日志
[root@nginx nginx-1.18.0]# tail -0f /usr/local/nginx/logs/host.access.log
- 访问(刷新)一次网页
- 发现访问,输出客户端ip与请求行
[root@nginx nginx-1.18.0]# tail -0f /usr/local/nginx/logs/host.access.log
192.168.23.1 GET / HTTP/1.1
3 虚拟主机
从客户端角度来看,每台虚拟主机是一个独立的服务器。
从服务器角度来看,每台虚拟主机对应只是一个server的配置。
- 在http模块内创建三个server如下:
(删除之前test的自定义日志)
server {
listen 80;
server_name www.server1.com;
access_log /www/server1/logs/host.access.log main;
error_log /www/server1/logs/host.error.log;
location / {
root /www/server1/html;
index index.html;
}
}
server {
listen 80;
server_name www.server2.com;
access_log /www/server2/logs/host.access.log main;
error_log /www/server2/logs/host.error.log;
location / {
root /www/server2/html;
index index.html;
}
}
server {
listen 80;
server_name www.server3.com;
access_log /www/server3/logs/host.access.log main;
error_log /www/server3/logs/host.error.log;
location / {
root /www/server3/html;
index index.html;
}
}
- 去掉log_format main 这部分的#使之可用
3.创建相应的文件夹,并在不同的index.html内输入不同的值
[root@nginx conf]# mkdir /www/server{1..3}/{logs,html} -p
[root@nginx conf]# echo server1 > /www/server1/html/index.html
[root@nginx conf]# echo server2 > /www/server2/html/index.html
[root@nginx conf]# echo server3 > /www/server3/html/index.html
[root@nginx conf]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx conf]# nginx -s reload
打开另一台虚拟机
[root@client ~]# vim /etc/hosts
在hosts内添加nginx服务端的ip与server
客户端在测试时要进行解析
访问成功
4 访问控制
4.1 用户认证
有时我们会有这么一种需求,就是你的网站并不想提供一个公共的访问或者某些页面不希望公开,我们希望的是某些特定的客户端可以访问.
那么我们可以在访问时要求进行身份认证, 就如给你自己的家门加一把锁, 以拒绝那些不速之客.
我们在服务课程中学习过apache的访问控制,对于Nginx来说同样可以实现,并且整个过程和Apache 非常的相似:
我们在server1中尝试
[root@nginx ~]# yum -y install httpd-tools
[root@nginx ~]# htpasswd -c /www/server1/.htpasswd tom
New password:
Re-type new password:
Adding password for user tom
# 查看加密存放的密码
[root@nginx ~]# cat /www/server1/.htpasswd
tom:$apr1$sN7i3YHz$PUYGG3vRfa0uauOUYQojC1
# 在创建一个jerry,去掉 -c 避免覆盖tom
[root@nginx ~]# htpasswd /www/server1/.htpasswd jerry
New password:
Re-type new password:
Adding password for user jerry
# 重载
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
成功
4.2 访问控制的方法
方法一:deny/allow 顺序:从上到下,匹配即停止
允许客户端访问,然后拒绝所有
客户端访问成功
[root@client ~]# curl www.server1.com
server1
主机访问被拒绝
方法二:黑/白名单
可以使用geo模块定义一个访问控制的黑/白名单
geo指令可以根据客户端的IP地址来给变量定义不同的值,语法如下:
Syntax: geo [$address] $variable { … }
Default: —
Context: http
例:禁止 192.168.10.11 和 127.0.0.1 访问
...
geo $black_list {
default 0;
192.168.10.11 1;
127.0.0.1 1;
}
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
if ($black_list) {
return 403;
}
...
}
...
限速
可使用limit_rate指令进行限速
用法:
Syntax: limit_rate rate; # 1.17.0以上的版本支持使用变量作为limit_rate的值
Default: limit_rate 0;
Context: http, server, location, if in location
map指令
map指令根据一个字符串来定义另一个变量的值
用法:
Syntax: map string $variable { ... }
Default: —
Context: http
我们可以利用geo和map方便的实现分段限速:
geo $limit {
default 2;
192.168.10.11 1;
192.168.10.13 0;
}
map $limit $rate {
2 128k;
1 1m;
0 0;
}
server { ...
...
location /download/ {
autoindex on; # 当目录中没有 index 文件时列出文件列表, 默认为 off
limit_rate $rate;
}
...
}
5 状态访问
状态访问统计:
在server中添加如下行
location = /status {
stub_status on; #打开状态页面
access_log off; #自己访问不用记录到访问日志
}
查看访问状态统计:
浏览器:http://192.168.10.11/status 刷新可得到如下变化结果
Active connections: 557
server accepts handled requests
36573075 36573075 43806112
Reading: 3 Writing: 16 Waiting: 538
-
Active connections
活动连接数 -
server accepts handled requests
nginx总共处理了36573075个连接, 成功创建36573075次握手 (相等表示中间没有失败的), 总共处理了43806112个请求 (平均每次握手处理了1.2个数据请求). -
Reading
nginx读取到客户端的Header信息数. -
Writing
nginx返回给客户端的Header信息数. -
Waiting
开启keep-alive的情况下,这个值等于active - (reading + writing),意思就是Nginx说已经处理完正在等候下一次请求指令的驻留连接.
6 nginx-echo模块
6.1 安装模块
Nginx-echo可以在Nginx中用来输出一些信息,是在测试排错过程中一个比较好的工具
它可以将信息进行汇总输出, 给维护人员带来很大帮助
1.下载nginx-echo模块
https://github.com/openresty/echo-nginx-module/
2.解压
```typescript
# [root@nginx ~]# cd ~
# [root@nginx ~]# tar xf echo-nginx-module-0.61.tar.gz -C /usr/local/nginx/
3.查看nginx原来的编译参数
[root@nginx ~]# nginx -V
4.进入nginx解压目录,重新编译
[root@nginx ~]# tar xf nginx-1.18.0.tar.gz
[root@nginx ~]# cd nginx-1.18.0/
[root@nginx nginx-1.18.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module (原来的编译选项) --add-module=/usr/local/nginx/echo-nginx-module-0.61/
[root@nginx ~]# make
模块仍未被添加
[root@nginx nginx-1.18.0]# nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
5.将原来的nginx二进制程序备份,使用刚编译好的新二进制程序
[root@nginx nginx-1.18.0]# ./objs/nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/usr/local/nginx/echo-nginx-module-0.61/
# mv /usr/local/nginx/sbin/nginx{,.bak}
# cp objs/nginx /usr/local/nginx/sbin/
模块添加成功
[root@nginx nginx-1.18.0]# nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/usr/local/nginx/echo-nginx-module-0.61/
至此,echo模块安装完毕.
6.重启nginx
# nginx -s stop
# nginx
6.2 nginx-echo用法
文档: https://github.com/openresty/echo-nginx-module
- echo: 可输出字符或变量,自带换行符,支持转义字符
location = /test1 {
echo "hello,world!";
}
location = /test2 {
echo -n "hello,";
echo "world!";
}
location = /test3 {
echo "$remote_addr";
}
# curl 127.0.0.1/test1
hello,world!
# curl 127.0.0.1/test2
hello,world!
# curl 127.0.0.1/test3
127.0.0.1
- echo_sleep: 暂停,后面接数字,单位为秒.
location = /timed_hello {
echo_reset_timer;
echo_sleep 2;
echo "echo-sleep takes about $echo_timer_elapsed sec.";
}
# curl 127.0.0.1/timed_hello
echo-sleep takes about 2.003 sec.
- echo_before_body,echo_after_body: 页面前输出,页面后输出
location /echo {
echo_before_body "begin";
proxy_pass http://192.168.10.42/echo;
echo_after_body "end";
}
# curl 192.168.10.42/echo/
This is test page
# curl 127.0.0.1/echo/
begin
This is test page
end
- echo_duplicate: 输出重复的字符, 不带换行符,支持转义字符
location /dup {
echo_duplicate 3 "--";
echo_duplicate 1 " END ";
echo_duplicate 3 "--";
echo;
}
# curl 127.0.0.1/dup
------ END ------