Better

Ethan的博客,欢迎访问交流

Nginx具体应用

熟悉Nginx的基础配置和Nginx能达到的功能。

基本命令

# 快速关闭 nginx,可能不保存相关信息,并迅速终止 web 服务
nginx -s stop
# 平稳关闭 nginx,保存相关信息,有安排的结束 web 服务
nginx -s quit
# 因改变了 nginx 相关配置,需要重新加载配置而重载
nginx -s reload
# 重新打开日志文件
nginx -s reopen  
# 为 nginx 指定一个配置文件,来代替缺省的 
nginx -c filename
# 不运行,而仅仅测试配置文件。nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件
nginx -t
# 显示 nginx 的版本
nginx -v
# 显示 nginx 的版本,编译器版本和配置参数
nginx -V

基础配置

# 运行用户
# user somebody;
# 启动进程,通常设置成和 cpu 的数量相等
worker_processes  1;
# PID文件,记录当前启动的 nginx 的进程 ID
pid  D:/Tools/nginx-1.10.1/logs/nginx.pid;
# 工作模式及连接数上限
events {
    use epoll;
    # 单个后台 worker process 进程的最大并发链接数
    worker_connections 1024;
}
# 设定 http 服务器,利用它的反向代理功能提供负载均衡支持
http {
    # 设定 mime 类型(邮件支持类型),类型由 mime.types 文件定义
    include       D:/Tools/nginx-1.10.1/conf/mime.types;
    default_type  application/octet-stream;
     # 设定日志
    log_format
    # sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    # 必须设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的 uptime
    sendfile        on;
    # tcp_nopush     on;
    # 连接超时时间
    keepalive_timeout  120;
    tcp_nodelay        on;
    # gzip 压缩开关
    # gzip  on;
    # 设置允许跨域
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers Authorization,Content-Type,Accept,Origin,User-            Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since;
    add_header Access-Control-Allow-Methods GET,POST,PUT,PATCH,DELETE,OPTIONS;
    # 设定实际的服务器列表 
    upstream zp_server1{
        server 127.0.0.1:8089;
    }
}

反向代理

上面讲解了 nginx 的基础配置,更多的功能主要通过 http 节点下的 server 节点实现,比如反向代理。

反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个服务器。

server {
    # 监听 80 端口,80 端口是知名端口号,用于 HTTP 协议
    listen       80;
    # 定义使用 www.xx.com 访问
    server_name  www.helloworld.com;
    # 首页
    index index.html
    # 指向 webapp 的目录
    root home/default
    # 编码格式
    harset utf-8;
    # 代理配置参数:在默认情况下经过 proxy 转发的请求,在后端看来远程地址都是 proxy 端的 ip 
    proxy_connect_timeout 180;
    proxy_send_timeout 180;
    proxy_read_timeout 180;
    proxy_set_header Host $host;
    # 后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
    proxy_set_header X-Forwarder-For $remote_addr;
   # 允许 web 服务器端获得用户的真实 ip
    proxy_set_header X-Real-IP $remote_addr;
    # 反向代理的路径(和 upstream 绑定),location 后面设置映射的路径
    location / {
        proxy_pass http://zp_server1;
    } 
    # 静态文件,nginx 自己处理
    location ~ ^/(images|javascript|js|css|flash|media|static)/ {
        root \webapp\views;
        #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。
        expires 30d;
    }
    # 设定查看 nginx 状态的地址
    location /NginxStatus {
        stub_status           on;
        access_log            on;
        auth_basic            "NginxStatus";
        auth_basic_user_file  conf/htpasswd;
    }
    # 禁止访问 .htxxx 文件
    location ~ /\.ht {
        deny all;
    }
    # 错误处理页面(可选择性配置)
    # error_page   404              /404.html;
    # error_page   500 502 503 504  /50x.html;
    # location = /50x.html {
    #     root   html;
    # }
}

负载均衡

我们在 server 外添加了一个 upstream,而直接在 proxy_pass 里面直接用 http://+upstream 的名称来使用。

upstream 中的 server 元素必须要注意,不能加 http://,但 proxy_pass 中必须加。

# 设定负载均衡的服务器列表
upstream load_balance_server {
    #weigth参数表示权值,权值越高被分配到的几率越大
    server 192.168.1.11:80   weight=5;
    server 192.168.1.12:80   weight=1;
    server 192.168.1.13:80   weight=6;
}

多 webapp 配置

很多时候一个服务器会运行多个不同的系统,我们知道,http 的默认端口号是 80,如果在一台服务器上同时启动这 3 个 webapp 应用,都用 80 端口,肯定是不成的。所以,这三个应用需要分别绑定不同的端口号。那么问题来了,用户在实际访问 www.helloworld.com 站点时,访问不同 webapp,总不会还带着对应的端口号去访问吧。所以,你再次需要用到反向代理来做处理。

  • 一个一级域名实现

    upstream product_server{
      server www.helloworld.com:8081;
    }
    upstream admin_server{
      server www.helloworld.com:8082;
    }
    upstream finance_server{
      server www.helloworld.com:8083;
    }
    配合 server 下 location 进行实现:
    # 默认指向 product 的 server
    location / {
      proxy_pass http://product_server;
    }
    location /product/ {
      proxy_pass http://product_server;
    }
    location /admin/ {
      proxy_pass http://admin_server;
    }
    location /finance/ {
      proxy_pass http://finance_server;
    }
    通过以上方式访问时候通过添加路径参数的方式实现访问多站点。
    
  • 多个域名二级实现
    首先需要在服务器配置 DNS 解析。通过多 server,同 80 端口的方式实现访问多站点。
    具体配置如下:

    server {
    listen 80;
    server_name blog.pig1024.me;
    location / {
      proxy_pass http://120.76.244.22:8899;
      proxy_set_header X-Real-IP $remote_addr;
    }
    }
    server {
    listen       80;
    server_name  pig1024.me;
    index index.jsp index.html;
    root /home/default;
    location / {
      proxy_pass http://127.0.0.1:9000;
      proxy_set_header X-Real-IP $remote_addr;
    }
    }
    

Https 反向代理

配置基本相同,注意如下几点即可:

# 监听 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;
# 阿里云 DEMO
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
    proxy_pass http://127.0.0.1:9000;
    proxy_set_header X-Real-IP $remote_addr;
    root html;
    index index.html index.htm;
}

很明显站点开启 HTTPS 之后,需要保证 HTTP 也能正常访问,有两种处理处理方式:

  1. http 强制跳转 https(推荐)
    server {
         listen 80;
         server_name blog.pig1024.me;
     rewrite ^ https://$http_host$request_uri? permanent;
         #return 301 https://$http_host$request_uri;
    }
    
  2. 同时支持 http 和 https(不推荐)
    server {
     listen              80;
     listen              443 ssl;
     server_name         www.example.com;
     ssl_certificate     www.example.com.crt;
     ssl_certificate_key www.example.com.key;
     ...
    }
    

静态站点

有时候,我们需要配置静态站点(即 html 文件和一堆静态资源)。

server {
    listen       80;
    server_name  static.zp.cn;
    location / {
        root /app/dist;
        index index.html;
        # 转发任何请求到 index.html
    }
}

项目路径自定义

server {
  listen 80 default_server;
  server_name localhost;
  index index.jsp index.html;
  root /home/default;
  location ~ .* {
    proxy_pass http://127.0.0.1:9000;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
<Engine name="Catalina" defaultHost="localhost">
# 标签下增加 host 标签
<Host name="localhost"  appBase="/home/default"
           unpackWARs="true" autoDeploy="true">

Location 匹配规则

指令语法

location [=|~|~*|^~|@] /uri/ { … } 或 location @name { … }

匹配模式

  • 普通字符串匹配:以=开头或开头无引导字符(~)的规则
  • 正则匹配:以~或~开头表示正则匹配,~表示正则不区分大小写

匹配规则

总体的匹配原则是:先匹配普通字符串模式,再匹配正则模式

  1. 先查找是否有=开头的精准匹配
  2. 在查找普通匹配,以 最大前缀 为原则
  3. 需要注意的是通常匹配到一个普通格式后,搜索并未结束,而是暂存当前匹配的结果,并继续搜索正则匹配模式。
  4. 所有正则匹配模式 location 中找到第一个匹配项后,就以此项为最终匹配结果,所以正则匹配项匹配规则,受定义的前后顺序影响,但普通匹配模式不会
  5. 如果未找到正则匹配项,则以 3 中缓存的结果为最终结果
  6. 如果一个都没有找到,返回 404

正则匹配与非正则匹配

  1. location ~ /test/.+.jsp$ { … }:正则匹配,支持标准的正则表达式语法。
  2. location ^~ / { … }:^~意思是关闭正则匹配,当搜索到这个普通匹配模式后,将不再继续搜索正则匹配模式。

常见问题

权限问题

Nginx 代理静态资源后,错误提示 ERR_CONTENT_LENGTH_MISMATCH

  • 原因:nginx 会缓存大文件到 proxy_temp 目录中,主进程在读取缓存的时候由于权限问题而无法访问
  • 解决:通过 sudo chmod -R 777 /usr/local/var/run/nginx/* 打开权限即可

大神代码



留言

瑶哈哈
2017-07-27 23:17

666