Nginx

目录

https://wangchujiang.com/nginx-tutorial/open in new window

1.安装

采用docker安装

docker pull nginx

# 启动并挂载配置目录 和静态资源目录
docker run --name my-nginx \
-p 80:80 \
-v /homt/ubuntu/nginx/conf:/etc/nginx \
-v /homt/ubuntu/nginx/html:/usr/share/nginx/html \
-d nginx

2.常用命令

service nginx start    # 启动nginx
service nginx reload   # 重新加载nginx配置文件
service nginx restart  # 重启
service nginx stop     # 停止
nginx -s reopen        # 重启 Nginx
nginx -s stop          # 停止 Nginx
nginx -v               # 查看版本号

3.配置

反向代理

HTTP

反向代理是一个Web服务器,它接受客户端的连接请求,然后将请求转发给上游服务器,并将从服务器得到的结果返回给连接的客户端。下面简单的反向代理的例子:

# 把http://localhost:80; 的请求转发到http://localhost:8080;上
server {  
  listen       80;                                                        
  server_name  localhost;                                              
  client_max_body_size 1024M;  # 允许客户端请求的最大单文件字节数

  location / {
    proxy_pass                         http://localhost:8080;
    proxy_set_header Host              $host:$server_port;
    proxy_set_header X-Forwarded-For   $remote_addr; # HTTP的请求端真实的IP
    proxy_set_header X-Forwarded-Proto $scheme;      # 为了正确地识别实际用户发出的协议是 http 还是 https
  }
}

复杂的配置: gitlab.com.conf:

# 把git.example.cn 的请求转发到http://localhost:3000;上
server {
    #侦听的80端口
    listen       80;
    server_name  git.example.cn;
    location / {
        proxy_pass   http://localhost:3000;
        #以下是一些反向代理的配置可删除
        proxy_redirect             off;
        #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
        proxy_set_header           Host $host;
        client_max_body_size       10m; #允许客户端请求的最大单文件字节数
        client_body_buffer_size    128k; #缓冲区代理缓冲用户端请求的最大字节数
        proxy_connect_timeout      300; #nginx跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
        proxy_buffer_size          4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
        proxy_buffers              4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
        proxy_busy_buffers_size    64k; #高负荷下缓冲大小(proxy_buffers*2}
}

HTTPS

一些对安全性要求比较高的站点,可能会使用 HTTPS(一种使用 ssl 通信标准的安全 HTTP 协议)。

这里不科普 HTTP 协议和 SSL 标准。但是,使用 nginx 配置 https 需要知道几点:

  • HTTPS 的固定端口号是 443,不同于 HTTP 的 80 端口
  • SSL 标准需要引入安全证书,所以在 nginx.conf 中你需要指定证书和它对应的 key

其他和 http 反向代理基本一样,只是在 Server 部分配置有些不同。

  #HTTP服务器
  server {
      #监听443端口。443为知名端口号,主要用于HTTPS协议
      listen       443 ssl;

      #定义使用www.xx.com访问
      server_name  www.helloworld.com;

      #ssl证书文件位置(常见证书文件格式为:crt/pem)
      ssl_certificate      cert.pem;
      #ssl证书key位置
      ssl_certificate_key  cert.key;

      #ssl配置参数(选择性配置)
      ssl_session_cache    shared:SSL:1m;
      ssl_session_timeout  5m;
      #数字签名,此处使用MD5
      ssl_ciphers  HIGH:!aNULL:!MD5;
      ssl_prefer_server_ciphers  on;

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

负载均衡

简单轮询

这里我配置了2台服务器,当然实际上是一台,只是端口不一样而已,而8081的服务器是不存在的,也就是说访问不到,但是我们访问 http://localhost 的时候,也不会有问题,会默认跳转到http://localhost:8080具体是因为Nginx会自动判断服务器的状态,如果服务器处于不能访问(服务器挂了),就不会跳转到这台服务器,所以也避免了一台服务器挂了影响使用的情况,由于Nginx默认是RR策略,所以我们不需要其他更多的设置

# 把localhost的请求转发到localhost:8080;或者localhost:8081;上面 轮询
upstream test {
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

权重

# 把localhost的请求转发到localhost:8080;或者localhost:8081;上面 9:1的请求比例
upstream test {
    server localhost:8080 weight=9;
    server localhost:8081 weight=1;
}

server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

ip_hash

# 把localhost的请求转发到localhost:8080;或者localhost:8081;根据IP的hash取余
upstream test {
    ip_hash;
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

fair:服务器响应时长

upstream test {
    fair;
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

least_conn:最少连接

upstream test {
    least_conn;
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

random:随机

upstream test {
    random;
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

上述server指令可选参数:

  1. weight:设置一个服务器的访问权重,数值越高,收到的请求也越多;
  2. fail_timeout:在这个指定的时间内服务器必须提供响应,如果在这个时间内没有收到响应,那么服务器将会被标记为down状态;
  3. max_fails:设置在fail_timeout时间之内尝试对一个服务器连接的最大次数,如果超过这个次数,那么服务器将会被标记为down;
  4. down:标记一个服务器不再接受任何请求;
  5. backup:一旦其他服务器宕机,那么有该标记的机器将会接收请求。

复杂模板如下:

upstream gitlab {
    ip_hash;
    # upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
    server 192.168.122.11:8081 ;
    server 127.0.0.1:82 weight=3;
    server 127.0.0.1:83 weight=3 down;
    server 127.0.0.1:84 weight=3; max_fails=3  fail_timeout=20s;
    server 127.0.0.1:85 weight=4;;
    keepalive 32;
}
server {
    #侦听的80端口
    listen       80;
    server_name  git.example.cn;
    location / {
        proxy_pass   http://gitlab;    #在这里设置一个代理,和upstream的名字一样
        #以下是一些反向代理的配置可删除
        proxy_redirect             off;
        #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
        proxy_set_header           Host $host;
        proxy_set_header           X-Real-IP $remote_addr;
        proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size       10m;  #允许客户端请求的最大单文件字节数
        client_body_buffer_size    128k; #缓冲区代理缓冲用户端请求的最大字节数
        proxy_connect_timeout      300;  #nginx跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300;  #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300;  #连接成功后,后端服务器响应时间(代理接收超时)
        proxy_buffer_size          4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
        proxy_buffers              4 32k;# 缓冲区,网页平均在32k以下的话,这样设置
        proxy_busy_buffers_size    64k; #高负荷下缓冲大小(proxy_buffers*2)
        proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
    }
}

重定向

  • permanent 永久性重定向。请求日志中的状态码为301
  • redirect 临时重定向。请求日志中的状态码为302

重定向整个网站

server {
    server_name old-site.com
    return 301 $scheme://new-site.com$request_uri;
}

重定向单页

server {
    location = /oldpage.html {
        return 301 http://example.org/newpage.html;
    }
}

重定向整个子路径

location /old-site {
    rewrite ^/old-site/(.*) http://example.org/new-site/$1 permanent;
}

跨域配置

在工作中,有时候会遇到一些接口不支持跨域,这时候可以简单的添加add_headers来支持cors跨域。配置如下:

server {
  listen 80;
  server_name api.xxx.com;
    
  #允许跨域请求的域,*代表所有
  add_header 'Access-Control-Allow-Origin' *;
  #允许带上cookie请求
  add_header 'Access-Control-Allow-Credentials' 'true';
  #允许请求的方法,比如 GET/POST/PUT/DELETE
  add_header 'Access-Control-Allow-Methods' *;
  #允许请求的header
  add_header 'Access-Control-Allow-Headers' *;

  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host  $http_host;    
  } 
}

爬虫过滤

根据 User-Agent 过滤请求,通过一个简单的正则表达式,就可以过滤不符合要求的爬虫请求(初级爬虫)。

location / {
    if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp") {
        return 503;
    }
    # 正常处理
    # ...
}

限流

Nginx 的”流量限制”使用漏桶算法(leaky bucket algorithm),该算法在通讯和分组交换计算机网络中广泛使用,用以处理带宽有限时的突发情况。就好比,一个桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水将会溢出;同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据”先进先出调度算法”(FIFO)等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

http {
  # 每个IP地址限制请求速度为每秒10次
  # Zone - 定义用于存储每个 IP 地址状态以及被限制请求 URL 访问频率的共享内存区域。
  # Rate - 定义最大请求速率;际上以毫秒的粒度来跟踪请求,所以速率限制相当于每 100 毫秒 1 个请求
  limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

  server {
    listen       80;
    server_name  example.com;

    location /api/ {
      # 使用限流 
      # burst:定义了超出 zone 指定速率的情况下,客户端还能发起多少请求(等于是一个缓冲队列,需要排队)
      # nodelay:可以提高请求的响应速度和用户体验,但可能会导致请求超出限制的频率
      limit_req zone=mylimit burst=20 nodelay;
      
      # 对限流的请求返回 444状态码
      limit_req_status 444;
      
      # 设置被限流的请求日志级别
      limit_req_log_level warn;
      
      proxy_pass http://localhost:3000/;
    }

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

白名单配置

定义了一个map,白名单的IP对应值就是0,返回的地址是"",其他IP对应的值是1,返回的地址就是实际IP,而空串将不会被限流,同理可以配置黑名单限流

geo $limit {
    default         1;
    # 白名单IP列表
    10.0.0.0/8         0;
    192.168.0.0/64     0;
}
map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server {
    location / {
        limit_req zone=req_zone burst=10 nodelay;

        # ...
    }
}

防盗链

location /api/ {
      #对源站点验证
      valid_referers *.imooc.com; 
      #非法引入会进入下方判断
      if ($invalid_referer) {
          return 404;
      } 
      proxy_pass http://localhost:3000/;
    }

静态文件压缩

http{
    #开启gzip,减少我们发送的数据量
    gzip on;
    #大于1k后开始压缩
    gzip_min_length 1k;
     
    #4个单位为16k的内存作为压缩结果流缓存
    gzip_buffers 4 16k;
     
    #gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
    gzip_comp_level 5;
     
    #压缩的类型
    gzip_types application/javascript text/plain text/css application/json application/xml    text/javascript; 
     
    #给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
    gzip_vary on;
     
    #禁用IE6以下的gzip压缩,IE某些版本对gzip的压缩支持很不好
    gzip_disable "MSIE [1-6].";
}
Last Updated: