1.nginx1.16.1编译安装

1.1 安装相关依赖包

  1. yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel

1.2 下载安装包

wget http://nginx.org/download/nginx-1.16.1.tar.gz

1.3 创建nginx用户

groupadd nginx
useradd nginx -g nginx -s /sbin/nologin -M

1.4 解压

tar zxvf nginx-1.16.1.tar.gz

1.5 编译安装

configure脚本支持的常用选项:

选项 说明
—prefix=path 定义一个目录,存放服务器上的文件,也就是nginx的安装目录,默认使用/usr/local/nginx
—sbin-path=path 设置nginx的可执行文件的路径,默认为prefix/sbin/nginx
—conf-path=path 设置nginx.conf配置文件的路径,nginx允许使用不同的配置文件启动,通过命令行中的-c选项,默认是为prefix/conf/nginx.conf
—pid-path=path 设置nginx.pid文件,将存储的主进程的进程号;安装完成后,可以随时改变的文件名,在nginx.conf配置文件中使用PID指令;默认情况下,文件名为prefix/logs/nginx.pid
—error-log-path=path 设置错误,警告日志的文件路径,安装完成后,可以在nginx.conf配置文件中使用error_log指定,默认情况下,为/prefix/logs/error.log
—http-log-path=path 设置请求日志文件路径,在nginx.conf中使用access_log来修改,默认为,prefix/logs/access.log
—user=name 设置nginx进程的用户,可以在nginx.conf中user来指定,默认为nobody
—group=name 设置nginx进程的用户组,可以在nginx.conf中user来指定,默认为非特权用户
—with-select_module —without-select_module 启用或禁用构建一个模块来允许服务器使用select()方法;该模块将自动建立,如果平台不支持kqueue,epoll,rtsig或/dev/poll
—with-poll_module —without-poll_module 启用或禁用构建一个模块来允许服务器使用poll()方法;该模块将自动建立,如果平台不支持kqueue,epoll,rtsig或/dev/poll
without-http_gzip_module 不编译压缩的HTTP服务器的响应模块,编译并运行此模块需要zlib库,默认支持
without-http_rewrite_module 不编译重写模块,编译并运行此模块需要PCRE库支持,默认支持
without-http_proxy_module 不编译http_proxy模块,默认支持
—with-http_ssl_module 使用https协议模块,默认情况下,该模块没有被构建,建立并运行此模块的OpenSSL库是必需的
—with-http_v2_module 支持grpc代理的必须模块
—with-pcre=path 设置PCRE库的源码路径,PCRE库的源码需要从PCRE网站下载并解压,其余的工作是nginx的编译来完成,正则表示式使用在location指令和ngx_http_rewrite_module模块中

编译安装:

cd nginx-1.16.1

./configure
    --prefix=/etc/nginx
    --sbin-path=/usr/sbin/nginx
    --conf-path=/etc/nginx/nginx.conf
    --error-log-path=/var/log/nginx/error.log
    --http-log-path=/var/log/nginx/access.log
    --pid-path=/var/run/nginx.pid
    --lock-path=/var/run/nginx.lock
    --http-client-body-temp-path=/var/cache/nginx/client_temp 
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp
    --user=nginx
    --group=nginx
    --with-http_ssl_module
    --with-http_realip_module
    --with-http_addition_module
    --with-http_sub_module
    --with-http_dav_module
    --with-http_flv_module
    --with-http_mp4_module
    --with-http_gunzip_module
    --with-http_gzip_static_module
    --with-http_secure_link_module
    --with-http_stub_status_module
    --with-http_auth_request_module
    --with-threads
    --with-stream
    --with-stream_ssl_module
    --with-http_slice_module
    --with-http_v2_module

make && make install

1.6 修改配置文件

mkdir -p /var/cache/nginx /etc/nginx/http.d /etc/nginx/stream.d
rm -fr nginx-1.16.1*

nginx.conf:
    #user  nobody;
    user  nginx;

    #Multicore
    worker_processes     auto;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  10240;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for" "$http_host"'
                        '$request_time $upstream_response_time $pipe - $upstream_addr';

        log_format  post_format $request_body;

        access_log  /var/log/nginx/access.log  main;
        error_log  /var/log/nginx/error.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  120;
        proxy_connect_timeout 600;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;

        #gzip  on;

        include /etc/nginx/http.d/*.conf;
    }

    stream {
        log_format proxy '$remote_addr [$time_local] '
                        '$protocol $status $bytes_sent $bytes_received '
                        '$session_time "$upstream_addr" '
                        '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
        access_log /var/log/nginx/stream.access.log proxy;

        include /etc/nginx/stream.d/*.conf;
    }

2. 配置文件说明

2.1 配置文件的组成部分

主配置文件:nginx.conf

include http.d/*.conf 在主配置文件中加入指令;然后在目录中建立http.d;在里面添加片段来实现;


2.2 配置指令(必须以分号结尾)

directive value1 [value2..];

支持使用变量:

  • 内置变量:由模块引入,可直接引用;
  • 自定义变量:set variable_name value;
    • 引用变量:$variable_name

2.3 配置文件结构

  • main block: 全局配置;
  • events { … }; 事件驱动的相关配置;
  • http { … }; http协议的相关配置
  • mail { … }; mail相关的配置;

2.4 http相关配置

http {
    ...
    server {
        ...
        listen IP:PORT;
        server_name localhost;    # 域名配置,没有域名使用localhost
        root  PATH;       # html目录路径
        alias
        location /url/ {
            ...
        }
    }
    server {
        ...
    }
}

2.5 正常运行的必备配置:

  • user USERNAME [GROUPNAME];
    指定用于运行worker进程的用户和组;
    user nginx nginx;
  • pid /PATH/TO/PID_FILE;
    指定nginx进程的pid文件路径;
    pid /var/run/nginx.pid;
  • worker_rlimit_nofile number;
    每个worker进程所能够打开的最大文件数;

3. 各个功能的实现

3.1 性能优化相关的配置

  • worker_processes number | auto;
    worker的进程数;通常应该为CPU的核心数减1;
  • worker_cpu_affinity cpumask…;
    将worker进程绑定在哪个cpu上;
    worker_cpu_affinity auto [cpumask];
    CPUMASK:
    0001 四核的0

    1000

    0000 0001  八核的0
    ...
    1000 0000
    
  • worker_priority nice;
    优先级,跟的是nice数值;
    [-20,19]
    100-139


3.2 调试、定位问题相关配置

  • daemon on | off;
    守护进程可以在后台运行;
    是否以守护进程方式启动nginx进程;
  • master_process on |off;
    是否以master/worker模型启动nginx进程;
  • error_log file | stderr | syslog:server=address[,parameter=value] | memory:size [debug|info|notice|warn|error|crit|alert|emerg];
    错误日志文件的记录方式及其日志级别;
    • file /PATH/TO/SOME_LOG_FILE;
    • stderr: 发送到错误输出;
    • syslog:server=address[,parameter=value]: 发送给syslog服务器;
    • memory:size


日志级别:
debug依赖于configure时的—with-debug选项;
注意:nginx不用原内核,则会导致CPU本地缓存没办法用了
注意:默认是守护进程方式(可以后台运行),调试的时候要关闭守护进程方式以及master模型;
注意:错误日志中的debug(显示调试信息)依赖于编译时的—with-debug选项;


3.3 定义套接字相关配置

  • server{..}
    配置一个虚拟主机;

    server{
        listen PORT;
        server_name HOSTNAME;
        root /PATH/TO/DOCUMENTROOT;
        ...
        location /url/ {
            ...
        }
    }
    
  • listen address[:port] [default_server] [ssl] [backlog=number] [rcvbuf=size] [sndbuf=size];
    listen port [default_server] [ssl];
    listen unix:path [default_server] [ssl];

    • default-server:默认虚拟主机;
    • ssl: 限制只能通过ssl连接提供服务;
    • backlog:后缓队列的长度;
    • rcvbuf: 接收缓存大小;
    • sndbuf:发送缓冲区大小;
  • server_name name..;
    指明当前server的主机名;后可跟一个或空白符分隔的多个主机;
    支持使用*任意长度的任意字符;
    支持以~起始的正则表达式模式字符串;
    应用策略:
    1. 首先精确匹配;
    2. 左侧*通配符匹配;
    3. 右侧*通配符匹配;
    4. 正则表达式模式匹配; ``` server_name www.test.com;

server_name *.test.com;

server_name www.test.*;

server_name ~^..test..$;

mail.test.com,www.test.com


- tcp_nodelay on|off;<br />tcp延迟发送,将多个小的报文攒在一起再发送,这会导致某些小的请求过不来<br />对keepalived模式下的连接是否启用TCP_NODELAY选项;<br />tcp_nopush on|off
- sendfile on|off;<br />默认off,直接在内核中封装响应报文发送给客户端;<br />是否启用sendfile功能;
- root path;<br />定义路径相关配置<br />设置web资源路径映射;用于指明用户请求的url所对应的本地文件系统上的文档所在目录路径;<br />可用上下文:http,server,location,if
- location [= | ~ | ~* | ^~] uri {...} **|** location [@name ](/name ) {...} <br />根据用户请求的URI来匹配定义的location,匹配到时,此请求将被相应的location块中的指令所处理;<br />=:URI精确匹配<br />~:做正则表达式模式匹配,区分字符大小写;<br />~*:做正则表达式模式匹配,不区分字符大小写;<br />^~: 对URI的左半部分做匹配检查,不区分字符大小写;<br />匹配优先级:=、^、/~*、不带符号;

www.test.com/images/1.jpg /images/1.jpg 则为URI请求;


- alias path;<br />定义路径别名,文档映射的一种机制;仅能用于location上下文;<br />root指令:给定的路径对应于location中的/rui/左侧的/;<br />alias指令:给定的路径对应于location中的/uri/右侧的/;

alias /bbs/ /web/forum/ http://www.test.com/bbs/a.jpg

location /bbs/{ alias /web/forum/; }

/web/forum/a.jpg

location /bbs/{ root /web/forum/; }

/web/forum/bbs/a.jpg


- index file...;<br />可用位置:http,server,location
- error_page code ...[=[response]] uri;<br />根据用户请求的资源的http响应的状态码实现错误页重定向;<br />http:[//www.test.com/hello.html](//www.test.com/hello.html) --> 因为资源不存在而被改为对http:[//www.test.coom/404.html](//www.test.coom/404.html)

---

<a name="85c407b4"></a>
### 3.4 客户端请求的相关配置

- keepalive_timeout timeout [header_timeout];<br />设定保持连接的超时时长,0表示禁止长连接;默认为75s;
- keepalive_requests number;<br />在一次长连接上所允许请求的资源的最大数量,默认为100;
- keepalive_disable none | browser ...;<br />对哪种浏览器禁用长连接;
- send_timeout time;<br />向客户端发送响应报文的超时时长;特别的,是指两次写操作之间的间隔时长;
- client_max_body_size 1000M;<br />限制上传文件大小限制,默认为1m
- client_header_timeout 1m;<br />读取请求头的超时时间
- client_body_timeout 1m;<br />读取请求尸体的超时时间
- client_body_buffer_size size;<br />用于接收客户端请求报文的body部分的缓冲区大小;默认为16k;超出此大小时,其将被暂存到磁盘上;
- clien_body_temp_path path [level1[level2[level3]]];<br />设定用于存储客户端请求报文的body部分的临时存储路径及子目录结构和数量;<br />/var/tmp/body 2 1 2<br />00-ff<br />注意:[level1[level2[level3]]]; 每个level用一个数字表示,每个1表示1个十六进制数字的意思;建立的存储文件则按级往下分;<br />level1 = 2  2个十六进制数字,00-ff,256个文件;
- limit_rate rate;<br />限制响应给客户端的传输速率,单位是bytes/sevond,0表示无限制;

dd if=/dev/zero of=/web/host1/download/test.img bs=1M count=50


- limit_except method ...{...};<br />限制对指定的请求方法之外的其它方法的使用客户端;

limit_except GET POST{ allow 172.18.0.0/16; deny all; }

表示除了GET和POST之外的其他方法仅允许172.18.0.0/16中的主机使用;


---

<a name="352ea861"></a>
### 3.5 文件操作优化的配置

- aio on | off | threads[=pool];<br />是否启用aio功能;
- directio size | off;
- open_file_cache off;**|** open_file_cache max=N [inactive=time];<br />nginx可以缓存以下三种信息:
   - 文件的描述符、文件大小和最近一次的修改时间;
   - 打开的目录的结构;
   - 没有找到的或者没有权限访问的文件的相关信息;

<br />max=N: 可缓存的缓存项上限达到上限后会使用LRU算法实现缓存管理;<br />inactive=time: 缓存项的超时时长,在此处指定的时长内未被命中的缓存项即为非活动项;

- open_file_cache_errors on | off;<br />是否缓存查找时发生错误的文件一类的信息;
- open_file_cache_min_uses number;<br />在open_file_cache指令的inactive参数指定的时长内,至少命中此处指定的次数方可不被归类到非活动项;
- open_file_cache_valid time;<br />缓存项有效性的检查频率;默认是60s;

---

<a name="8ece09c8"></a>
## 4. 常用模块介绍

<a name="aec0f867"></a>
### 4.1 ngx_http_access_module

实现基于ip的访问控制功能;

- allow address | CIDR | unix: | all;
- deny  address | CIDR | unix: | all;

可用上下文:http, server, location, limit_except

---

<a name="3e63b8f6"></a>
### 4.2 ngx_http_auth_basic_module

认证功能;

- auth_basic string | off;<br />使用basic机制进行用户认证;
- auth_basic_user_file file;<br />认证用的账户密码文件;<br />文件格式:name:password:commet

htpasswd -m /etc/nginx/.ngxpasswd jerry

vim nginx.conf

location /admin{ auth_basic “Admin Area”; auth_basic_user_file /etc/ginx/.ngxpasswd; }

mkdir /web/host1/admin


---

<a name="b315ed4d"></a>
### 4.3 ngx_http_stub_status_module

用于输出nginx的基本状态信息;

Active connections: 1 server accepts handled requests 155 155 298 Reading:0 Writing:1 Waiting:0


- Active connections: 处于活动状态的客户端连接的数量;
- accepts:已经接受的客户端请求的总数;
- handled:已经处理完成的客户端请求的总数;
- requests:客户端发来的总的请求数;
- Reading:处于读取客户端请求报文首部的连接数;
- Writing: 处于向客户端发送响应报文过程中的连接数;
- Waiting:处于等待客户端发出请求的空闲连接数;

location /status { stub_status }


valid_referers none | blocked | server_names |string..;

定义合法的referer数据;

- none:请求报文首部没有referer首部;
- blocked:请求报文的referer首部没有值;
- server_names:其值是主机名;
- arbitrary string:直接字符串,可以使用*作为通配符;
- regular expression:被指定的正则表达式模式匹配到的字符串;要使用~起始;

valid_referers none blocked server_names _.test.com test._ ~.test.;

if($vivalid_referer){ return 403; }


referers定义一些合理的跳转过来的网站链接,如果在referers首部不合理则拒绝访问;

---

<a name="9dcdc6ad"></a>
### 4.4 ngx_http_ssl_module

- ssl on | off;<br />是否启用当前虚拟主机的ssl功能;
- ssl_certificate file;<br />当前虚拟主机使用的PEM格式的证书文件;
- ssl_certificate_key file;<br />当前虚拟主机使用的证书文件中的公钥配对儿的私钥文件路径,PEM格式;
- ssl_protocols [SSLv2][SSLv3][TLSv1][TLSv1.1][TLSv1.2];<br />SSL协议的版本;
- ssl_session_cache off | none | [builtin[:size]][shared:name:size];<br />指明ssl会话的缓存机制;
   - builtin: 使用openssl内建的缓存机制,此为各worker独有;
   - shared:由各worker共享的缓存;
   - name: 缓存空间的名称;
   - size: 字节为单位的缓存空间的大小,每1MB内存空间可缓存4000个会话;
- ssl_session_timeout time;<br />ssl会话超时时长,指ssl session cache中缓存条目有效时长;<br />ssl是在tcp建立以后,然后建立起ssl会话连接,断开时先断开ssl然后才是tcp四次挥手;
- ssl_session_cache builtin:1000 shared:SSL:10m;<br />SSL: 表示an arbitraty name ,多个虚拟主机可共享同一个名称的ssl缓存空间;<br />10m: 表示10M,1M大概有4000sessions;

<a name="9a505032"></a>
#### 4.4.1 nginx配置私有CA和https

<a name="d833984b"></a>
##### 1.生成CA证书:

openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt Country Name (2 letter code) [AU]:CN # 指定国家代码 State or Province Name (full name) [Some-State]:shanghai # 省份 Locality Name (eg, city) []:shanghai # 城市名称 Organization Name (eg, company) [Internet Widgits Pty Ltd]:ceshi # 公司名称 Organizational Unit Name (eg, section) []:devops # 部门 Common Name (e.g. server FQDN or YOUR name) []:test.com # 一般写当前主机名即可 Email Address []: # 邮箱,也可以不写


ca.crt        # 公钥

ca.key        # 私钥

<a name="1786669a"></a>
##### 2.生成证书请求文件:

openssl req -newkey rsa:4096 -nodes -sha256 -keyout test.ky -out test.csr Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:shanghai
Locality Name (eg, city) []:shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ceshi
Organizational Unit Name (eg, section) []:devops
Common Name (e.g. server FQDN or YOUR name) []:test.com # 注意,这里可用写泛域名,在生产环境中最好写你公司的网站地址,如果多网站需要使用证书可用泛域名,当对来说比较贵 Email Address []:

Please enter the following ‘extra’ attributes to be sent with your certificate request A challenge password []: # 注意,这里不要输入密码,直接回车即可,否则nginx在使用证书时需要交互式输入密码 An optional company name []:


test.key        # 专门用于网站的私钥

test.csr        # 专门用于网站的公钥,但是该公钥还没有被签发证书,需要找自建的CA服务器做证书签发,有时候也可以说它是证书请求文件

<a name="26a138b5"></a>
##### 3.签发证书

openssl x509 -req -days 36500 -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt


test.crt         # 被私有CA签发证书的公钥,这个证书文件可以直接使用了

<a name="5fb9b443"></a>
##### 4.验证证书内容

openssl x509 -in test.crt -noout -text


<a name="245ea4fd"></a>
#### 4.4.2 证书相关

- SSL:Secure Sockets Layer,现在应该叫"TLS",https就是带加密的http协议,而https的加密是基于SSL的;
- OpenSSL:是SSL的一个实现,SSL只是一种规范;
- X.509: 一种证书标准,主要定义了证书中应该包含哪些内容;
- 同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式:
   - PEM:Privacy Enhanced Mail,打开看文本格式,以"------BEGIN..."开头,"-----END..."结尾,内容是BASE64编码;<br />查看PEM格式证书的信息:openssl x509 -in cerificate.pem -text -noout<br />Apache和*NIX服务器偏向于使用这种编码格式;
   - DER:Distinguished Encoding Rules,打开看是二进制格式,不可读;<br />查看DER格式证书的信息:openssl x509 -in certificate.der -inform der -text -noout<br />JAVA和Windows服务器偏向于使用这种编码格式;

<a name="95a7b01e"></a>
##### 相关的文件扩展名

- CRT:CRT应该是certificate的三个字母,其实还是证书的意思,常见于*NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码;
- CER:还是certificate,还是证书,常见于Windows系统,同样的,可能是PEM编码,也可能是DER编码,大多数应该是DER编码;
- KEY:通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER;<br />查看KEY的办法:openssl rsa -in mykey.key -text -noout<br />如果是DER格式的话:openssl rsa -in mykey.key -text -noout -inform der
- CSR:Certificate Signing Request,即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥,<br />在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保存好;<br />查看的办法:openssl req -noout -text -in my.csr(如果是DER格式的话照旧加上-inform der)
- PFX/P12:predecessor of PKCS#12,对*nix服务器来说,一般CRT和KEY是分开存放在不同文件中的,但Windows的IIS则将它们存在一个PFX文件中,<br />因此这个文件包含了证书和私钥,PFX通常会有一个提取密码,想把里面的东西读取出来的话,它就要求你提供提取密码,PFX使用的是DER编码;<br />PFX转换为PEM编码:openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes<br />生成PFX的命令:<br />其中CACert.crt是CA的根证书,有的话也通过-certfile参数一起带进来,PFX其实是个证书密钥库;

openssl pkcs12 -export -in certificate.crt -inkey privatekey.key -out certificate.pfx -certfile CACert.crt


- JKS:Java Key Storage,Java的专利,跟Openssl关系不大,利用Java的一个叫keytool工具生成,也可以将PFX转为JKS;

<a name="871909ce"></a>
##### 证书编码的转换

- PEM转为DER:openssl x509 -in cert.crt -outform der -out cert.der
- PEM转成CRT:openssl x509 -in fullchain.pem -out fullchain.crt
- openssl rsa -in privkey.pem -out privkey.key
- DER转为PEM:openssl x509 -in cert.crt -inform der -outform pem -out cert.pem<br />(要转换KEY文件也类似,要把x509换成rsa,要转CSR的话,把x509换成req)

<a name="5a79859a"></a>
##### 获得证书

- 向权威证书颁发机构申请证书:<br />把csr交给权威证书颁发机构,权威证书颁发机构对此进行签名,完成。保留好csr,当权威证书颁发机构颁发的证书过期的时候,你还可以用同样的csr来申请新的证书,key保持不变;

openssl req -newkey rsa:2048 -new -nodes -keyout my.key -out my.csr


- 生成自签名的证书:<br />在生成证书的过程中会填一堆东西,其实真正要填的只有Common Name,通常填写你服务器的域名,或者服务器的IP

openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem


- 可获得免费ssl证书:[https://letsencrypt.org/zh-cn/getting-started/](https://letsencrypt.org/zh-cn/getting-started/)

---

<a name="72545131"></a>
### 4.5 ngx_http_log_module

The ngx_http_log_module module writes request logs in the specified format.

- access_log path [format [buffer=size [flush=time]] [if=condition]];
- access_log path format gzip[=level] [buffer=size] [flush=time] [if=condition];
- access_log syslog:server=address[,parameter=value][format[if=condition]];
- access_log off;

log_format name string...;

- open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
- open_log_file_cache off;
   - max: 最大缓存条目;
   - inactive=time:非活动时长;
   - min_uses: 最少使用次数;
   - valid:验证缓存条目有效性的频率;

---

<a name="e32f19f9"></a>
### 4.6 ngx_http_rewrite_module

rewrite regex replacecement [flag];

- 把用户请求的URI基于regex做检查,匹配到时将替换为replacement指定的字符串;
- 在同一个location中存在的多个rewrite规则会自上而下逐个被检查(循环);可以使用fiag控制此循环功能;
- 如果replacement是以http://或https://开头,则替换结果会直接以重定向方式返回给客户端;

[flag]

- last: 重写完成后停止对当前uri在当前location中的后续其它重写操作,改为对新uri的新一轮处理;
- break:重写完成后停止对当前uri在当前location中的后续其他重写操作;
- redirect:重写完成以后以临时重定向方式直接返回重写后生成的新的URL给客户端,由客户对新URL进行请求;(302)
- permanent:重写完成以后以永久重定向方式直接返回重写后生成的新的URL给客户端,由客户对新URL进行请求;(301)

rewrite_log on | off;

是否启用重写日志;启用时,日志信息被发往错误日志;

if(condition){...};

条件判断机制,在条件满足时,执行配置块中的配置;<br />引入一个新的配置上下文;

比较表达式,condition:

- ==,!=
- ~:模式匹配,区分字母大小写;
- ~*:模式匹配,不区分字符大小写;
- !~: 模式不匹配,区分字符大小写;
- !~*:模式不匹配,不区分字符大小写;

文件及目录存在性判断:

- -f,!-f: 文件
- -d,!-d: 目录
- -e,!-e: 存在
- -x,!-x: 执行

return:

- return code [text];
- return code URL;
- return URL;

set $variable value;

用户自定义变量;

---

<a name="d6300d5e"></a>
### 4.7 ngx_http_gzip_module

过滤器,对指定类型的资源压缩传输以节约带宽;

- gzip on | off;<br />启用或禁用gzip压缩响应报文;
- gzip_comp_level level;<br />指定压缩比,1-9,默认为1;
- gzip_disable regex...;<br />regex是匹配客户端浏览器类型的模式,表示对所有匹配到的浏览器不执行压缩响应;
- gzip_min_length length;<br />触发启用压缩功能的响应报文的最小长度;
- gzip_http_version 1.0 | 1.1;<br />设定启用压缩响应功能时,协议的最小版本;
- gzip_types mime-type ..;<br />指定仅执行压缩的资源内容类型;默认为text/html;
- gzip_proxied off | expired | no-cache | no-store |private | no_last_nodified | no_etag | auth | any..<br />对代理的请求基于何种属性判断其是否应该启用压缩功能;

示例:

gzip on; gzip_http_version 1.0; gzip_comp_level 6; gzip_disable msie6; gzip_min_length 2; gzip_types text/plain text/css text/xml application/x-javascript application/xml application/json application/java-script;


---

<a name="f6c0b147"></a>
### 4.8 ngx_http_fastcgi_module

LNMP -> nginx+php -> fastcgi

php: 编译时,支持fpm;

./configure ... --enable-fpm

php-fpm工作方式(类似于httpd的perfork):

- listen = 127.0.0.1:9000
- listen.allowed_cilents = 127.0.0.1
- pm = dynamic | static
   - pm.start_servers: 启动fpm进程时启动的工作进程数量;
   - pm.min_spare_servers: 最少空闲进程数;
   - pm.nax_spare_servers: 最大空闲进程数;
   - pm.max_children: 最大工作进程数;
- user = USERNAME
- group = GROUPNAME

fastcgi模块指令:

- fastcgi_pass address;<br />address是fpm服务器监听的地址和端口;<br />示例: `fastcgi 127.0.0.1:9000;`
- fastcgi_index name;<br />fastcgi应用的主页名称;
- fastcgi_param parameter value [if_not_empty];<br />传递给fpm服务器的参数及其值;
- fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time]<br />[loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
   - path: 文件系统路径,用于存储缓存的文件数据;
   - max_size=size: 定义此路径下的多大空间用于存储缓存数据;
   - levels=#[:#[:#]]: 缓存目录层级定义;
   - levels=1:2
   - keys_zone=name:size<br />内存中用于缓存k/v(内存/磁盘)映射关系的空间名称及大小;
   - inactive=time

注意:只能定义在http上下文;

- fastcgi_cache zone | off;<br />是否启用cache,如果启用,数据缓存于哪个cache中;
- fastcgi_cache_key string;<br />定义要使用的缓存键;<br />例如:fastcgi_cache_key $request_rui;
- fastcgi_cache_methods GET | HEAD | POST..;<br />缓存哪些类型的请求的相关类型;
- fastcgi_cache_min_uses number;
- fastcgi_cache_valid [code...] time;<br />对不同响应码设定其可缓存时长;<br />注意:调用缓存时,至少应该指定三个参数
- fastcgi_cache
- fastcgi_cache_key
- fastcgi-cache_valid

注意:nginx中不能转php,php只是httpd的模块;

yum -y install php-fpm php-mysql php-mbstring php-gd php-xml

vim /etc/php-fpm.d/www.conf

http{ fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcgicache:10m } location { fastcgi_cache fcgicache; fastcgi_cache_key $request_uri; fastcgi_cache_valid 200 302 10m; fastcgi_cache_valid 301 1h; fastcgi_cache_valid any 1m; }

ab -c 10 -n 100 https://192.168.40.135/text.php


---

<a name="1acb365e"></a>
### 4.9 ngx_http_proxy_module

Nginx是轻量级的,那么就会少了很多特性,所以一般就作为httpd的反向代理服务器;

lnamp: 前端静态资源用nginx处理,动态资源通过nginx的反向代理请求到后端的httpd,httpd利用php模块来加载;(整个过程就不需要用到fastcgi);

<a name="a36ec4cd"></a>
#### 4.9.1 proxy_pass URL;

- url 只是host<br />这里指不包含 $uri, 如:
   - `http://host`
   - `https://host`
   - `http://host:port`
   - `https://host:port`
   - `http://host/`
   - `http://host:port`

// 访问: / 后端: / // 访问: /api/xx 后端: /api/xx // 访问: /api/xx?aa 后端: /api/xx?aa location / { proxy_pass http://node:8080; }

// 访问: /api/ 后端: /api/ // 访问: /api/xx 后端: /api/xx // 访问: /api/xx?aa 后端: /api/xx?aa // 访问: /api-xx?aa 后端: location /api/ { proxy_pass http://node:8080; }

// 访问: /api/ 后端: /api/ // 访问: /api/xx 后端: /api/xx // 访问: /api/xx?aa 后端: /api/xx?aa // 访问: /api-xx?aa 后端: /api-xx?aa location /api { proxy_pass http://node:8080; }


- url包含路径<br />当 proxy_pass url 的 url 包含路径时,匹配时会根据 location 的匹配后的链接透传给 url,<br />在 proxy_pass url 包含路径时,将会把匹配之后的路径透传给url,如;
| location 规则 | 访问的原始链接 | 匹配之后的路径 |
| --- | --- | --- |
| location / | / |  |
| location / | /a | a |
| location / | /a/b/c?d | a/b/c?d |
| location /a/ | /a/ |  |
| location /a/ | /a/b/c?d | b/c?d |

// 访问: / 后端: / // 访问: /api/xx 后端: /api/xx // 访问: /api/xx?aa 后端: /api/xx?aa location / { proxy_pass http://node:8080/; }

// 访问: /api/ 后端: / // 访问: /api/xx 后端: /xx // 访问: /api/xx?aa 后端: /xx?aa // 访问: /api-xx?aa 未匹配 location /api/ { proxy_pass http://node:8080/; }

// 访问: /api 后端: / // 访问: /api/ 后端: // // 访问: /api/xx 后端: //xx // 访问: /api/xx?aa 后端: //xx?aa // 访问: /api-xx?aa 后端: /-xx?aa location /api { proxy_pass http://node:8080/; }

// 访问: /api/ 后端: /v1 // 访问: /api/xx 后端: /v1xx // 访问: /api/xx?aa 后端: /v1xx // 访问: /api-xx?aa 未匹配 location /api/ { proxy_pass http://node:8080/v1; }

// 访问: /api/ 后端: /v1/ // 访问: /api/xx 后端: /v1/xx // 访问: /api/xx?aa 后端: /v1/xx // 访问: /api-xx?aa 未匹配 location /api/ { proxy_pass http://node:8080/v1/; }


- 如果location定义其rui时使用了正则表达式匹配机制,则proxy_pass后的路径必须不能使uri;

location ~|~* PATTEN { proxy_pass http://HOST; }


- 重写代理链接 - url rewrite<br />当原始链接(浏览器访问的链接)和代理服务器链接规则不一致时,可以使用Nginx URL Rewrite功能去动态的重写,如:<br />以上请求会把匹配 /api/ 的链接重写为 /?path= 的链接透传给 node:8080 服务,有意思的是当使用 rewrite 指令并且生效后,proxy_pass url 链接中的路径会被忽略,如:

location ~ ^/api/ { rewrite ^/api/(.) /?path=$1 break; proxy_pass http://node:8080; }

```
// 访问:   /                               后端:   /node/
// 访问:   /api                            后端:   /node/api
// 访问:   /api/                           后端:   /?path=
// 访问:   /api/a/b/c                      后端:   /?path=a/b/c
location / {
    rewrite ^/api/(.*) /?path=$1 break;
    proxy_pass http://node:8080/node/;
}

4.9.2 proxy_set_header

  • proxy_set_header field value;
    设定向后端主机发送的请求报文的首部及其值;
    示例:
    对于在nginx提供反向代理的时候,后端日志记录为真正的客户端IP而不是nginxIP:
    前端nginx上:
    后端httpd服务器上:
    proxy_set_header X-Forwarded-For $proxy_add_x_forward_for; //更常用,转发端的值,后边变量表示将$remote_addr的值追加到前边转发的值上(因为有多级代理,会将各级代理的ip追加在一起);
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add-x_forwared_for;
    
    # vim /etc/nginx/conf.d/default.conf
    server {
    proxy_set_header X-ReaL-IP(自己定义的名称) $remote_addr(引用的变量);
    }
    
    # vim /etc/httpd/conf/httpd.conf
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined    
    LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    

4.10 ngx-cache-module

  • proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size];
    用于http上下文;
  • proxy_cache zone|off;
    调用缓存,默认为off;
  • proxy_cache_key string;
    定义缓存键:
    • proxy_cache_key $request_uri
    • proxy_cache_key $scheme$proxy$request_uri
    • $scheme$proxy_host$request_uri //请求协议:代理服务器:请求的链接
  • proxy_cache_valid [code …] time;
    为不同的响应码设定其缓存的时长
    示例:

    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    
  • proxy_cache_use_stale error|timeout|invalid_header|updating|http_500|http_502|http_503|off….


4.11 ngx_http_proxy_module

跟连接相关的命令

  • proxy_connect_timeout time;
    与后端服务器建立连接的超时时长,默认为60s,最长为75s;
  • proxy_read_timeout time;
    等待后端主机发送响应报文的超时时长,默认为60s;
  • proxy_send_timeout time;
    向后端服务发送请求报文的超时时长,默认为60s;

4.12 ngx_http_headers_module

用于在响应给客户端的报文中添加首部

  • add_header name value [always];
    向响应报文添加自定义首部,并赋值;
    http,server,locaiton,if in location
    add_header X-Via $server_addr(本机IP的变量);
  • expires(过期时间) [modified] time;
    expires epoch | max | off;
    用于添加Expire及Cache-Control首部或修改首部的值;

4.13 ngx_http_upstream_module

将多个后端主机定义为服务器组,而后可由proxy_pass,fastcgi_pass,memcached_pass等进行引用;

  • upstream name {…}
    定义后端服务器组;引入新的上下文;只能用于http上下文;
    name: 名称,直接字符串;
  • server
    server address [parameters];
    定义服务器的地址和相关的参数;
    地址格式:
    • IP[:port]
    • HOSTNAME[:port]
    • unix:/PATH/TO/SOME_SOCK_FILE


参数:

  • weight=number: 服务器权重;
  • max_fails=number: 最大失败尝试次数;
  • fail_timeout=time:设置服务器不可用超时时长;
  • backup:备用主机;
  • down:手动标记其不再处理任何用户请求;
    • ip_hash
      源地址哈希调度算法;
    • least_conn
      最少连接调度算法;
    • health_check [parameters];
      定义后端主机的健康状态检测机制;只能用于location上下文;
      可用参数:
  • interval=#: 检测的频度,默认为5秒;
  • fails=number:判定为失败的检测次数(3+);
  • passes=number:判定为成功的检测次数(1);
  • uri=uri:执行健康状态检测时请求的uri;
  • match=name:基于哪个match做检测结果为“成功”或“失败”的判定;
  • port=number:向服务器的哪个端口发起健康状态检测请求;
    • match name {…}
      仅能用于http上下文;对后端主机做健康状态检测时定义其结果判断标准;
      专用指令:
  • status
    • status CODE
    • status | CODE
    • status CODE-CODE
  • header:基于响应首部进行判断
    • header HEADER-VALUE
    • header HEADER!=VALUE
    • header [!] HEADER
    • header HEADER ~ VALUE
  • body: 期望的响应报文的主体部分应该有的内容;
    • body ~ “CONTENT”
    • body !~ “CONTENT”


注意:只能在nginx 2.0以上;

  • hash key [consistent]
    定义调度方法,可自定义基于何种信息(key)进行绑定;
    • hash $remote_addr
    • hash $request_uri
    • hash $cookie_username

补充:内置变量的调用,向客户端展示缓存命令与否;

addr_header X-Cache $upstream_cache_status;


5. 实例

http {
  proxy_cache_path /var/cache/nginx/proxy levels=1:1:1 keys_zone=pcache:10 max_size=1g;

  upstream websrvs {
    server 192.168.10.129:80 weight=2;
    server 192.168.10.130:80 weight=1;
    least_conn;
  }

  match health {
    status 200;
    body ~ "OK";
  }
}

server{
  proxy_set_header X-Real-IP $remote_addr

  location / {
    add_header X-Via $server-addr;
    add_header X-Cache $upstream_cache_status  //缓存命中与否;
    proxy_cache pcache;
    proxy_cache_key $request_uri;
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    proxy_pass http://192.168.10.129;
    health_check match=health interval=2 fails=3 uri=/.health.html(隐藏的文件);
  }

  location ~* \.php$ {
    proxy_pass http://192.168.10.130;
  }

客户端和代理服务器之间使用ssl,代理和后端服务器使用httpd;

http://nginx.org/en/docs/http/ngx_http_core_module    //查找nginx的各种变量;

ip hash:只能在upstream中调度;

  upstream websrvs {
    server 192.168.10.129:80 weight=2;
    server 192.168.10.130:80 weight=1;

    sticky cookie srv_id expires=1h path=/;

6. nginx做代理

6.1 四层tcp代理和负载均衡

nginx - 图1

  • 前提
    nginx要支持ngx_stream_core_module和ngx_stream_proxy_module模块,可以使用nginx -V来查看是否已经支持
  • 示例 ``` cat /etc/nginx/stream.d/test.conf

upstream UPSTREAM_NAME { server IP:PORT weight=5 max_fails=3 fail_timeout=30s; }

server { listen LOCAL_PORT; proxy_pass UPSTREAM_NAME; proxy_connect_timeout 1s; proxy_timeout 600s; access_log /var/log/nginx/test.log proxy; }


---

<a name="37b506a3"></a>
### 6.2 七层代理

- 示例

cat /etc/nginx/http.conf/test.conf

server { listen PORT; server_name www.test.com; # 如果没有域名,写成localhost client_max_body_size 5000M; proxy_connect_timeout 1200; keepalive_timeout 1200; proxy_read_timeout 1200; proxy_send_timeout 1200; location / { proxy_connect_timeout 1200; keepalive_timeout 1200; proxy_read_timeout 1200; proxy_send_timeout 1200; client_max_body_size 5000M; proxy_pass http://IP:PORT; } }


---

<a name="84156eed"></a>
### 6.3 grpc代理

- 前提
   - nginx版本要大于1.13.10+
   - ngixn要支持两个模块--with-http_ssl_module --with-http_v2_module,可以使用nginx -V查看;
- 示例

server { listen PORT http2;

location / {
  grpc_pass grpc://IP:PORT;
}

} ```