Nginx(老博客迁移)

1,167 阅读9分钟

nginx命令

参数

-? / -h 帮助
-c 使用指定的配置文件
-g 指定配置指令
-p 指定运行目录
-s 发送信号
	 stop 立即停止服务
	 quit 优雅的停止服务
	 reload 重载配置文件
	 reopen 重新开始记录日志文件
-t / -T 测试配置文件是否有语法错误
-v / -V 打印nginx的版本信息, 编译信息等

Nginx启动

/usr/local/nginx/sbin/nginx

通过指定配置文件启动

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

配置文件语法检查

# 检查默认配置文件是否有语法错误
/usr/local/nginx/sbin/nginx -t
# 检查指定配置文件语法是否有错误
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -t

Nginx配置文件解读


#user  nobody;          # 设置worker进程运行用户
worker_processes  1;    # 配置workder进程数量,通常设置为cpu的数量或者cpu数量的2倍

#error_log  logs/error.log;     # 配置全局日志及日志级别-> debug > info > notice > warn > error > crit > alert > emerg
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;     # 配置进程pid文件


# 配置工作模式和连接数
events {
    worker_connections  1024;   # 配置每个worker进程连接数上限,nginx总连接数等于 worker_processes * worker_connections
}


http {
    include       mime.types;   # 配置nginx支持哪些多媒体类型,可以在conf/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"';

    # 配置access.log日志存放路径,并使用上面定义的main日志格式
    #access_log  logs/access.log  main;

    sendfile        on; # 开启高效文件传输模式
    #tcp_nopush     on; # 防止网络阻塞

    #keepalive_timeout  0;
    keepalive_timeout  65;  # 长连接超时时间,单位是秒

    #gzip  on;  # 开启gzip压缩输出

    # 配置虚拟主机
    server {
        listen       80;    # 配置监听端口
        server_name  localhost; # 配置域名

        #charset koi8-r;    # 配置字符集

        #access_log  logs/host.access.log  main;    # 设置此虚拟主机的访问日志,如果没有配置的话则使用全局的access_log

        # 默认匹配 / 的请求,当访问路径中有 / , 会被该location匹配并处理
        location / {
            root   html;    # root是配置服务器的默认网站根目录位置,默认为nginx安装目录下的html目录
            index  index.html index.htm;    # 配置默认首页文件的名称
        }

        #error_page  404              /404.html;    # 配置404页面

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;    # 配置50x页面
        
        # 精确匹配50x.html
        location = /50x.html {
            root   html;
        }

        # PHP请求全部转发到apache处理
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # PHP请求全部转发到FastCGI处理
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # 禁止访问.htaccess文件
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # 配置另一个虚拟主机
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # 配置https服务(安全的网络传输协议,加密传输)
    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

Nginx内置变量

$uri	当前请求的uri,不带参数
$request_uri	请求的uri,带完整参数
$host	http请求报文中host首部,如果没有则以处理此请求的虚拟主机的主机名代替
$hostname 	nginx服务运行在主机的主机名
$remote_addr	客户端IP
$remote_port	客户端端口
$remote_user	使用用户认证时客户端用户输入过的用户名
$request_filename	用户请求中的URI经过本地root或alias转换后映射的本地文件路径
$request_method	请求方法, GET, POST, PUT等
$server_addr	服务器地址
$server_name	服务器名称
$server_port	服务器端口
$server_protocol	服务器向客户端发送响应时的协议,如http/1.1 http/1.0
$scheme	在请求中使用scheme,如http://xxx.com中的http
$http_HEADER	匹配请求报文中指定的HEADER
$http_host	匹配请求报文中的host首部
$document_root	当前请求映射到的root配置文件
$time_local	nginx的时间
$request	request请求行,GET等方法, http协议等
$status	response返回的状态码
$body_bytes_sent	从服务端响应给客户端body信息大小
$http_referer	http上一级页面, 防盗链, 用户行为分析时会使用
$http_user_agent http头部信息, 客户端访问设备等信息
$http_x_forwarded_for	http请求携带的http信息

alias与root

location /hello {
    root /usr/local/nginx/html/myweb;
}
# 实际请求位置是/usr/local/nginx/html/myweb/hello,把/hello拼在后面


location /hello {
    alias /usr/local/nginx/html/myweb;
}
# 实际请求位置是/usr/local/nginx/html/myweb

打开目录文件浏览功能

location / {
    autoindex on;
}

autoindex常用参数

官网文档地址 nginx.org/en/docs/htt…

autoindex_exact_size off;
默认为on,显示出文件的确切大小,单位是bytes。
修改为off,显示出文件的大概大小,单位是KB或者MB或者GB

autoindex_localtime on;
默认为off,显示的文件时间为GMT时间。
修改为on,显示的文件时间为文件的服务器时间。

charset utf-8/gbk;
默认中文目录乱码,添加上解决乱码。

整个虚拟主机开启目录浏览

location / {
    autoindex on;
    autoindex_localtime on;
    autoindex_exact_size off;
}

单独目录开启目录浏览

直接二级目录开启目录流量

location /down/ {
    autoindex on;
    autoindex_localtime on;
    autoindex_exact_size off;
}

虚拟目录开启目录浏览

location /down/ {
    alias /home/wwwroot/test/;
    autoindex on;
    autoindex_localtime on;
    autoindex_exact_size off;
}

限制nginx每秒向客户端发起响应的速度

location / {
    set $limit_rate 1k;
}

日志格式

官网文档地址 nginx.org/en/docs/htt…

ngin x内置模块或第三方模块中的变量都可以配置上去,记录到日志中,这里main是日志格式的名称,可以自己起名字.

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;

反向代理

官网文档地址 nginx.org/en/docs/str…

Tcp, U四层代理

在http同级下配置

worker_processes auto;

error_log /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

stream {
    upstream backend {
        hash $remote_addr consistent;

        server backend1.example.com:12345 weight=5;
        server 127.0.0.1:12345            max_fails=3 fail_timeout=30s;
        server unix:/tmp/backend3;
    }

    upstream dns {
       server 192.168.0.1:53535;
       server dns.example.com:53;
    }

    server {
        listen 12345;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass backend;
    }

    server {
        listen 127.0.0.1:53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }

    server {
        listen [::1]:12345;
        proxy_pass unix:/tmp/stream.socket;
    }
}

示例

stream {
    upstream mysql_server {
       server 192.168.101.40:3306;
    }

    server {
        listen 3340;
        proxy_connect_timeout 5s;
        proxy_timeout 10s;
        proxy_pass mysql_server;
    }
}
Http七层代理

当我们使用nginx反向代理时,用于与反向代理服务器直接建立一个连接,反向代理与上游服务器建立另一个连接,当上游服务器想拿到用户的真实信息是(比如$remote_addr)时拿到的是反响代理的IP。

解决办法:

用户是直接和反向代理服务器建立连接的,因此我们可以在反向代理服务器上拿到用户的真实信息,我们把这些信息写入到请求头(header)发送给上游服务器,这样上游服务器就可以拿到用户的真实信息了

upstream myserver {
    server 127.0.0.1:8080;
}

location / {
    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://myserver;
}
# 反向代理也可以直接使用proxy_pass转发到上游服务器地址
location /admin {
    proxy_pass http://192.168.101.38:8080;
}

flask获取用户真实ip

from flask import Flask, request, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    real_ip = request.headers.get('X-Forwarded-For')
    if real_ip:
        return jsonify({'ip': request.remote_addr, 'real_ip': real_ip})
    return jsonify({'ip': request.remote_addr})


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

正向代理

server {
    listen 80;

    # dns
    resolver 233.5.5.5;
    location / {
        proxy_pass http://$http_host$request_uri;
    }
}

负载均衡

上游服务器在负载均衡调度中的状态

状态说明
down当前server暂时不参与负载均衡
backup预留的备份服务器
max_fails当前服务器请求失败的次数
fail_timeout经过max_fails失败后,服务暂停时间
max_conns限制最大连接数

负载均衡其它配置

upstream myserver {
    server 192.168.101.40:8080;
    server 192.168.101.41:8080;

    # backup表示备用机器,其它所有非backup机器down的时候,才请求backup机器
    server 192.168.101.42:8080 backup;
    # down表示当前的server节点是down的状态,不参与负载均衡
    server 192.168.101.43:8080 down;
}
upstream myserver {
    # weight表示权重,用于上游服务器性能不均的场景
    server 192.168.101.40:8080 weight=3;
    server 192.168.101.41:8080 weight=1;
}

location / {
    proxy_pass http://myserver;
}

负载均衡常用策略

  1. 轮询(默认)

    每个请求轮流分配到不同的上游服务器,如果上游服务器挂掉,将自动剔除

    upstream myserver {
        server 192.168.101.40:8080;
        server 192.168.101.41:8080;
    }
    
  2. 权重

    每个请求按一定比例分发到不同的上游服务器, weight值越大访问比例越大,用于上游服务器性能不均的场景

     upstream myserver {
         server 192.168.101.40:8080 weight=2;
         server 192.168.101.41:8080 weight=1;
     }
    
  3. ip_hash

    ip_hash也叫IP 绑定,每个请求按访问的hash值分配,这样每个访问的客户端会固定访问一个上游服务器,可以解决会话Session丢失的问题。

    upstream myserver {
        ip_hash;
        server 192.168.101.40:8080;
        server 192.168.101.41:8080;
    }
    
  4. 最少连接

    请求会被转发到连接数最少的服务器上

    upstream myserver {
        least_conn;
        server 192.168.101.40:8080;
        server 192.168.101.41:8080;
    }
    
  5. url_hash

    按照访问的URL的hash结果来分配请求,使每个URL定向到同一个后端服务器

    upstream myserver {
        hash $request_uri;
        server 192.168.101.40:8080;
        server 192.168.101.41:8080;
    }
    

动静分离

静态资源请求交由nginx处理,动态请求由nginx转发至上游服务器处理

实现静态代理

当访问静态资源的时候,则从/usr/local/nginx/html/static目录下获取

基于静态资源后缀匹配

location ~ .*\.(js|css|htm|html|gif|jpg|jpeg|png|bmp|swf|ico|rar|zip|txt)$ {
    root /usr/local/nginx/html/static;
}

~表示正则匹配

.第一个点表示任意字符

\.表示转义字符,把.转义为原来的.

|表示或者的意思

$表示结尾

基于静态文件目录匹配

location ~ .*/(css/js/img/image){
    root /usr/local/nginx/html/static;
}

虚拟主机

nginx可通过配置多个server标签来配置多个虚拟主机部署多个网站。

可以通过配置不同端口来配置多个虚拟主机。

也可以通过相同端口不同域名来配置虚拟主机。

使用缓存

用户请求分两种,一种是静态,一种是动态,当不同用户访问同一个URL看到的内容是不同的,这就是一个动态请求,需要交由上游服务器处理,而有些资源是一段时间不会发送变化的,这个时候为了减轻上游服务器的压力,我们可以让nginx把上游服务器返回的内容缓存一段时间,比如缓存一天,在一天之内即使上游服务器对这个内容的响应发生了变化,也不会交由上游服务器去处理,只会去拿nginx缓存中的内容响应给浏览器。因为nginx的性能远远领先于上游服务器的性能,使用这样一种特性,对一些小的站点会有非常大的性能提升。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m max_size=10g inactive=60m use_temp_path=off;

使用缓存

location / {
    proxy_cache mycache;
    proxy_cache_key $host$uri$is_args$args;
    proxy_cache_valid 200 304 302 1d;
}

GoAccess实时开始化监控access日志

Nginx进程结构

  • Master进程
  • Worker进程
  • Cache manager进程
  • Cache loader进程

说明:

worker进程数量的设置一般对应cpu的数量。

进程结构说明:

Master是一个父进程,它有很多子进程WorkerCache managerCache loader

Master主要是用来做Worker进程的管理(监控每个Worker进程是不是在正常的工作,需不需要做重载配置,需不需要做热部署等工作),真正用来处理请求的是Worker进程

Cache loader是用来做缓存的载入。

Cache manager是用来做缓存的管理。

Nginx进程管理: 信号

- Master进程
  - 监控worker进程
  - CHLD
  - 管理worker进程
  - 接收信号
    - TERM,INT
    - QUIT
    - HUP
    - USR1
    - USR2
    - WINCH
- Worker进程
  - 接收信号
    - TERM,INT
    - QUIT
    - USR1
    - WINCH
- Nginx命令行
  - reload	-> HUP
  - reopen  -> USR1
  - stop    -> TERM
  - quit    -> QUIT

发送信号

kill -HUP 进程ID

Nginx执行reload流程

1.向master进程发送HUP信号(reload命令)
2.master进程校验配置语法是否正确
3.master进程打开新的监听端口(或其它应用其它修改的部分)
4.master进程用新配置启动新的worker子进程
5.master进程向老worker子进程发送QUIT新型号
6.老worker进程关闭监听句柄,处理完当前连接后结束进程

Nginx热升级流程

1.将旧nginx文件替换成新的nginx文件(注意备份)
2.向master进程发送USR2信号
3.master进程修改pid文件名,加后缀.oldbin
4.master进程用新nginx文件启动master进程
5.向老master进程发送QUIT信号,关闭老master进程
6.回滚:向老master发送HUP,向新master发送QUIT

worker进程:优雅的关闭(主要针对http请求)

1.设置定时器
	worker_shutdown_timeout
2.关闭监听句柄
3.关闭空闲连接
4.在循环中等待全部连接关闭
5.退出进程

Nginx访问限制

连接限制limit_conn_module

# http模块配置
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

# 同一时刻只允许一个客户端IP连接
location / {
    limit_conn conn_zone 1; 	
}

请求限制limit_req_module

# http模块配置,rate限制速率,限制一秒钟最多处理一个IP请求
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s

# location模块配置,1r/s直接收一个请求,多余的直接处理
location / {
    limit_req zone=req_zone;
}

# location模块配置,请求超过1r/s,剩下的将被延迟处理
location / {
    limit_req zone=req_zone burst=3 nodelay;
}
# 压力测试
ab -n 50 -c 20 页面地址

基于IP的访问控制http_access_module

官方文档地址nginx.org/en/docs/htt…

允许 配置语法

Syntax:	allow address | CIDR | unix: | all;
Default:	
Context:	http, server, location, limit_except

拒绝 配置语法

Syntax:	deny address | CIDR | unix: | all;
Default:	
Context:	http, server, location, limit_except

拒绝某一个IP,其它的全部允许

location / {
    root /home/wwwroot/web;
    index index.html;
    deny 192.168.10.18;
    allow all;
}

如有允许某个IP,其它全部拒绝,那么就先配置允许的,在后面写deny all;

基于用户登录认证http_auth_basic_module

官网文档地址nginx.org/en/docs/htt…

​ 配置语法

Syntax:	auth_basic string | off;
Default:	
auth_basic off;
Context:	http, server, location, limit_except

用户密码配置文件

Syntax:	auth_basic_user_file file;
Default:	—
Context:	http, server, location, limit_except
yum -y install httpd-tools

htpasswd语法

Usage:
htpasswd [-cimBdpsDv] [-C cost] passwordfile username
htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password
htpasswd -n[imBdps] [-C cost] username
htpasswd -nb[mBdps] [-C cost] username password

参数说明
-c 创建passwdfile.如果passwdfile 已经存在,那么它会重新写入并删去原有内容.
-n 不更新passwordfile,只将加密后的用户名密码显示在屏幕上;
-m 默认采用MD5算法对密码进行加密
-d 采用CRYPT算法对密码进行加密
-p 不对密码进行进行加密,即使用普通文本格式的密码
-s 采用SHA算法对密码进行加密
-b 命令行中一并输入用户名和密码而不是根据提示输入密码,可以看见明文,不需要交互
-D 删除指定的用户

示例

# 创建用户用户
htpasswd -cb /usr/local/nginx/conf/htpasswd wanghaha 123456

# 删除用户
htpasswd -D /usr/local/nginx/conf/htpasswd wanghaha
location / {
    auth_basic           "closed site";
    auth_basic_user_file /usr/local/nginx/conf/htpasswd;
}

gzip压缩

# 开启gzip
gzip off;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 1;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

# 设置压缩所需要的缓冲区大小     
gzip_buffers 32 4k;

# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;

rewrite

正则测试工具pcretest

yum -y install pcre-tools

语法:

/中间写正则表达式/

[root@localhost ~]# pcretest
PCRE version 8.32 2012-11-30

  re> /^(\d{3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
data> 192.168.101.1
 0: 192.168.101.1
 1: 192
 2: 168
 3: 101
 4: 1

Rewrite标记flag

flag说明
last停止rewrite检测
break停止rewrite检测
redirect返回302临时重定向,地址栏会显示跳转后的地址
permanent返回301永久重定向,地址栏会显示跳转后的地址

浏览器缓存

# nginx时间单位
ms  milliseconds 毫秒
s   seconds 
m   minutes
h   hours
d   days
w   weeks
M   months, 30 days
y   years, 365 days
# 页面缓存20天
location / {
    expires 20d;
}

跨域访问

location ~ .*\.(html|htm)$ {
    add_header Access-Control-Allow-Origin http://你的域名.com;
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
}

静态资源防盗链

只允许指定服务器IP地址(或域名)来访问静态资源

location \ .*\.(jpg|gif|png)$ {
    valid_referers none blocked 192.168.101.40;
    if($invalid_referer) {
        return 403;
    }
}