Nginx安装(CentOS)及常见配置

安装Nginx

添加Nginx源

1
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

查询

1
yum list nginx

安装

1
yum install -y nginx

卸载

1
yum -y remove nginx*

启动

1
service nginx start

停止

1
service nginx stop

设为开机启动

1
chkconfig nginx on

1
systemctl enable nginx.service

重新加载配置

1
2
nginx -t
service nginx reload

查看版本

1
nginx -v

配置文件路径/etc/nginx/conf.d

Nginx配置生效

查看配置是否可用

1
nginx -t

重新加载配置

1
nginx -s reload

全局变量

全局变量

  • $args : 这个变量等于请求行中的参数,同$query_string
  • $content_length : 请求头中的Content-length字段。
  • $content_type : 请求头中的Content-Type字段。
  • $document_root : 当前请求在root指令中指定的值。
  • $host : 请求主机头字段,否则为服务器名称。
  • $http_user_agent : 客户端agent信息
  • $http_cookie : 客户端cookie信息
  • $limit_rate : 这个变量可以限制连接速率。
  • $request_method : 客户端请求的动作,通常为GET或POST。
  • $remote_addr : 客户端的IP地址。
  • $remote_port : 客户端的端口。
  • $remote_user : 已经经过Auth Basic Module验证的用户名。
  • $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
  • $scheme : HTTP方法(如http,https)。
  • $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
  • $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
  • $server_name : 服务器名称。
  • $server_port : 请求到达服务器的端口号。
  • $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
  • $uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
  • $document_uri : 与$uri相同。

例:

http://localhost:88/test1/test2/test.php

1
2
3
4
5
6
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php

常见场景

静态网站

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
server {  
listen 80;
server_name www.psvmc.cn;
return 301 https://$server_name$request_uri;
}

server {
server_name www.psvmc.cn;

root /data/web_front/myblog/;
index index.html;

# SSL
listen 443 ssl;
ssl_certificate /etc/nginx/cert/xhkjedu.pem;
ssl_certificate_key /etc/nginx/cert/xhkjedu.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

# body size
client_max_body_size 200m;

# log
# error_log /dev/null crit;
error_log /etc/nginx/logs/error_www.psvmc.cn.log error;

# gzip
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\."; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on;

# timeout
keepalive_timeout 60;

# html不缓存 解决前端更新缓存问题
location ~ .*\.(html)$ {
add_header Cache-Control no-store;
}
}

禁用html缓存

前端项目使用VUE开发的都是单页,也就是只有一个html文件,但是每次更新可能因为用户缓存,而无法正常访问,所以建议html不进行缓存。

如果HTML文件较小建议直接禁用缓存

1
2
3
4
# html不缓存 解决前端更新缓存问题
location ~ .*\.(html)$ {
add_header Cache-Control no-store;
}

如果HTML文件较大建议使用协商方式

1
2
3
4
5
# html协商缓存 解决前端更新缓存问题
location ~ .*\.(html)$ {
# 或者用add_header Cache-Control no-cache;
add_header Pragma no-cache;
}

对比:

Pragma: no-cache:和Cache-Control: no-cache区别

  • Pragma: no-cacheCache-Control: no-cache作用相同

  • Pragma: no-cache可以应用到http 1.0 和http 1.1

  • Cache-Control: no-cache只能应用于http 1.1.

Cache-Control: no-cache和Cache-Control: no-store区别

看字面意思容易误解,no-cache就是不缓存,但是no-cache并不是不缓存,而是使用协商缓存,所以并不能禁止缓存,no-store才是真正的禁止缓存。

从节省带宽角度讲,使用no-cache更优一点,文件未发生改变时只传输很小的报文大小,只有在文件改变时才会传输整个文件大小。而不是no-store不管什么情况都传输整个文件大小。

反代接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {  
listen 80;
server_name mapi.psvmc.cn;
listen 443 ssl;
ssl_certificate /etc/nginx/cert/xhkjedu.pem;
ssl_certificate_key /etc/nginx/cert/xhkjedu.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
error_log /etc/nginx/logs/error_mapi.psvmc.cn.log error;

location / {
client_max_body_size 1000m;
client_body_buffer_size 128k;
client_body_timeout 5m;

send_timeout 20s;

proxy_pass http://172.24.197.8:9011/;
proxy_cookie_path / /;
proxy_redirect / /;
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_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_buffer_size 64k;
proxy_buffers 8 64k;
}
}

反代WS

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
upstream imtest_xhkjedu {   
server 123.123.123.123:8090;
}

server {
listen 80;
server_name imtest.abc.com;
client_max_body_size 200m;
location / {
proxy_pass http://imtest_xhkjedu/;
proxy_cookie_path / /;
proxy_redirect / /;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_buffer_size 64k;
proxy_buffers 8 64k;
client_max_body_size 200m;
client_body_buffer_size 128k;
send_timeout 60;
}
}

相比之前配置的HTTP代理 主要增加了以下配置

1
2
3
4
5
6
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

无法获取IP

1
2
3
4
5
6
7
8
9
location /ws/  {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

注意

只有建立连接的时候才能获取到IP。

获取IP

1
2
3
ws.on('connection', function connection(ws, req) {
const ip = req.connection.remoteAddress;
});

Java

1
2
3
4
String address = session.remoteAddress().toString();
String host = headers.get("Host");
String xrealip = headers.get("X-Real-IP");
String xforwardedfor = headers.get("X-Forwarded-For");

分别取到的地址为

address: 127.0.0.1:48630

host: sockettest2.xhkjedu.com

xrealip: 123.14.108.207

xforwardedfor: 123.14.108.207

其中X-Real-IPX-Forwarded-For获取到的是用户的IP。

负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
upstream a_psvmc {  
server a.psvmc.cn:8080;
server a.psvmc.cn:9080;
ip_hash;
}

server {
listen 80;
server_name a.psvmc.cn;

location / {
proxy_pass http://a_psvmc;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}

动静分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
upstream filetest_psvmc {   
server 127.0.0.1:8905;
}


server {
listen 80;
server_name filetest.psvmc.cn;
listen 443;
ssl on;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

location ^~ /static/ {
index index.html;
root /data/wwwjarapi/8905xhkjfileapitest/;
}

location / {
client_max_body_size 1000m;
client_body_buffer_size 128k;
client_body_timeout 5m;

proxy_pass http://filetest_psvmc/;
proxy_cookie_path / /;
proxy_redirect / /;
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_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_buffer_size 64k;
proxy_buffers 8 64k;
send_timeout 20s;
}
}

注意

20行的代码root的路径不要配置为/data/wwwjarapi/8905xhkjfileapitest/static/

否则会在static文件夹下再查找static文件夹

正向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
server {
resolver 114.114.114.114;#指定DNS服务器IP地址
listen 1080;
location / {
proxy_pass http://$host$request_uri; #设定代理服务器的协议和地址
proxy_set_header HOST $host;
proxy_buffers 256 4k;
proxy_max_temp_file_size 0k;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_next_upstream error timeout invalid_header http_502;
}
}

server {
resolver 114.114.114.114;#指定DNS服务器IP地址
listen 1443;
location / {
proxy_pass https://$host$request_uri;#设定代理服务器的协议和地址
proxy_buffers 256 4k;
proxy_max_temp_file_size 0k;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_next_upstream error timeout invalid_header http_502;
}
}

测试

1
2
curl  -I --proxy 192.168.10.10:1080 www.baidu.com
curl -I --proxy 192.168.10.10:1443 www.baidu.com

代理Mysql/远程连接/SSH

详细文章查看:https://www.psvmc.cn/article/2020-12-31-nginx-tcp.html

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
stream {
upstream ssh {
server 192.168.0.143:22;
}

server {
listen 3333;
proxy_connect_timeout 1h;
proxy_timeout 1h;
proxy_pass ssh;
}

upstream mstsc {
server 192.168.0.19:3389;
}

server {
listen 13389;
proxy_connect_timeout 1h;
proxy_timeout 1h;
proxy_pass mstsc;
}

upstream mysql {
server 192.168.0.143:3306;
}

server {
listen 13306;
proxy_connect_timeout 1h;
proxy_timeout 1h;
proxy_pass mysql;
}
}

注意该配置要和http同级

SSL配置

/etc/nginx/cert目录放入证书文件

  • psvmc.pem
  • psvmc.key

Nginx的配置文件添加如下配置

1
2
3
4
5
6
7
8
listen 443;
ssl on;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

配置完成后基本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
upstream test_psvmc {   
server 111.111.111.111:8090;
}


server {
listen 443;
server_name test.psvmc.com;
client_max_body_size 200m;
ssl on;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass https://test_psvmc/;
proxy_cookie_path / /;
proxy_redirect / /;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 200m;
client_body_buffer_size 128k;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_buffer_size 64k;
proxy_buffers 8 64k;
send_timeout 60;
}
}

重启

1
2
nginx -t
service nginx reload

HTTP自动跳转HTTPS

方式1:使用return

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name psvmc.cn;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl;
server_name psvmc.cn;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
# other
}

如果此时nginx作为Tomcat的前端反向代理的话,需要将相应配置放在配置ssl的server块中。

方式2:使用rewrite

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name psvmc.cn;
rewrite ^(.*) https://$server_name$1 permanent;
}

server {
listen 443 ssl;
server_name psvmc.cn;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
# other
}

如果此时nginx作为Tomcat的前端反向代理的话,需要将相应配置放在配置ssl的server块中。

方式3:使用error_page

只允许HTTP来访问时,用HTTP访问会让Nginx报497错误,然后利用error_page将链接重定向至HTTPS上。

1
2
3
4
5
6
7
8
9
server {
listen 80;
listen 443 ssl;
server_name psvmc.cn;
ssl_certificate /etc/nginx/cert/psvmc.pem;
ssl_certificate_key /etc/nginx/cert/psvmc.key;
# other
error_page 497 https://$server_name$request_uri;
}

使用error_page指令时,将http和https的监听配置写在同一个server块中,对应的其他配置也需要在该server配置块中完成。

需要注意的是,此时需要将error_page指令语句写在最后,否则不能生效。

location

基本语法

1
location [=|~|~*|^~|@] pattern{……}
  • = 严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。
  • ~ 匹配区分大小写的定的正则表达式
  • ~* 匹配不区分大小写的定的正则表达式
  • ^~ 类似于无修饰符的行为,也是以指定模式开始,不同的是,如果模式匹配,
    那么就停止搜索其他模式了
  • !~ 不匹配区分大小写的定的正则表达式
  • !~* 不匹配不区分大小写的定的正则表达式

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
location = / {
# 只匹配 / 的查询.
[ configuration A ]
}

location / {
# 匹配任何以 / 开始的查询,但是正则表达式与一些较长的字符串将被首先匹配。
[ configuration B ]
}

location ^~ /images/ {
# 匹配任何以 /images/ 开始的查询并且停止搜索,不检查正则表达式。
[ configuration C ]
}

location ~* \.(gif|jpg|jpeg)$ {
# 匹配任何以gif, jpg, or jpeg结尾的文件,但是所有 /images/ 目录的请求将在Configuration C中处理。
[ configuration D ]
}

location ~*.(gif|jpg|swf)$ {
valid_referers none blocked image.psvmc.cn static.psvmc.cn;
if ($invalid_referer) {
#防盗链
rewrite ^/ http://$host/daolian.png;
}
[ configuration E ]
}

各请求的处理如下例:

  • / → configuration A
  • /documents/document.html → configuration B
  • /images/1.gif → configuration C
  • /documents/1.jpg → configuration D

查找顺序

模式 含义
location = /uri = 表示精确匹配,只有完全匹配上才能生效
location ^~ /uri ^~ 开头对URL路径进行前缀匹配,并且在正则之前。
location ~ pattern 开头表示区分大小写的正则匹配
location ~* pattern 开头表示不区分大小写的正则匹配
location /uri 不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location / 通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default

优先级

  1. 精确匹配 =
  2. 前缀匹配 ^~
  3. 按文件中从前到后顺序的正则匹配
  4. 匹配不带任何修饰的前缀匹配
  5. 交给/通用匹配
  6. 当有匹配成功时候,停止匹配,按当前匹配规则处理请求

root、alias指令区别

1
2
3
4
5
6
7
8
9
location /img/ {
alias /var/www/image/;
}
#若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件

location /img/ {
root /var/www/image;
}
#若按照这种配置的话,则访问/img/目录下的文件时,nginx会去/var/www/image/img/目录下找文件。]

区别

  • alias是一个目录别名的定义,root则是最上层目录的定义。
  • alias后面必须要用/结束,否则会找不到文件的 而root则可有可无

大文件上传

1
2
3
4
5
6
7
client_max_body_size     1000m;
client_header_timeout 1m;
client_body_timeout 5m;
proxy_connect_timeout 60s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;
send_timeout 20s;

每个参数的意思:

client_max_body_size

限制请求体的大小,若超过所设定的大小,返回413错误。

client_header_timeout

读取请求头的超时时间,若超过所设定的大小,返回408错误。

client_body_timeout

读取请求实体的超时时间,若超过所设定的大小,返回413错误。

proxy_connect_timeout

http请求无法立即被容器(tomcat, netty等)处理,被放在nginx的待处理池中等待被处理。

此参数为等待的最长时间,默认为60秒,官方推荐最长不要超过75秒。

proxy_read_timeout

http请求被容器(tomcat, netty等)处理后,nginx会等待处理结果,也就是容器返回的response。

此参数即为服务器响应时间,默认60秒。

proxy_send_timeout

http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒。

send_timeout

服务器把结果返回的时间

大文件上传费时的是文件到代理服务器(Nginx)的时间,所以proxy_xxx相关的时间不用配置的过长

文件下载

1
2
3
4
5
6
location /download/ {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'application/octet-stream';
alias /data/wwwjarapi/8908schoolfiletest/static/;
}

关键语句

add_header ‘Content-Type’ ‘application/octet-stream’;

重定向

GET请求

301重定向

1
2
3
location = /static/应用.apk {
return 301 https://psvmc.oss-cn-huhehaote.aliyuncs.com/client/123.apk;
}

规则路径是可以支持中文的。

重写

主要用于地址迁移 重定向到新的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {  
server_name zujuan.xhkjedu.com;
client_max_body_size 200m;
listen 443;
ssl on;
ssl_certificate /etc/nginx/cert/xhkjedu.pem;
ssl_certificate_key /etc/nginx/cert/xhkjedu.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
index index.html;
root /data/web_front/zujuan;


location /userapi/login {
rewrite ^/userapi/login$ https://zujuan.xhkjedu.com/userapi/tip.json;
}
}

主要配置是

1
2
3
location /userapi/login {
rewrite ^/userapi/login$ https://zujuan.xhkjedu.com/userapi/tip.json;
}

注意

rewrite是302重定向,会把post请求重定向为get请求。

POST请求

307重定向

  • 301 永久重定向,告诉客户端以后应从新地址访问.
  • 302 作为HTTP1.0的标准,以前叫做Moved Temporarily ,现在叫Found. 现在使用只是为了兼容性的处理,包括PHP的默认Location重定向用的也是302.

但是HTTP 1.1 有303 和307作为详细的补充,其实是对302的细化

  • 303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。
  • 307:对于POST请求,表示请求还没有被处理,客户端应该向Location里的URI重新发起POST请求。

大部分浏览器 302 会将 POST 请求转为 GET

1
2
3
location ~ ^/userapi/login {
return 307 https://www.psvmc.cn/sapi/userapi/login;
}

反代

1
2
3
location ~ ^/userapi/login {
proxy_pass https://www.psvmc.cn/sapi/userapi/login;
}

日志

默认位置

使用yum安装的Nginx的默认日志位置

1
cd /var/log/nginx

示例

创建文件夹

1
mkdir /etc/nginx/logs/

项目对应的配置文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name psvmc.cn www.psvmc.cn;

location / {
root /data/www/www;
index index.html index.htm;
}

access_log /etc/nginx/logs/access_www.psvmc.cn.log buffer=32k flush= 5s;
error_log /etc/nginx/logs/error_www.psvmc.cn.log error;
log_not_found off;
}

错误日志

1
error_log  <FILE>  <LEVEL>;

关键字:其中关键字error_log不能改变

日志文件:可以指定任意存放日志的目录

错误日志级别:常见的错误日志级别有[debug | info | notice | warn | error | crit | alert | emerg],级别越高记录的信息越少。

生产场景一般是 warn | error | crit 这三个级别之一

关闭错误日志

只禁用无法找到的错误日志

1
log_not_found off;

禁用所有错误日志

error_log off并不能关闭日志记录功能,它将日志文件写入一个文件名为off的文件中,如果你想关闭错误日志记录功能,应使用以下配置:

把存储位置设置到Linux的黑洞中去

1
error_log /dev/null crit;

访问日志

默认

1
2
3
4
5
6
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;
}

其中main是定义日志格式化方式的名称log_format main

关闭访问日志

1
access_log  off;

连接数查看

Nginx连接数

1
netstat -apn|grep 'nginx: worker'|wc -l

系统连接数

1
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

查看TIME_WAIT

单独查看TIME_WAIT

1
ss -nat | grep TIME-WAIT

image-20220111153246667

这里看到大部分都是9001和9011端口的服务占用的

我们查询一下数量

1
2
ss -nat | grep TIME-WAIT | grep 9001 | wc -l
ss -nat | grep TIME-WAIT | grep 9011 | wc -l

TIME_WAIT状态产生的原因

TIME_WAIT产生于tcp连接的4次挥手阶段,并且产生在主动断开连接的一方
这里假设是客户端首先发起断开连接的请求,过程如下
a、客户端先发送FIN,进入FIN_WAIT1状态
b、服务端收到FIN,发送ACK,进入CLOSE_WAIT状态,客户端收到这个ACK,进入FIN_WAIT2状态
c、服务端发送FIN,进入LAST_ACK状态
d、客户端收到FIN,发送ACK,进入TIME_WAIT状态,服务端收到ACK,进入CLOSE状态
客户端TIME_WAIT持续2倍MSL时长,在linux体系中大概是60s,转换成CLOSE状态
注:MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,MSL指明TCP报文在Internet上最长生存时间,每个具体的TCP实现都必须选择一个确定的MSL值.RFC 1122建议是2分钟,但BSD传统实现采用了30秒.TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟.在redhat和centos系统中MSL也是采用的30秒

三次握手和四次挥手

tcp

高并发配置优化

工作进程数与进程连接数

worker_processes和worker_connections

/etc/nginx/nginx.conf中配置

1
2
3
4
5
6
7
8
worker_processes  auto;
worker_rlimit_nofile 256000;

events {
use epoll;
worker_connections 65535;
multi_accept on;
}

查看CPU逻辑数量

1
cat /proc/cpuinfo | grep "processor" | wc -l

超时时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server{
keepalive_timeout 60;
keepalive_requests 10240;
tcp_nodelay on;
client_header_buffer_size 4k;
open_file_cache max=102400 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
client_header_timeout 15;
client_body_timeout 15;
reset_timedout_connection on;
send_timeout 15;
server_tokens off;
client_max_body_size 1000m;
}

其中:

keepalived_timeout 60:客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接
keepalive_requests 10240:参数限制了一个 HTTP 长连接最多可以处理完成的最大请求数, 默认是 100。当连接处理完成的请求数达到最大请求数后,将关闭连接。
tcp_nodelay:也是防止网络阻塞,不过要包涵在keepalived参数才有效
client_header_buffer_size 4k:客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过 1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
open_file_cache max=102400 inactive=20s:这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
open_file_cache_valid 30s:这个是指多长时间检查一次缓存的有效信息。
open_file_cache_min_uses 1:open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
client_header_timeout:设置请求头的超时时间。我们也可以把这个设置低些,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误
client_body_timeout:设置请求体的超时时间。我们也可以把这个设置低些,超过这个时间没有发送任何数据,和上面一样的错误提示
reset_timeout_connection:告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。
send_timeout:响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接
server_tokens:并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。
client_max_body_size:上传文件大小限制

启用Gzip压缩

建议在全局http下配置

非常有效

1
2
3
4
5
6
7
8
9
server{
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\."; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on;
}

禁用access_logs

建议在全局http下配置

访问日志记录,它记录每个nginx请求,因此消耗了大量CPU资源,从而降低了nginx性能。

完全禁用访问日志记录

1
2
3
4
server{
log_not_found off;
access_log off;
}

注:log_not_found off;是否在error_log中记录不存在的错误。默认是记录。

防盗链

防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量,那么我们的解决办法由几种:
1:水印,品牌宣传,你的带宽,服务器足够
2:防火墙,直接控制,前提是你知道IP来源
3:防盗链策略下面的方法是直接给予404的错误提示
如:

1
2
3
4
5
6
7
8
9
location ~*^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
valid_referers none blocked www.psvmc.cn psvmc.cn;
if($invalid_referer) {
#return 302 http://www.psvmc.com/img/nolink.jpg;
return 404;
break;
}
access_log off;
}

参数可以使如下形式:none 意思是不存在的Referer头(表示空的,也就是直接访问,比如直接在浏览器打开一个图片)

blocked 意为根据防火墙伪装Referer头,如:“Referer:XXXXXXX”。server_names 为一个或多个服务器的列表,0.5.33版本以后可以在名称中使用\*通配符

expires缓存调优

缓存,主要针对于图片,css,js等元素更改机会比较少的情况下使用,特别是图片,占用带宽大,我们完全可以设置图片在浏览器本地缓存365d,css,js,html可以缓存个10来天,这样用户第一次打开加载慢一点,第二次,就非常快了!缓存的时候,我们需要将需要缓存的拓展名列出来, Expires缓存配置在server字段里面,如:

1
2
3
4
5
6
7
8
9
10
11
location ~* \.(ico|jpe?g|gif|png|bmp|swf|flv)$ {
expires 30d;
log_not_found off;
access_log off;
}

location ~* \.(js|css)$ {
expires 7d;
log_not_found off;
access_log off;
}

fastcgi调优

fastcgi配置优化,如:

1
2
3
4
5
6
7
8
9
10
fastcgi_connect_timeout    600;
fastcgi_send_timeout 600;
fastcgi_read_timeout 600;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_temp_path/usr/local/nginx1.10/nginx_tmp;
fastcgi_intercept_errors on;
fastcgi_cache_path/usr/local/nginx1.10/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:128minactive=1d max_size=10g;

fastcgi_connect_timeout:指定连接到后端FastCGI的超时时间,如:600
fastcgi_send_timeout:向FastCGI传送请求的超时时间,如:600
fastcgi_read_timeout:指定接收FastCGI应答的超时时间,如:600
fastcgi_buffer_size:指定读取FastCGI应答第一部分需要用多大的缓冲区,默认的缓冲区大小为fastcgi_buffers指令中的每块大小,可以将这个值设置更小,如: 64k。
fastcgi_buffers:指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,如果一个php脚本所产生的页面大小为256KB,那么会分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp_path指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于磁盘。一般这个值应该为站点中php脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“8 32K”、“4 64k”等。如:4 64k
fastcgi_busy_buffers_size:建议设置为fastcgi_buffers的两倍,繁忙时候的buffer,如:128k
fastcgi_temp_file_write_size:在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍,该数值设置小时若负载上来时可能报502BadGateway,如:128k
fastcgi_temp_path:缓存临时目录
fastcgi_intercept_errors:这个指令指定是否传递4xx和5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息,如:on
fastcgi_cache_path:如: /usr/local/nginx1.10/fastcgi_cachelevels=1:2keys_zone=cache_fastcgi:128minactive=1d max_size=10g: fastcgi_cache缓存目录,可以设置目录层级,比如1:2会生成16*256个子目录,cache_fastcgi是这个缓存空间的名字,cache是用多少内存(这样热门的内容nginx直接放内存,提高访问速度),inactive表示默认失效时间,如果缓存数据在失效时间内没有被访问,将被删除,max_size表示最多用多少硬盘空间。
fastcgi_cache cache_fastcgi:表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502的错误放生。cache_fastcgi:为proxy_cache_path指令创建的缓存区名称

fastcgi_cache_valid 200 302 1h:用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一小时,要和fastcgi_cache配合使用
fastcgi_cache_valid 301 1d:将301应答缓存一天
fastcgi_cache_valid any 1m:将其他应答缓存为1分钟
fastcgi_cache_min_uses 1:该指令用于设置经过多少次请求的相同URL将被缓存。

总结:
nginx的缓存功能有:proxy_cache / fastcgi_cache
proxy_cache的作用是缓存后端服务器的内容,可能是任何内容,包括静态的和动态。proxy_cache缓存减少了nginx与后端通信的次数,节省了传输时间和后端宽带。
fastcgi_cache的作用是缓存fastcgi生成的内容,很多情况是php生成的动态的内容。fastcgi_cache缓存减少了nginx与php的通信的次数,更减轻了php和数据库(mysql)的压力。

代理与反向代理

img

正向代理

正向代理通过上面的图理解其实就是用户想从服务器拿资源数据,但是只能通过proxy服务器才能拿到,所以用户A只能去访问proxy服务器然后通过proxy服务器去服务器B拿数据,这种情况用户是明确知道你要访问的是谁,在我们生活中最典型的案例就是“翻墙“了,也是通过访问代理服务器最后访问外网的。

反向代理

反向代理其实就是客户端去访问服务器时,他并不知道会访问哪一台,感觉就是客户端访问了Proxy一样,而实则就是当proxy关口拿到用户请求的时候会转发到代理服务器中的随机(算法)某一台。而在用户看来,他只是访问了Proxy服务器而已,典型的例子就是负载均衡了。

常见错误

端口无法绑定

nginx: [emerg] bind() to 0.0.0.0:8091 failed (13: Permission denied)

是开启selinux 导致的

查看状态 如果输出 disabledPermissive 那就是关闭了
如果输出 Enforcing 那就是开启了 selinux

1
getenforce

临时关闭

1
2
3
4
# 临时关闭
setenforce 0
# 临时开启
setenforce 1

永久关闭

修改/etc/selinux/config文件

1
vi /etc/selinux/config

1
SELINUX=enforcing

改为

1
SELINUX=disabled

立即生效

1
source /etc/selinux/config

静态项目访问403

编辑配置文件

1
vi /etc/nginx/nginx.conf

修改内容

用户修改为root 默认是nginx

1
user root;

输入

1
getenforce

出现Enforcing表示已强制执行安全策略了

配置关闭

1
vi /etc/selinux/config

修改为disable

SELINUX=disabled

重启

1
reboot