企业级高性能web服务器之Nginx详解

一、Nginx 高并发

1.1 同步与异步

同步与异步的重点在消息通知的方式上,也就是调用结果的通知方式不同。

同步:当一个同步调用发出去后,调用者要一直等待调用的结果通知后,才能进行后续的执行。
​
异步:当一个异步调用发出去后,调用者不必一直等待调用结果的返回,异步调用,要想获得结果,

一般有两种方式:

1、主动轮询异步调用的结果;
​
2、被调用方通过callback(回调通知)来通知调用方调用结果。

实例解释:

同步取快递:小明收到快递将送达的短信,在楼下一直等到快递送达。

异步取快递:小明收到快递将送达的短信,快递到楼下后,小明再下楼去取。

异步取快递,小明知道快递到达楼下有两种方式:

1、不停的电话问快递小哥到了没有,即主动轮询;
​
2、快递小哥到楼下后,打电话通知小明,然后小明下楼取快递,即回调通知。
1.2 阻塞与非阻塞

阻塞与非阻塞的重点在于进/线程等待消息时候的行为,也就是在等待消息的时候,当前进/线程是挂起状态,还是非挂起状态。

阻塞:调用在发出去后,在消息返回之前,当前进/线程会被挂起,直到有消息返回,当前进/线程才会被激活
​
非阻塞:调用在发出去后,不会阻塞当前进/线程,而会立即返回。

实例解释:

阻塞取快递:小明收到快递即将送达的信息后,什么事都不做,一直专门等快递。
​
非阻塞取快递:小明收到快递即将送达的信息后,等快递的时候,还一边敲代码、一边刷微信。
​
同步与异步,重点在于消息通知的方式;阻塞与非阻塞,重点在于等消息时候的行为。

所以,就有了下面4种组合方式

1)同步阻塞:小明收到信息后,啥都不干,等快递;
​
2)同步非阻塞:小明收到信息后,边刷微博,边等着取快递;
​
3)异步阻塞:小明收到信息后,啥都不干,一直等着快递员通知他取快递;
​
4)异步非阻塞:小明收到信息后,边刷着微博,边等快递员通知他取快递。

大部分程序的I/O模型都是同步阻塞的,单个进程每次只在一个文件描述符上执行I/O操作,每次I/O系统调用都会阻塞,直到完成数据传输。传统的服务器采用的就是同步阻塞的多进程模型。一个server采用一个进程负责一个request的方式,一个进程负责一个request,直到会话结束。进程数就是并发数,而操作系统支持的进程数是有限的,且进程数越多,调度的开销也越大,因此无法面对高并发。

Nginx采用了异步非阻塞的方式工作。我们先来先了解一下I/O多路复用中的epoll模型。

epoll模型:

 当连接有I/O事件产生的时候,epoll就会去告诉进程哪个连接有I/O事件产生,然后进程就去处理这个事件。

例如:小明家楼下有一个收发室,每次有快递到了,门卫就先代收并做了标记;然后通知小明去取送给小明的快递

为什么Nginx比其他web服务器并发高 ?(Nginx工作原理)

Nginx配置use epoll后,以异步非阻塞方式工作,能够轻松处理百万级的并发连接。

处理过程:每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到可能发生阻塞的地方。比如向后端服务器转发request,并等待请求返回。那么,这个处理的worker不会这么傻等着,他会在发送完请求后,注册一个事件:“如果后端服务器返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有新的request进来,他就可以很快再按这种方式处理。而一旦后端服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。通过这种快速处理,快速释放请求的方式,达到同样的配置可以处理更大并发量的目的。

二、Nginx结构

Nginx (engine x)是一个高性能的 HTTP和反向代理 web服务器,同时也提供了 IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的 Rambler.ru站点开发的,第一个公开版本0.1.0发布于 2004年 10月 4日。Nginx是一款轻量级的 Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like协议下发行。其特点是占有内存少,并发能力强。

2.1 工作架构

nginx有两种工作模式:master-worker模式和单进程模式。在 master-worker模式下,有一个 master进程和至少一个的 worker进程,单进程模式顾名思义只有一个进程。这两种模式有各自的特点和适用场景。

master-worker

该模式下,nginx启动成功后,会有一个 master进程和至少一个的 worker进程。master进程负责处理系统信号,加载配置,管理 worker进程(启动,杀死,监控,发送消息/信号等)。worker进程负责处理具体的业务逻辑,也就是说,对外部来说,真正提供服务的是 worker进程。生产环境下一般使用

这种模式,因为这种模式有以下优点:

1.稳定性高,只要还有worker进程存活,就能够提供服务,并且一个 worker进程挂掉  master进程会立即启动一个新的 worker进程,保证worker进程数量不变,降低服务中断的概率。
​
2.配合linux的cpu亲和性配置,可以充分利用多核cpu的优势,提升性能
​
3.处理信号:配置重新加载/升级时可以做到尽可能少或者不中断服务(热重启)

单进程模式:

单进程模式下,nginx启动后只有一个进程,nginx的所有工作都由这个进程负责。由于只有一个进程,因此可以很方便地利用 gdb等工具进行调试。该模式不支持 nginx的平滑升级功能,任何的信号处理都可能造成服务中断,并且由于是单进程,进程挂掉后,在没有外部监控的情况下,无法重启服务。因此,该模式一般只在开发阶段和调试时使用,生产环境下不会使用。(了解)

2.2 nginx进程结构

2.3 配置文件结构
2.3.1 全局配置段
#user  nobody;        #程序运行的用户和组
worker_processes  1;  #启动进程,指定 nginx启动的工作进程数量,建议按照  cpu数目来指定,一般等于  cpu核心数目
​
#error_log  logs/error.log;   #定义错误日志
#error_log  logs/error.log  notice; #定义错误日志的级别
#error_log  logs/error.log  info;
​
#pid        logs/nginx.pid;   #程序Pid存放位置
​
events {
 use epoll;
accept_mutex on;  #同一时间的多个请求由worker进程轮流处理,而防止被同时唤醒多个worker,默认设置成off,新请求会唤醒所有的worker进程,此过程也被成为“惊群”,建议设置成on;
​
multi_accept on  ;  #on时nginx服务器的每个工作进程可以同时接受多个网络请求,如果设置成off,则每次只能接收一个请求,建议打开
    worker_connections  1024;  #单个工作进程的最大连接数,total_processes=worker_processes * worker_connections
}
2.3.2 http段
#http段
http {
    include       mime.types;  #文件的扩展名映射表  
    default_type  application/octet-stream;   #mime扩展支持的格式,代表.*
​
    #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 和tcp_nodelay on 两个指令设置为on,可防止网络及磁盘I/O阻塞,提升Nginx工作效率
    #tcp_nopush     on;
​
    #keepalive_timeout  0;      #会话保持的超时时间,单位为s,0代表不断开。
    keepalive_timeout  65;
          
    #gzip  on;       #压缩
2.3.3 server段
#server段
    server {              #服务配置部分
        listen       80;      #监听的端口
        server_name  localhost;   #服务器域名,可以有多个,用空格分来
        #charset koi8-r;
    
        #access_log  logs/host.access.log  main;
    
        location / {     #网站的根目录
            root   html;   #相对路径的根目录
            index index.html index.htm  index.php;  
        }                     #默认首页的类型
        
        #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$ {          #反向代理到php-fpm来处理php的页面
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi.conf;
        }
        
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
​
}
2.4 Nginx的模块

Nginx是由内核和模块构成。Nginx的模块从结构上,可以分为核心模块、基础模块和第三方模块。这些模块主要包括如下部分:

1、核心模块:HTTP模块、EVENT模块和MAIL模块。
2、基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块。
3、第三方模块:HTTP Upstream Request Hash模块、Notice模块、HTTP Access Key模块和Limit_req模块等。

如果从功能上分,Nginx的模块又可以分为以下三类:

1、处理器模块(Handlers)。 此模块直接处理请求,并进行输出内容和修改headers信息等操作,处理器模块一般只能有1个。
2、过滤器模块(Filters)。 此模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。
3、代理类模块(Proxies)。 此类模块主要与一些后端服务FastCGI等进行交互,实现服务代理和负载均衡等功能。

以下是 nginx 的常用模块的表格展示:

模块名称

功能

rewrite

重写 URL

proxy

代理

ssl

SSL 加密

worker_processes

进程数

event

事件驱动模型

resize_file

文件大小限制

http_access

HTTP 访问权限控制

http_limit_methods

HTTP 方法限制

http_limit_conn

HTTP 连接限制

http_limit_req_zone

HTTP 请求配额 zone

http_auth_login

HTTP 认证登录

http_auth_pass

HTTP 认证授权

smtp

SMTP 代理

imap

IMAP 代理

http_autoindex

HTTP 自动展开目录

x_forwarded_for

代理 IP 追踪

set_real_ip_from

代理 IP 白名单

real_ip_header

代理 IP 响应头

x_forwarded_proto

代理协议追踪

x_forwarded_端口

代理端口追踪

模块名称

模块作用

ngx_http_access_module

四层基于 IP 的访问控制,可以通过匹配客户端源 IP 地址进行限制

ngx_http_auth_basic_module

状态页,使用 basic 机制进行用户认证,在编译安装 nginx 的时候需要添加编译参数--withhttp_stub_status_module,否则配置完成之后监测会是提示语法错误

ngx_http_stub_status_module

状态统计模块

ngx_http_gzip_module

文件的压缩功能

ngx_http_gzip_static_module

静态压缩模块

ngx_http_ssl_module

nginx 的 https 功能

ngx_http_rewrite_module

重定向模块,解析和处理 rewrite 请求

ngx_http_referer_module

防盗链功能,基于访问安全考虑

ngx_http_proxy_module

将客户端的请求以 http 协议转发至指定服务器进行处理

ngx_stream_proxy_module

将客户端的请求以 tcp 协议转发至指定服务器处理

ngx_http_fastcgi_module

将客户端对 php 的请求以 fastcgi 协议转发至指定服务器助理

ngx_http_uwsgi_module

将客户端对 Python 的请求以 uwsgi 协议转发至指定服务器处理

ngx_http_headers_module

可以实现对头部报文添加指定的 key 与值

ngx_http_upstream_module

负载均衡模块,提供服务器分组转发、权重分配、状态监测、调度算法等高级功能

ngx_stream_upstream_module

后端服务器分组转发、权重分配、状态监测、调度算法等高级功能

ngx_http_fastcgi_module

实现通过 fastcgi 协议将指定的客户端请求转发至 php-fpm 处理

ngx_http_flv_module

为 flv 伪流媒体服务端提供支持

三、Nginx的基本配置管理

1.注意配置文件中的结尾有;作为结束~!(切记!)
​
2.每次实验修改完配置文件后需要重启  nginx才会生效
  • worker_rlimit_nofile 65536

3.1 nginx的信号

kill 命令 传给信号给进程 Nginx的主进程(master进程)

TERM INT(快速退出,当前的请求不执行完成就退出)
QUIT (优雅退出,执行完当前的请求后退出)
HUP(重新加我配置文件,用新的配置文件启动新worker进程,井优雅的关闭旧的worker进程)
USR1 (重新打开日志文件)
USR2(平滑的开级nginx二进制文件 拉起一个新的主进程,旧主进程不停止)
WINCH(优雅的关闭worker进程)

使用语法:

kill 选项参数   pid     ##关闭
kill -INT  / kill -TERM   pid      ##快速关闭
kill -QUIT    pid      ##优雅关闭
kill -WINCH   pid      ##优雅的关闭worker进程
[root@lnmp/usr/local/src]$ wget https://sourceforge.net/projects/pcre/files/pcre/8.41/pcre-8.41.tar.gz
[root@lnmp/usr/local/src]$ wget https://nginx.org/download/nginx-1.18.0.tar.gz
<p>[root@lnmp/usr/local/src]$ tar xf pcre-8.41.tar.gz
[root@myx01/usr/local/src/pcre-8.41]$ ./configure --prefix=/usr/local/pcre
[root@myx01/usr/local/src/pcre-8.41]$ make -j 8 && make install -j 8</p>
<p>[root@lnmp/usr/local/src]$ tar xf nginx-1.18.0.tar.gz
[root@lnmp/usr/local/src/nginx-1.18.0]$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --user=nginx --group=nginx
[root@lnmp/usr/local/src/nginx-1.18.0]$ make -j 8 && make install -j 8
[root@lnmp/usr/local/nginx/sbin]$ ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
[root@lnmp/usr/local/nginx/sbin]$ useradd -M -s /sbin/nologin nginx</p>
<p>[root@lnmp/usr/local/nginx/sbin]$ cat /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target</p>
<p>[root@lnmp/usr/local/nginx/sbin]$ chmod 754 /lib/systemd/system/nginx.service</p>
<p>[root@lnmp/usr/local/src/nginx-1.18.0]$ nginx -v
nginx version: nginx/1.18.0</p>
<p>[root@lnmp/usr/local/nginx/sbin]$ systemctl start nginx
[root@lnmp/usr/local/nginx/sbin]$ ps -ef | grep nginx
root       9263      1  0 11:13 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx      9264   9263  0 11:13 ?        00:00:00 nginx: worker process
root       9266   9089  0 11:13 pts/0    00:00:00 grep --color=auto nginx
3.2 平滑升级

升级软件版本之后,需要启动新的版本,启动不了,端口已经被占用

如果直接把旧版本的服务停止掉,会影响线上业务的使用
最佳解决办法:
1、旧的不先停掉
2、新的又可以起来
3、旧的和新的同时提供服务,旧的请求完成之后,就停掉旧进程
​
-USR2 平滑启动一个进程(平滑升级)
-WINCH 优雅的关闭子进程
-QUIT 优雅关闭主进程
3.2.1 编译安装新的版本

本次我们安装nginx-1.20的版本,获取老版本的编译参数可以使用./nginx -V来获取

升级新版本,需要和新软件的版本安装在和旧版本一致的位置上,如下:

[root@lnmp/usr/local/src]$ nginx -v
nginx version: nginx/1.18.0</p>
<p>[root@lnmp/usr/local/src]$ wget https://nginx.org/download/nginx-1.20.0.tar.gz</p>
<p>[root@lnmp/usr/local/src]$ tar xf nginx-1.20.0.tar.gz
​
[root@lnmp/usr/local/src/nginx-1.20.0]$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre=/usr/local/src/pcre-8.41 --user=nginx --group=nginx
​
[root@lnmp/usr/local/src/nginx-1.20.0]$ make -j 8 && make -j 8 install

安装完成后,会自动把旧版本的nginx备份成nginx.old。

[root@lnmp/usr/local/nginx/sbin]$ ls
nginx  nginx.old

如果想旧版本和新版本同时运行

kill -USR2  主进程号(旧nginx pid)

如果只运行新版本,先查看旧版本的主进程号,并使用kill -WINCH 优雅的关闭子进程,再关闭旧的主进程

kill -WINCH 旧的主进程号
kill -QUIT  旧的主进程号
3.2.2 版本升级的第二种方式

我们在解压新的版本./configure之后,在新版本的安装目录下有个Makefile文件,我们可以打开这个文件查看一下内容,也可以使用upgrade进行升级,其实这是nginx给我们提供的默认升级方式。

[root@lnmp/usr/local/src/nginx-1.20.0]$ cat Makefile</p>
<p>default:	build</p>
<p>clean:
rm -rf Makefile objs</p>
<p>.PHONY:	default clean</p>
<p>build:
$(MAKE) -f objs/Makefile</p>
<p>install:
$(MAKE) -f objs/Makefile install</p>
<p>modules:
$(MAKE) -f objs/Makefile modules</p>
<p>upgrade:
/usr/local/nginx/sbin/nginx -t</p>
<pre><code>kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
sleep 1
test -f /usr/local/nginx/logs/nginx.pid.oldbin

kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`

.PHONY: build install modules upgrade

操作步骤1:将新的nginx的二进制文件删除,恢复旧的版本

[root@lnmp/usr/local/nginx/sbin]$ ls
nginx  nginx.old</p>
<p>[root@lnmp/usr/local/nginx/sbin]$ mv nginx.old nginx
mv:是否覆盖"nginx"? y

操作步骤2:重新启动nginx

[root@lnmp sbin]# /etc/init.d/nginx_php.sh stop
nginx service stop success!
[root@lnmp sbin]# /etc/init.d/nginx_php.sh start
nginx service start success!
[root@lnmp sbin]# ./nginx -v
nginx version: nginx/1.18.0

操作步骤3:进入新的nginx版本,进行重新编译安装

[root@lnmp/usr/local/src]$ wget https://nginx.org/download/nginx-1.20.2.tar.gz</p>
<p>[root@lnmp/usr/local/src]$ tar xf nginx-1.20.2.tar.gz
[root@lnmp/usr/local/src]$ cd nginx-1.20.2/</p>
<p>[root@lnmp/usr/local/src/nginx-1.20.2]$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre=/usr/local/src/pcre-8.41 --user=nginx --group=nginx
​
[root@lnmp/usr/local/src/nginx-1.20.2]$ make install && make upgrade   ##这一步是在更新nginx</p>
<p>[root@lnmp/usr/local/src/nginx-1.20.2]$ nginx -v
nginx version: nginx/1.20.2</p>
<p>[root@lnmp/usr/local/src/nginx-1.20.2]$ ps -ef | grep nginx
root      41241      1  0 11:36 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     41243  41241  0 11:36 ?        00:00:00 nginx: worker process
root      41251   9089  0 11:36 pts/0    00:00:00 grep --color=auto nginx</p>
<p>[root@lnmp/usr/local/src/nginx-1.20.2]$ kill -USR2 41241
[root@lnmp/usr/local/src/nginx-1.20.2]$ kill -WINCH 41241
[root@lnmp/usr/local/src/nginx-1.20.2]$ kill -QUIT 41241</p>
<p>[root@lnmp/usr/local/src/nginx-1.20.2]$ ps -ef | grep nginx
root      41252      1  0 11:37 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     41253  41252  0 11:37 ?        00:00:00 nginx: worker process
root      41273   9089  0 11:42 pts/0    00:00:00 grep --color=auto nginx

操作步骤4:重新访问查看

3.3 Nginx的状态统计

官方网站:https://nginx.org/en/docs/http/ngx_http_stub_status_module.html

a、安装 nginx时将--with-http_stub_status_module模块开启

b、修改 nginx配置文件(写入要访问的 server标签中)

 [root@myx01/usr/local/nginx/sbin]$ nginx -V 	# 查看安装了哪些模块</p>
<p>   
#location / {
#    root   html;
#    index  index.html index.htm;
#}</p>
<pre><code>    #error_page  404              /404.html;
    location /nginx_status{
            stub_status on;
            access_log off;
    }

c、重启服务:systemctl restart nginx

d、客户端访问网址:http://IP/nginx_status

"Active connections"表示当前的活动连接数;

"server accepts handled requests"表示已经处理的连接信息

三个数字依次表示已处理的连接数、成功的 TCP握手次数、已处理的请求数,后期我们在学到zabbix的部分的时候,我们会利用这个模块来对nginx的性能进行监控。

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

官方网站:https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html

a、原理和 apache的目录保护原理一样(利用上一个实验接着完成)

b、在状态统计的 location中添加:

auth_basic "Welcome to nginx_status!";
​
auth_basic_user_file /usr/local/nginx/html/htpasswd.nginx;

c、使用 http的命令 htpasswd进行用户密码文件的创建(生成在上面指定的位置)

[root@localhost conf]# htpasswd -c /usr/local/nginx/html/htpasswd.nginx user1
New password:
Re-type new password:
Adding password for user user1
​
注意:第二次创建用户加-b选项 # 如果报错就取消-b选项

注意:htpasswd命令是没有的,centos需要安装httpd—tools,ubuntu需要安装apache2-utils

d、重启 nginx并再次访问统计页面

3.5 基于 IP的身份验证(访问控制)

官方网站:https://nginx.org/en/docs/http/ngx_http_access_module.html

a、接着上一个实验完成操作

b、在状态统计的 location中添加:

allow 192.168.1.130;
deny 192.168.1.0/24;
仅允许 192.168.1.130访问服务器

3.6 nginx的虚拟主机(基于域名)
a、提前准备好两个网站的域名,并且规划好两个网站网页存放目录
​
b、在 Nginx主配置文件中并列编写两个  server标签,并分别写好各自信息

编写nginx.conf配置文件

[root@lnmp/usr/local/nginx/conf]$ vim nginx.conf
include /apps/nginx/conf/conf.d/*.conf;</p>
<p>[root@lnmp/usr/local/nginx/conf/conf.d]$ cat it.myx.com.conf
server {
listen 80;
server_name it.myx.com;
index index.html index.htm index.php;
root  html/it;
}</p>
<p>[root@lnmp/usr/local/nginx/conf/conf.d]$ cat bbs.myx.com.conf
server {
listen 80;
server_name bbs.myx.com;
index index.html index.htm index.php;
root  html/bbs;
}
[root@lnmp/usr/local/nginx/html]$ cat /usr/local/nginx/html/it/index.html
it
[root@lnmp/usr/local/nginx/html]$ cat /usr/local/nginx/html/bbs/index.html
bbs

c、添加本地hosts的解析

[root@lnmp/usr/local/nginx/html]$ vim /etc/hosts
10.0.0.8 it.myx.com
10.0.0.8 bbs.myx.com

d、重载配置

[root@lnmp/usr/local/nginx/html]$ systemctl reload nginx</p>
<h2 id="[root@lnmp/usr/local/nginx/html]$ curl it.myx.com
it
[root@lnmp/usr/local/nginx/html]$ curl bbs.myx.com
bbs</code></pre><p style="text-align: start; ">e、访问测试</p><ul><li><p style="text-align: start; "><strong>Windows Host解析文件:C:\Windows\System32\drivers\etc\hosts</strong></p></li></ul><pre><code class="language-shell"># 添加
10.0.0.8 www.myx.com
10.0.0.8 www.it.com</code></pre><p style="text-align: start; "><img loading="lazy" src="/upload/image-dgxd.png" width="944px" height="235.75px" style="display: inline-block"></p><p style="text-align: start; "></p><h5 style="text-align: start; " id="heading-22"><strong>3.7 nginx的虚拟主机(基于端口)</strong></h5><pre><code>         server {
          listen 80;
           server_name it.hopu.com;
           index index.html index.htm index.php;
           root  html/it;
          }
        server {
           listen 81;
           server_name it.hopu.com;
           index index.html index.htm index.php;
           root  html/bbs;
       }</code></pre><h5 style="text-align: start; " id="heading-23"><strong>3.8 nginx的虚拟主机(基于IP)</strong></h5><pre><code>1、添加IP
[root@lnmp conf]# ifconfig ens33:1 192.168.1.15/24  ##临时添加个子接口IP
[root@lnmp conf]# ip add
lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
   inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   link/ether 00:0c:29:d9:4b:17 brd ff:ff:ff:ff:ff:ff
   inet 192.168.1.10/24 brd 192.168.1.255 scope global noprefixroute ens33
      valid_lft forever preferred_lft forever
   inet 192.168.1.15/24 brd 192.168.1.255 scope global secondary ens33:1
      valid_lft forever preferred_lft forever
   inet6 fe80::f077:e3ce:7cf1:1ede/64 scope link noprefixroute
      valid_lft forever preferred_lft forever
[root@lnmp conf]#
​
2、配置nginx配置文件
​
        server {
          listen 80;
           server_name 192.168.1.10;
           index index.html index.htm index.php;
           root  html/it;
          }
        server {
           listen 80;
           server_name 192.168.1.15;
           index index.html index.htm index.php;
           root  html/bbs;
       }
       
3、重启nginx进行测试</code></pre><p style="text-align: start; ">如果是基于IP地址访问的虚拟主机,则需要看include的位置,如果在server段之前,则优先匹配include里配置的虚拟主机,匹配的原则是“首字母越靠前,则会被优先匹配”;如果在server段之后,则优先匹配主配置文件中的虚拟主机。</p><h5 style="text-align: start; " id="heading-24"><strong>3.9 nginx实现 https</strong></h5><p style="text-align: start; ">a、安装 nginx时,需要将<code>--with-http_ssl_module</code>模块开启</p><p style="text-align: start; ">b、在对应要进行加密的 server标签中添加以下内容开启 SSL</p><pre><code>[root@lnmp/usr/local/nginx/conf/conf.d]$ cat it.myx.com.conf 
server {
listen 80;
server_name it.myx.com;
index index.html index.htm index.php;
root  html/it;	
listen 443 ssl;
ssl_certificate /usr/local/nginx/conf/ssl/myx.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/myx.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers
"EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
}</code></pre><p style="text-align: start; ">c、生成证书和秘钥文件</p><pre><code>建立服务器私钥,生成 RSA密钥
[root@lnmp/usr/local/nginx/conf/ssl]$ openssl genrsa -out myx.key 1024
Generating RSA private key, 1024 bit long modulus
.++++++
................++++++
e is 65537 (0x10001)</code></pre><pre><code>需要依次输入国家,地区,组织,email。最重要的是有一个  common  name,可以写你的名字或者域
名。如果为了 https申请,这个必须和域名吻合,否则会引发浏览器警报。生成的  csr文件交给  CA签
名后形成服务端自己的证书
[root@lnmp/usr/local/nginx/conf/ssl]$ openssl req -new -key myx.key -out myx.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.">[root@lnmp/usr/local/nginx/html]$ curl it.myx.com
it
[root@lnmp/usr/local/nginx/html]$ curl bbs.myx.com
bbs

e、访问测试

  • Windows Host解析文件:C:\Windows\System32\drivers\etc\hosts

# 添加
10.0.0.8 www.myx.com
10.0.0.8 www.it.com

3.7 nginx的虚拟主机(基于端口)
         server {
          listen 80;
           server_name it.hopu.com;
           index index.html index.htm index.php;
           root  html/it;
          }
        server {
           listen 81;
           server_name it.hopu.com;
           index index.html index.htm index.php;
           root  html/bbs;
       }
3.8 nginx的虚拟主机(基于IP)
1、添加IP
[root@lnmp conf]# ifconfig ens33:1 192.168.1.15/24  ##临时添加个子接口IP
[root@lnmp conf]# ip add
lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
   inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   link/ether 00:0c:29:d9:4b:17 brd ff:ff:ff:ff:ff:ff
   inet 192.168.1.10/24 brd 192.168.1.255 scope global noprefixroute ens33
      valid_lft forever preferred_lft forever
   inet 192.168.1.15/24 brd 192.168.1.255 scope global secondary ens33:1
      valid_lft forever preferred_lft forever
   inet6 fe80::f077:e3ce:7cf1:1ede/64 scope link noprefixroute
      valid_lft forever preferred_lft forever
[root@lnmp conf]#
​
2、配置nginx配置文件
​
        server {
          listen 80;
           server_name 192.168.1.10;
           index index.html index.htm index.php;
           root  html/it;
          }
        server {
           listen 80;
           server_name 192.168.1.15;
           index index.html index.htm index.php;
           root  html/bbs;
       }
       
3、重启nginx进行测试

如果是基于IP地址访问的虚拟主机,则需要看include的位置,如果在server段之前,则优先匹配include里配置的虚拟主机,匹配的原则是“首字母越靠前,则会被优先匹配”;如果在server段之后,则优先匹配主配置文件中的虚拟主机。

3.9 nginx实现 https

a、安装 nginx时,需要将--with-http_ssl_module模块开启

b、在对应要进行加密的 server标签中添加以下内容开启 SSL

[root@lnmp/usr/local/nginx/conf/conf.d]$ cat it.myx.com.conf
server {
listen 80;
server_name it.myx.com;
index index.html index.htm index.php;
root  html/it;	
listen 443 ssl;
ssl_certificate /usr/local/nginx/conf/ssl/myx.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/myx.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers
"EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
}

c、生成证书和秘钥文件

建立服务器私钥,生成 RSA密钥
[root@lnmp/usr/local/nginx/conf/ssl]$ openssl genrsa -out myx.key 1024
Generating RSA private key, 1024 bit long modulus
.++++++
................++++++
e is 65537 (0x10001)
需要依次输入国家,地区,组织,email。最重要的是有一个  common  name,可以写你的名字或者域
名。如果为了 https申请,这个必须和域名吻合,否则会引发浏览器警报。生成的  csr文件交给  CA签
名后形成服务端自己的证书
[root@lnmp/usr/local/nginx/conf/ssl]$ openssl req -new -key myx.key -out myx.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.</h2>
<p>Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:MYX
Organizational Unit Name (eg, section) []:MYX
Common Name (eg, your name or your server's hostname) []:it.myx.com	# 这里的域名要和server段中的一致
Email Address []:myx@qq.com</p>
<p>Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# 生成签字证书
[root@lnmp/usr/local/nginx/conf/ssl]$ openssl x509 -req -days 365 -sha256 -in myx.csr -signkey myx.key -out myx.crt
Signature ok
subject=/C=CN/ST=HB/L=WH/O=MYX/OU=MYX/CN=it.myx.com/emailAddress=myx@qq.com
Getting Private key

d、将证书复制到/usr/local/nginx/conf/ssl目录下

[root@localhost ssl]# ls
hopu.crt  hopu.csr  hopu.key

e、设置 http自动跳转 https功能

原有的 server标签修改监听端口

[root@lnmp/usr/local/nginx/conf/conf.d]$ vim server {
listen 443 ssl;
ssl_certificate /usr/local/nginx/conf/ssl/myx.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/myx.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers
"EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
server_name it.myx.com;
index index.html index.htm index.php;
root  html/it;
}
[root@lnmp/usr/local/nginx/conf/conf.d]$ 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

f、重启nginx,访问测试

g、HSTS的实现

HSTS的全称是HTTP Strict-Transport-Security,它是一个Web安全策略机制(web security policy mechanism)。 HSTS最早于2015年被纳入到ThoughtWorks技术雷达,并且在2016年的最新一期技术雷达里,它直接从“评估(Trial)”阶段进入到了“采用(Adopt)“阶段,这意味着ThoughtWorks强烈主张业界积极采用这项安全防御措施,并ThoughtWorks已经将其应用于自己的项目。

HSTS最为核心的是一个HTTP响应头(HTTP Response Header)。正是它可以让浏览器得知,在接下来的一段时间内,当前域名只能通过HTTPS进行访问,并且在浏览器发现当前连接不安全的情况下,强制拒绝用户的后续访问要求。

在http段中加入下面的内容:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

重启Nginx服务,并使用https的方式访问网站:

3.10 nginx重写功能
3.10.1 rewrite

官方网站:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

http状态码:https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

rewire规则也称为规则重写,主要功能是实现浏览器访问 Http Url的跳转,其正则达式是基于Perl语言。通常而言,几乎所有的Web服务器均可以支持URL重写,URL规则重写的用途如下:

1、对搜索引擎优化( search engine optimization,SEO)友好,利于搜索引擎抓取网站页面
2、隐藏网站URL真实地址,浏览器显示更加美观;
3、网站变更升级,可以基于 rewrite临时重定向到其他页面。

Nginx rewrite规则使用中有3个概念,分别是 rewrite结尾标识符、 rewrite规则常用表达式 ,Nginx rewrite变量,3个概念的详解如下:

(1) Nginx rewrite结尾标识符,用于 rewrite规则末尾,表示规则的执行属性详解
   last:表示匹配本条规则后,继续向后匹配,浏览器地址栏URL地址不变。
   break:本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变。
   redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
   permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。
其中last和 break用来实现URL重写时,浏览器地址栏URL地址不变。
​
2) Nginx rewrite规则常用表达式,主要用于匹配参数、字符串及过滤设置,详解如下:
  .:匹配任何单字符
  [word:匹配字符串word
  [^word:不匹配字符串word
  ?:匹配0个或者1个
  <em>:匹配0个或者多个
  +:匹配1个或者多个
  ^:字符串开头
  $:字符串结尾
​
(3)Nginx rewrite变量,常用于匹配HTTP请求头信息、浏览器主机名、URL等,具体转义符标志内容如下
​
HTTP_USER_AGENT:用户使用的代理,例如浏览器。
Http_Referer:告知服务器,从哪个页面来访问的。
Http_Cookie:客户端缓存,主要用于存储用户名和密码等信息。
Http_Host:匹配服务器 servername域名。
Http_Accept:客户端的浏览器支持的MIME类型。
REMOTE_ADDR:客户端的IP地址。
QUERY_STRING:URL中访问的字符串。
DOCUMENT_ROOT:服务器发布目录。
SERVER_PORT:服务器端口
SERVER_PROTOCOL:服务器端协议。
TIME_YEAR:年。
TIME_MON:月。
TIME_DAY:日。

注意:rewrite 只能在server {},location {},if {}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用 例如:http://www.hopu.com/bbs/index.html?a=1&b=2只针对/abc/bbs/index.html重写

3.10.2 企业实战案例

案例1:公司网站升级了,原来使用的是test.myx.com网站,随着业务不断的发展,需要切换到新的域名上来

[root@lnmp/usr/local/nginx/conf/conf.d]$ vim test.myx.com.conf
server{
listen 80;
server_name test.myx.com;
rewrite ^(.</em>)$ https://it.myx.com/$1 permanent;
root html;
index index.html index.htm;
}

案例2:公司业务新版本上线,要求所有 IP 访问任何内容都显示是一个固定维护的页面,只有公司 IP 192.168.1.1 访问正常

   server {
       listen       80;
       server_name  www.bestit.com;
​
       #charset koi8-r;
​
       #access_log  logs/host.access.log  main;
      ##设置是否是合法的IP标记
       set $rewrite true;
     ##设置变量$rewrite,变量值为boole值true
     
      #判断是否为合法IP
       if ($remote_addr = "192.168.1.1"){
        set $rewrite false;
      #当客户端IP为192.168.1.1时,将变量值设为flase,不进行重写
          }
      #除了合法IP,其它都是非法IP,进行重写跳转到维护页面
       if ($rewrite = true) {
       #当变量值为true时,进行重写
          rewrite (.+) /weihu.html;
          }
        #重写在访问IP后边插入/weihu.html,例如192.168.1.120/weihu.html
      location = /weihu.html {
       #页面返回/usr/local/nginx/html/weihu.html的内容
        root /usr/local/nginx/html;
          }
       location / {
           root   html;
           index  index.html index.htm;
       }
}

案例3:当访问www.bestit.com/upload/index.php的时候跳转到首页文件

    server {
       listen       80;
       server_name  www.bestit.com;
​
       #charset koi8-r;
​
       #access_log  logs/host.access.log  main;
        location ~* /upload/.<em>.php$ {
               rewrite (.+) http://www.bestit.com permanent;
                }
       location / {
           root   html;
           index  index.html index.htm;
       }
}

案例4:为了加强安全,公司新申请了SSL证书,需要绑定到公司的域名www.hopu.com上来,实现当用户访问http://www.hopu.com自动跳转到https://www.hopu.com站点上来

  #HTTP段配置  
server {
       listen       80;
       server_name  www.hopu.com;
​
       #charset koi8-r;
​
       #access_log  logs/host.access.log  main;
       ##判断请求的架构如果是http,就开启重定向
       if ( $scheme = http ) {  
      rewrite  / https://www.hopu.com/$1 permanent;
        }
       location / {
           root   html;
           index  index.html index.htm;
       }
}
   #HTTPS段配置
       server {
       listen       443 ssl;
       server_name  www.hopu.com;
      ssl_certificate /usr/local/nginx/ssl/hopu.crt;
      ssl_certificate_key /usr/local/nginx/ssl/hopu.key;
      ssl_session_timeout 5m;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_prefer_server_ciphers on;
      ssl_ciphers "EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
}

案例5:伪静态配置

伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页面,但是有的朋友为了实时的显示一些信息。或者还想运用动态脚本解决一些问题。不能用静态的方式来展示网站内容。但是这就损失了对搜索引擎的友好面。怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。伪静态技术是指展示出来的是以html一类的静态页面形式,但其实是用ASP一类的动态脚本来处理的。

flag:last

     server {
        listen 80;
        server_name 192.168.1.10;
        root html;
        index index.html index.php;
    location / {
        rewrite /index.html /index.php last;     #last
            }
     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.conf;
       }
     }

flag: break

     server {
        listen 80;
        server_name 192.168.1.10;
        root html;
        index index.html index.php;
    location / {
        rewrite /index.html /index.php break;    #break
          }
     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.conf;
       }
     }

注意:last在匹配的时候并未结束,而是一直向后匹配,所以会通过php-fpm解析到了页面,但是break会停止解析,导致php的页面无法识别,而出现了下载的页面。

3.10.3 return

案例1:禁止访问以.sh,flv,.mp3等文件后缀名的文件

​
   location ~ .</em>.(sh|flv|mp3)$
   {
   return 403;
   }

案例2:以 /index/ 开头的请求,如果链接的状态为 404。则会匹配到 @index_error 这条规则上

location /index/ {
      error_page 404 = @index_error;
      }
   location @index_error {
          default_type text/html;
          return 503;
        }

案例3:将http://www.hopu.com跳转到https://www.bestit.com

  #HTTP段配置  
server {
       listen       80;
       server_name  www.hopu.com;
​
       #charset koi8-r;
​
       #access_log  logs/host.access.log  main;
       
     return 301 https://www.hopu.com$request_uri;
​
       location / {
           root   html;
           index  index.html index.htm;
       }
}
   #HTTPS段配置
       server {
       listen       443 ssl;
       server_name  www.hopu.com;
      ssl_certificate /usr/local/nginx/ssl/hopu.crt;
      ssl_certificate_key /usr/local/nginx/ssl/hopu.key;
      ssl_session_timeout 5m;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_prefer_server_ciphers on;
      ssl_ciphers "EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
}

3.11 目录列表显示

官方网站:https://nginx.org/en/docs/http/ngx_http_autoindex_module.html

#可以配置在http,server,location段,推荐配置在location段
  location /download {
   autoindex on;
   index index;
   limit_rate 1024K;
   autoindex_localtime on;
   autoindex_exact_size on;
   alias /data/download;
}
#注意:只有当目录列表中找不到文件时才会使用目录列表,如果index中没有文件,而又没有开启autoindex,则会报403

帮助我们将网站文件列表显示

3.12 字符集设置

官方网站:https://nginx.org/en/docs/http/ngx_http_charset_module.html

默认nginx的字符集无法显示中文,因此会出现乱码,所以可以设置正确的字符集来显示中文

#可以配置在http,server,location段,推荐配置在http段
charset utf-8;
[root@localhost conf]# curl -I  192.168.1.10/index.php
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Mon, 13 Nov 2023 12:29:32 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 22
Last-Modified: Mon, 13 Nov 2023 12:20:25 GMT
Connection: keep-alive
ETag: "65521489-16"
Accept-Ranges: bytes
3.13 URI匹配之location
3.13.1 location的匹配规则

官方文档:https://nginx.org/en/docs/http/ngx_http_core_module.html#location

普通的匹配规则

规则表达式

规则含义

=

进行普通字符精确匹配。也就是完全匹配

^~

表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他 location

~

表示执行一个正则匹配,区分大小写

~

表示执行一个正则匹配,不区分大小写

!~

表示执行一个正则匹配,不匹配区分大小写

!~

表示执行一个正则匹配,不匹配不区分大小写

正则表达式规则

字符

含义

.

匹配任意单个字符,可以是一个汉字

^

行首锚定,用于模式的最左侧

$

行尾锚定,用于模式的最右侧

?

0 或 1 次

+

1 次或多次 (1 次或以上)

</p>

转义符

\d

只匹配数字

{n}

重复 n 次

{n,}

至少 n 次 (n 次以上)

{n,m}

n 到 m 次

[ ]

定义匹配字符的范围,只匹配一次

[c]

单个字符

[a-z]

匹配任意小写字母

[a-zA-Z0-9]

匹配任意字母和数字

()

表达式的开始和结束位置

|

或运算符 a|b

location 语法规则

(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
​
^~类型表达式。一旦匹配成功,则不再查找其他匹配项。
​
正则表达式类型(~和~<em>)的优先级次之。
​
常规字符串匹配类型(不带任何修饰符的匹配),按前缀匹配。/test
​
通用匹配(/),如果没有其它匹配,任何请求都会匹配到。
3.13.2 location 配置案例

官方范例:

location = / {
   [ configuration A ]
}
​
location / {
   [ configuration B ]
}
​
location /documents/ {
   [ configuration C ]
}
​
location ^~ /images/ {
   [ configuration D ]
}
​
location ~</em> .(gif|jpg|jpeg)$ {
   [ configuration E ]
}
​
he “/” request will match configuration A, the “/index.html” request will match configuration B(???????), the “/documents/document.html” request will match configuration C, the “/images/1.gif” request will match configuration D, and the “/documents/1.jpg” request will match configuration E
  1. =,精确匹配

server {
   listen 80;
  server_name www.bestit.com;
location / {
   root  /data/www;
   index index.html index.htm;
}
location  =/logo.png {
    root /data/nginx/images;
    index index.html index.htm;
  }
}
​
#上传logo.png图片到/data/nginx/images,重启Nginx并访问测试
#访问测试: http://www.bestit.com/logo.png
  1. ~,大小写敏感

  location ~ /H.?.png {
   index index.html index.htm;
   root /data/nginx/html/images;
}
​
#上传上传HP.png图片到/data/nginx/html/images,重启Nginx并访问测试
#访问测试: http://www.bestit.com/Hp.png
#无法访问http://www.bestit.com/hp.png
  1. ~,大小写忽略

  location ~</em> /H.?.png {
   index index.html index.htm;
   root /data/nginx/html/images;
}
#上传上传HP.png图片到/data/nginx/html/images,重启Nginx并访问测试
#访问测试: http://www.bestit.com/Hp.png [成功]
#无法访问http://www.bestit.com/hp.png [失败,网站根目录下没有hp.png图片]

4)^~,只匹配以 uri 开头

 location ^~ /images/ {
  root /data/nginx;
  index index.html;
}
#以 /images/ 开头的请求,都会匹配上</p>
<h1 id="上传图片到/data/nginx/images/下,重启服务">上传图片到/data/nginx/images/下,重启服务</h1><h1 id="访问http://www.bestit.com/images/hp.png测试">访问http://www.bestit.com/images/hp.png测试</h1>
<p>​
​
将内容修改成如下,访问hp.png,谁会被匹配到?
location ~* /.<em>.png {
   index index.html index.htm;
   root /data/nginx/html/images;
}
location ^~ /images/ {
  root /data/nginx;
  index index.html;
}
  1. /,其他匹配不成功,匹配此项

location / {
   root  /data/www;
   index index.html index.htm;
}
​
#如果上述内容匹配不到,则进行改匹配

如果匹配路径资源存在,则优先获取。

location匹配说明:

 1. 精确匹配:location = /  {.....}
2. 一般匹配:location  /  {.....}
3. 正则匹配:location ~ / {.....}
3.13.3 优先级匹配实例
location = /hp.png {
  root /data/nginx/static1;
  index index.html;
}
location /hp.png {
  root /data/nginx/static2;
  index index.html;
}
​
location ~</em> .(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
   root /data/nginx/static3;
   index index.html;
}
}
​</p>
<h1 id="将hp.png图片上传到/data/nginx/static{1..3}后,重启nginx测试">将hp.png图片上传到/data/nginx/static{1..3}后,重启nginx测试</h1>
<p>[root@localhost /]# mkdir /data/nginx/static{1..3}
3.13.4 location匹配最佳实践
# 将静态资源文件进行请求路由
location ~ .*.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
   root /data/webapps/www1;
   expires 30d;
}</p>
<h1 id="将请求服务器接口的服务配置路由并反向代理">将请求服务器接口的服务配置路由并反向代理</h1>
<p>​
location ~ .(php|jsp)$ {
   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_pass http://jvm_web1;  // 反向代理的请求地址
}
3.14 自定义错误页面

自定义错误页面,自定义响应码进行响应

编辑 nginx.conf ,在你的 http 模块下的 server 模块中添加如下的 error_page 和 location
​
http {
  # ...
​
  server {
     # ...
​
     error_page 404 /error.html; # 将404错误页指向自定义的错误页面
​
     #error_page 400 403 404 /error.html; # 你还可以这样写,让多个状态码指向同一个页面
​
     # ...
​
     location = /error.html {
         root /path/to/your/html/files; # 指定你自定义错误页面所在的路径,即 error.html 所在的路径
       
     }
    
  }
}
3.14.1 错误页面配置范例
server {
  listen 80;
  server_name www.bestit.com;
  error_page 404 /error.html;
location = /error.html {
   root /data/nginx/error;
    }
}
3.14.2 防止浏览器“劫持”页面

部分浏览器在访问到一些错误页面的时候,会进行页面内容的劫持,为了避免这个问题,可以做如下设置:

server {
   listen 80;
  server_name www.bestit.com;
  error_page 404 =302 /error.html;
  location = /error.html {
   root /data/nginx/error;
    }
}
​
#将访问错误的页面跳转到302重定向。


四、 Nginx日志管理

官方网站:https://nginx.org/en/docs/http/ngx_http_log_module.html

默认位置在nginx安装目录下的:logs/access.log,也可修改日志配置,在配置文件中:conf/nginx.conf

日志类型:
1)访问日志   access.log
2)错误日志   error.log
4.1 访问日志
4.1.1 查看访问日志

默认nginx的日志格式如下:

[root@lnmp logs]# cat access.log |head -n 1
192.168.1.1 - - [10/Oct/2022:14:00:18 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
[root@lnmp logs]#
4.1.2 访问日志的格式说明
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
   #                  '$status $body_bytes_sent "$http_referer" '
   #                  '"$http_user_agent" "$http_x_forwarded_for"';

4.2 错误日志

官方网站:https://nginx.org/en/docs/ngx_core_module.html#error_log

主要记录一些启动和运行中的错误信息

开启错误日志   日志的位置      日志级别
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
4.2.1 查看错误日志
[root@lnmp logs]# cat error.log |tail -n 1
2022/9/29 21:09:44 [error] 2207#0: <em>1 directory index of "/usr/local/nginx/html/" is forbidden, client: 192.168.1.1, server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.10"
4.3 自定义日志格式

自定义的格式必须要写在http段中

log_format   mylogs  '$remote_addr - $remote_user [$time_local] "$request" '
                     "$http_referer" "$http_user_agent" ;

引用日志格式,需要在server段中引用

  access_log logs/local.access.log mylogs;
[root@lnmp logs]# cat local.access.log
192.168.1.1 - - [19/Oct/2022:21:40:01 +0800] "GET / HTTP/1.1" -Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
4.4 日志切割参考脚本
#!/bin/bash
date=$(date +%F -d -1day)
cd /usr/local/nginx/logs
if [ ! -d cut ] ; then
 mkdir cut
fi
 mv access.log cut/access_$(date +%F -d -1day).log
 mv error.log cut/error_$(date +%F -d -1day).log
/usr/local/nginx/sbin/nginx -s reload
tar -jcvf cut/$date.tar.bz2 cut/</em>
rm -rf cut/access* && rm -rf cut/error*
 cat >>/var/spool/cron/root<<eof
 00 00 * * * /bin/sh /usr/local/nginx/logs/cut_nginx_log.sh >/dev/null 2>&1
eof
find -type f -mtime +10 | xargs rm -rf

五、Nginx使用扩展

5.1 安装第三方模块

第三方模块是指nginx官方没有的功能,开源社区的开发者定制开发的一些功能,可以通过编译加载第三方的模块的方式使用新的功能

5.1.1 安装第三方模块方法
./configure --prefix=/你的安装目录  --add-module=/第三方模块目录
5.1.2 在nginx安装目录中创建文件夹third_moule。

下载模块到nginx安装目录中的third_module。

https://codeload.github.com/aperezdc/ngx-fancyindex/zip/master

https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz

[root@lnmp nginx-1.20.2]# mkdir third_module
5.1.3 解压模块
[root@lnmp third_module]# tar zxvf v0.61.tar.gz
[root@lnmp third_module]# unzip ngx-fancyindex-master.zip
5.1.4 安装第三方模块

进入到Nginx的安装目录下进行编译安装

[root@lnmp nginx-1.20.2]# ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre=/usr/local/src/pcre-8.41 --user=nginx --group=nginx --add-module=/usr/local/src/nginx-1.20.2/third_module/echo-nginx-module-0.61 --add-module=/usr/local/src/nginx-1.20.2/third_module/ngx-fancyindex-master
[root@lnmp nginx-1.20.2]# make -j 8 && make -j 8  install && make -j 8 upgrade
5.1.5 查看新的模块

可以进入到nginx的二进制安装路径下加-V查看

[root@lnmp sbin]# ./nginx -V
nginx version: bf/1.2.3
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 --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre=/usr/local/src/pcre-8.41 --user=nginx --group=nginx --add-module=/usr/local/src/nginx-1.20.2/third_module/echo-nginx-module-0.61 --add-module=/usr/local/src/nginx-1.20.2/third_module/ngx-fancyindex-master
​
5.2 使用第三方模块
5.2.1 使用ngx-fancyindex模块实现目录列表优化显示
    server {
       listen       80;
       server_name  192.168.1.10;
       #加入如下几句:
       fancyindex on;
       fancyindex_localtime on; #on for local time zone. off for GMT
       fancyindex_exact_size off; #off for human-readable. on for exact size in bytes
       fancyindex_ignore "fancyindex"; #ignore this directory when showing list
       fancyindex_default_sort date_desc; #以上传时间倒序排列
       charset utf8;
       root html;
       index abc;
       #access_log  logs/host.access.log  main;
​
       error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }
       }
​

5.2.2 使用echo模块

可以使用echo打印nginx的系统环境变量

https://nginx.org/en/docs/http/ngx_http_core_module.html#var_document_root

location {
#以文本的形式显示
default_type text/plain;
#打印根路径
echo $document_root;
}
location {
default_type text/html;
#输出html内容,需要使用text/html类型
echo <h1>hello hopu</h1>;
}
location {
default_type text/html;
#输出html内容,需要使用text/html类型
echo $date_local;
echo $hostname;
}

更多系统变量,请参考:https://nginx.org/en/docs/varindex.html

5.3 OpenResty

官方网站:http://openresty.org/cn/

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关,作者章亦春

5.3.1 安装openresty

安装方式有多种多样,适用于不同的操作系统平台,针对centos平台提供

1)yum 安装
2)源码编译安装
CentOS
你可以在你的 CentOS 系统中添加 openresty 仓库,这样就可以便于未来安装或更新我们的软件包(通过 yum check-update 命令)。 运行下面的命令就可以添加我们的仓库(对于 CentOS 8 或以上版本,应将下面的 yum 都替换成 dnf):
​</p>
<h1 id="add the yum repo:">add the yum repo:</h1>
<p>wget https://openresty.org/package/centos/openresty.repo
sudo mv openresty.repo /etc/yum.repos.d/
​</p>
<h1 id="update the yum index:">update the yum index:</h1>
<p>sudo yum check-update
然后就可以像下面这样安装软件包,比如 openresty:
​
sudo yum install -y openresty
如果你想安装命令行工具 resty,那么可以像下面这样安装 openresty-resty 包:
​
sudo yum install -y openresty-resty
命令行工具 opm 在 openresty-opm 包里,而 restydoc 工具在 openresty-doc 包里头。
​
列出所有 openresty 仓库里头的软件包:
​
sudo yum --disablerepo="*" --enablerepo="openresty" list available

我们采取源码编译安装的方式安装:

下载地址:https://openresty.org/download/openresty-1.19.9.1.tar.gz

[root@lnmp ~]# tar -zxvf openresty-1.19.9.1.tar.gz -C /usr/local/src/
[root@lnmp openresty-1.19.9.1]# ./configure --prefix=/usr/local/openresty
[root@lnmp openresty-1.19.9.1]# ll /usr/bin/gmake
lrwxrwxrwx. 1 root root 4 Oct 29 13:16 /usr/bin/gmake -> make
[root@lnmp openresty-1.19.9.1]# make -j 8 && make -j 8 install
5.3.2 查看openresty的编译参数
[root@lnmp bin]# ./openresty -v
nginx version: openresty/1.19.9.1
[root@lnmp bin]# ./openresty -V
nginx version: openresty/1.19.9.1
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/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.1 --add-module=../echo-nginx-module-0.62 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.32 --add-module=../ngx_lua-0.10.20 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.15 --add-module=../rds-csv-nginx-module-0.09 --add-module=../ngx_stream_lua-0.0.10 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_ssl_module
5.3.3 启动openresty
[root@lnmp bin]# /usr/local/openresty/bin/openresty

5.3.4 openresty的语法示例
        location / {
           default_type text/html;
           content_by_lua 'ngx.say("<p>Hello, World!</p>")';
       }

六、Nginx参数调优

6.1 隐藏nginx的版本

Nginx 编译前的优化 ,可以用于修改nginx的版本

[root@lnmp core]# pwd
/usr/local/src/nginx-1.20.2/src/core
​
[root@lnmp core]# vim src/core/nginx.h //目的更改源码隐藏软件名称和版本号
改:
13 #define NGINX_VERSION "1.12.2" #此行修改的是你想要的版本号
14 #define NGINX_VER "nginx/" NGINX_VERSION #此行修改的是你想修改的软件
名称
为:
13 #define NGINX_VERSION "8.8.2"
14 #define NGINX_VER "XWS/" NGINX_VERSION
[root@lnmp core]# vim src/http/ngx_http_header_filter_module.c
改:49 static u_char ngx_http_server_string[] = "Server: nginx" CRLF; //修改 HTTP 头信
息中的 connection 字段,防止回显具体版本号
为:49 static u_char ngx_http_server_string[] = "Server: XWS" CRLF;

完成后重新编译安装即可。

6.2 Nginx运行工作进程数量

Nginx运行工作进程个数一般设置CPU的核心或者核心数x2。如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor /proc/cpuinfo | wc -l

[root@localhost ~]# grep ^worker</usr/local/nginx/conf/nginx.conf
worker_processes  4;
[root@localhost ~]# nginx -s reload
[root@localhost ~]# ps -ef |grep nginx
root       1666      1  0 19:29 ?        00:00:00 nginx: master process nginx
nobody     1681   1666  0 19:30 ?        00:00:00 nginx: worker process
nobody     1682   1666  0 19:30 ?        00:00:00 nginx: worker process
nobody     1683   1666  0 19:30 ?        00:00:00 nginx: worker process
nobody     1684   1666  0 19:30 ?        00:00:00 nginx: worker process
root       1686   1633  0 19:30 pts/0    00:00:00 grep --color=auto nginx
[root@localhost ~]# 
6.3 Nginx运行CPU亲和力
CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将制定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提高。

比如4核配置:

worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000

比如8核配置:

worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 0000100000010000 00100000 01000000 10000000;

worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。

那么如果我是 4 线程的 CPU,我只想跑让vim命令运行在1号CPU上呢

语法: taskset -c  N 命令
[root@lnmp conf]# taskset -c 0 vim a.txt   #1 号 CPU ID 是 0
[root@lnmp conf]# ps -ef |grep vim
root       2549   1177  0 23:06 pts/0    00:00:00 vim a.txt
root       2571   2553  0 23:07 pts/1    00:00:00 grep --color=auto vim
[root@lnmp conf]# taskset -p 2549
pid 2549's current affinity mask: 1 

如果想查看ssh服务运行在哪个CPU核心上,可以如下查看方式:

[root@lnmp conf]# ps -ef |grep sshd
root        975      1  0 19:41 ?        00:00:00 /usr/sbin/sshd -D
root       1097    975  0 19:41 ?        00:00:03 sshd: root@pts/0
root       2232    975  0 21:35 ?        00:00:00 sshd: root@notty
root       2241    975  0 21:35 ?        00:00:00 sshd: root@notty
root       2551    975  0 23:06 ?        00:00:00 sshd: root@pts/1
root       2583   2553  0 23:09 pts/1    00:00:00 grep --color=auto sshd
[root@lnmp conf]# taskset -p 975
pid 975's current affinity mask: ff           #ff代表是8个核心,1个f代表是4个核心

例:指定 vim b.txt 程序运行在第 2 和第 4 个 CPU 上

[root@lnmp conf] taskset -c 1,3 vim b.txt
[root@lnmp conf] ps -axu | grep vim
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
root 6314 1.5 0.2 143612 3280 pts/1 S+ 14:41 0:00 vim b.txt
root 6317 0.0 0.0 103300 848 pts/2 S+ 14:41 0:00 grep vim
[root@lnmp conf] taskset -p 6314
pid 6314's current affinity mask: a</p>
<h1 id="a 为十进制的 10=2+8">a 为十进制的 10=2+8</h1>
<p>注:在哪个 CPU 上运行,那一位就赋为 1 
关于换算方式:</p>
<p>8个核心的CPU ID:   7 6 5 4 3 2 1 0
对应10的十进制数位: 128 64 32 16 8 4 2 1
十六进制的16个数是:0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F</p>
<p>对应每一个16进制的二进制位:0=0000,1=0001,2=0010,3=0011,4=0100,5=0101,6=0110,7=0111,8=1000,9=1001,A=1010,
B=1011,C=1100,D=1101,E=1110,F=1111</p>
<p>那么例如出现pid 8987's current affinity mask: ff   ff是16进制,转换二进制:11111111,意思就是sshd在8个CPU上进行却换!所以对应每一个数值!
比如说16进制的40,那么转换二进制01000000,意思就是在第7块CPU上运作

6.4 Nginx最大打开文件数
worker_rlimit_nofile 65535;

这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。

注:文件资源限制的配置可以在/etc/security/limits.conf设置,针对root/user等各个用户或者代表所有用户来设置。

</em>   soft nofile   65535</p>
<ul>
<li>  hard nofile   65535

用户重新登录生效(ulimit -n)

6.5 进程优先级

官方文档:https://nginx.org/en/docs/ngx_core_module.html#worker_priority

worker_priority 20;
[root@lnp conf]# watch -n2 'ps axo pid,cmd,psr,ni|grep nginx'
6.6 Nginx事件处理模型
events {
use epoll;
worker_connections 65535;
multi_accept on;
}

nginx采用epoll事件模型,处理效率高。

work_connections是单个worker进程允许客户端最大连接数,这个数值一般根据服务器性能和内存来制定,实际最大值就是worker进程数乘以work_connections。

实际我们填入一个65535,足够了,这些都算并发值,一个网站的并发达到这么大的数量,也算一个大站了!

multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接,默认是on,设置为on后,多个worker按串行方式来处理连接,也就是一个连接只有一个worker被唤醒,其他的处于休眠状态,设置为off后,多个worker按并行方式来处理连接,也就是一个连接会唤醒所有的worker,直到连接分配完毕,没有取得连接的继续休眠。当你的服务器连接数不多时,开启这个参数会让负载有一定的降低,但是当服务器的吞吐量很大时,为了效率,可以关闭这个参数。

扩展: select,poll,epoll 都是 IO 多路复用的机制。I/O 多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。epoll 在 Linux2.6 内核中正式引入,和 select 相似其实都 I/O 多路复用技术。

epoll 优势:
1、epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048, 一般来说这个数目和系统内存关系很大,具体数目可以 cat /proc/sys/fs/file-max查看。
[root@lnmp http]# cat /proc/sys/fs/file-max
179482
​
2、 效率提升,epoll 最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,epoll 的效率就会远远高于 select 和 poll。
3、 内存拷贝,epoll 在这点上使用了“共享内存”,这个内存拷贝也省略了  

6.7 开启高效传输模式
 Include mime.types;                                          媒体类型
default_type application/octet-stream;                       默认媒体类型 足够
sendfile on;                                                 开启高效文件传输模式,sendfile 指令指定 nginx 是否调用,  sendfile 函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成 off。
tcp_nopush on;                                                必须在 sendfile 开启模式才有效,防止网络阻塞,积极的减少网络报文段的数量

6.8 连接超时时间

主要目的是保护服务器资源,CPU,内存,控制连接数,因为建立连接也是需要消耗资源的,TCP 的三次握手四次挥手等,我们一般断掉的是那些建立连接但是不做事儿,也就是我建立了链接开始,但是后续的握手过程没有进行,那么我们的链接处于等待状态的,全部断掉!同时我们也希望 php 建议短链接,消耗资源少

keepalive_timeout 60 65;
client_header_timeout 15;
client_body_timeout 15;
send_timeout 15;
keepalived_timeout 客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接
client_header_timeout 客户端请求头读取超时时间,如果超过设个时间没有发送任何数据,nginx将返回 request time out 的错误
client_body_timeout 客户端请求主体超时时间,超过这个时间没有发送任何数据,和上面一样的错误提示
send_timeout 响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx 关闭连接
6.9 文件上传大小限制

我们知道 PHP 可以修改上传文件大小限制,nginx 也可以修改,默认大小是1M,超过此大小会报413的错误,阿里云的虚拟主机的文件上传功能就是使用此功能实现。

http {
client_max_body_size 10m;  
}
6.10 Fastcgi 调优

Nginx 没有配置 factcgi,你使用 nginx 是一个失败的方法,配置之前。了解几个概念:

Cache:写入缓存区
Buffer:读取缓存区
Fastcgi 是静态服务和动态服务的一个接口  
fastcgi_connect_timeout 300;    #指定链接到后端 FastCGI 的超时时间。
​
fastcgi_send_timeout 300;     #向 FastCGI 传送请求的超时时间,这个值是指已经完成两次握手后向 FastCGI 传送请求的超时时间。
​
fastcgi_read_timeout 300; #指定接收 FastCGI 应答的超时时间,这个值是指已经完成两次握手后接收 FastCGI 应答的超时时间。
​
fastcgi_buffer_size 64k;   #指定读取 FastCGI 应答第一部分需要用多大的缓冲区,这个值表示将使用 1 个 64KB 的缓冲区读取应答的第一部分(应答头),可以设置为 fastcgi_buffers 选项指定的缓冲区大小。
​
fastcgi_buffers 4 64k;    #指定本地需要用多少和多大的缓冲区来缓冲 FastCGI 的应答请求,如果一个 php 脚本所产生的页面大小为 256KB,那么会分配 4 个 64KB 的缓冲区来缓存,如果页面大小大于256KB,那么大于 256KB 的部分会缓存到 fastcgi_temp 指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于磁盘。一般这个值应该为站点中 php 脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为 256KB,那么可以把这个值设置为“8 16K”、“4 64k”等。
​
fastcgi_busy_buffers_size 128k; #建议设置为 fastcgi_buffer 的两倍,繁忙时候的
​
bufferfastcgi_temp_file_write_size 128k; #在写入 fastcgi_temp_path 时将用多大的数据库,默认值
是 fastcgi_buffers 的两倍,设置上述数值设置小时若负载上来时可能报 502Bad Gateway
​
fastcgi_cache gnix; #表示开启 FastCGI 缓存并为其指定一个名称。开启缓存非常有用,可以有效降低 CPU 的负载,并且防止 502 的错误发生,但是开启缓存也可能会引起其他问题,要很据具体情况选择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; #请求的数量
fastcgi_cache_path #定义缓存的路径

修改 nginx.conf 配置文件,在 http 标签中添加如下:

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#fastcgi_temp_path /data/ngx_fcgi_tmp;
fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 #缓存路径,levels 目录层次 2 级
keys_zone=ngx_fcgi_cache:512m #定义了一个存储区域名字,缓存大小
inactive=1d max_size=40g; #不活动的数据在缓存中多长时间,目录总大小

在 server location 标签添加如下:

location ~ .<em>.(php|php7)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_cache ngx_fcgi_cache;
fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_cache_key http://$host$request_uri;
}
[root@lnmp http]# mkdir /data/ngx_fcgi_cache -pv
6.11 IP 和 301 优化

有时候,我们发现访问网站的时候,使用 IP 也是可以得,我们可以把这一层给屏蔽掉,让其直接反馈给403,也可以做跳转

1)跳转的做法  
​
server {
listen 80 default_server;
server_name _;
rewrite ^ http://www.baidu.com$request_uri?;
}
2)403 反馈的做法
server {
listen 80 default_server;
server_name _;
return 403;
}
3)301 跳转的做法,如我们域名一般在解析的过程中,a.com 一般会跳转到 www.a.com
server {
listen 80;
  root /usr/share/nginx/html/;
  server_name www.a.com a.com;
  if ($host = 'a.com' ) {
  rewrite ^/(.</em>)$ http://www.a.com/$1 permanent;
}
}
6.12 gzip 调优

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

使用gzip压缩功能,可能为我们节约带宽,加快传输速度,有更好的体验,也为我们节约成本,所以说这是一个重点。

Nginx启用压缩功能需要你来ngx_http_gzip_module模块,apache使用的是mod_deflate。

一般我们需要压缩的内容有:文本,js,html,css,对于图片,视频,flash什么的不压缩,同时也要注意,我们使用gzip的功能是需要消耗CPU的!

gzip on;
gzip_min_length 2k;
gzip_buffers   4 32k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css image/jpeg image/png image/jpg;
gzip_vary on;
gzip_proxied any;
字段的含义:
​</li>
</ul>
<ul>
<li>gzip_min_length 1k :设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大。
​</li>
<li>gzip_buffers 4 32k :压缩缓冲区大小,表示申请4个单位为32K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。
​</li>
<li>gzip_http_version 1.1 :压缩版本,用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可。
​</li>
<li>gzip_comp_level 6 :压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源。
​</li>
<li>gzip_types text/css text/xml application/javascript :用来指定压缩的类型,‘text/html’类型总是会被压缩。默认值: gzip_types text/html (默认不对js/css文件进行压缩)
​</li>
<li>
<ul>
<li>压缩类型,匹配MIME型进行压缩;</li>
<li>不能用通配符 text/*;</li>
<li>text/html默认已经压缩 (无论是否指定);</li>
<li>设置哪压缩种文本文件可参考 conf/mime.types。
​</li>
</ul>
</li>
<li>gzip_vary on :varyheader支持,改选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过nginx压缩的数据。

6.13 expires 缓存

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

#配置在server段
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;
}
​
同时也可以对目录及其进行判断
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
expires 360d;
}
location ~(robots.txt) {
expires 7d;
break;
}
​
​
或者
#配置在http段
expires 1h;

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

总结:

expire功能优点:
​</li>
<li>expires可以降低网站购买的带宽,节约成本;</li>
<li>同时提升用户访问体验;</li>
<li>减轻服务的压力,节约服务器成本,是web服务非常重要的功能。
​
expire功能缺点:
​</li>
<li>被缓存的页面或数据更新了,用户看到的可能还是旧的内容,反而影响用户体验。
​
解决办法:第一个缩短缓存时间,例如:1天,但不彻底,除非更新频率大于1天;第二个对缓存的对象改名。
​
网站不希望被缓存的内容:
​</li>
<li>网站流量统计工具;</li>
<li>更新频繁的文件(google的logo)。
6.14 防盗链

防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量,那么我们的解决办法由几种:

1. 水印,品牌宣传,你的带宽,服务器足够;</li>
</ul>
<ol start="2">
<li>防火墙,直接控制,前提是你知道IP来源;</li>
<li>防盗链策略下面的方法是直接给予403的错误提示。
location ~* .(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.hopu.com hopu.com ;
 if ($invalid_referer) {
   return 403;
     }
     }

参数可以使如下形式:

  • none :意思是不存在的Referer头(表示空的,也就是直接访问,比如直接在浏览器打开一个图片)。

  • blocked :意为根据防火墙伪装Referer头,如:“Referer:XXXXXXX”。

  • server_names :为一个或多个服务器的列表

测试:找另外一个服务器,安装nginx,新建如下的index.html的页面,代码如下

< html>
<h1>TEST Nginx PNG </h1>
<img src="http://www.hopu.com/a.png">
</html>
​

这是没有做限制之前的访问界面

这是限制之后的页面,反馈的是403

6.15 防止 DDOS 攻击

官方网站:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

通过使用 limit_conn_zone 进行控制单个 IP 或者域名的访问次数 ,http 字段中配置

http
{
limit_conn_zone $binary_remote_addr zone=addr:10m;
限制连接数:
​
要限制连接,必须先有一个容器对连接进行计数,在http段加入如下代码:
​
"zone=" 给它一个名字,可以随便叫,这个名字要跟下面的 limit_conn 一致
​
$binary_remote_addr = 用二进制来储存客户端的地址,1m 可以储存 32000 个并发会话

接下来需要对server不同的位置(location段)进行限速,比如限制每个IP并发连接数为1,则

server
​
{
​
listen 80;
​
server_name 192.168.1.10;
​
index index.html index.htm index.php;
​
limit_conn addr 1; #是限制每个IP只能发起1个连接 (addr 要跟 limit_conn_zone 的变量对应)
​
limit_rate 100k; #限速为 100KB/秒
​
root html;
}

测试:找一台服务器安装ab压测工具

[root@server2 ~]# yum -y install httpd-tools
[root@server2 ~]# ab -c 1000 -t 10 http://192.168.1.10/index.html

查看访问日志,结果出现了大量的503,503状态码意味着服务不可用。

七、总结

Nginx 是一个流行的 Web 服务器和反向代理服务器,它被广泛用于优化 Web 应用程序的性能、可靠性和可扩展性。在实际应用中,Nginx 具有许多强大的功能和选项,我们要学会如何配置nginx,这里要求掌握nginx的平滑升级和虚拟主机,SSL配置等功能,同时在nginx中还有很多第三方的扩展模块,要学会如何去配置和安装,其次在生产中,对域名的重写功能也是一个重点。

总之,Nginx 是一个非常强大的 Web 服务器和反向代理服务器,它具有丰富的功能和选项,可以优化 Web 应用程序的性能、可靠性和可扩展性。在实际应用中,Nginx 可以用于负载均衡、缓存、SSL 加密等功能,从而提高网站的性能和安全性。