实用的前端nginx配置-实战篇

451 阅读3分钟

Nginx 快速上手

apt install nginx / yum install nginx

nginx -v

nginx version: nginx/1.21.0

Nginx 操作常用命令

Nginx 的命令在控制台中输入 nginx -h 就可以看到完整的命令

-?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/nginx/)
  -e filename   : set error log file (default: logs/error.log)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

常用指令

nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启\
nginx -s reopen # 重启 Nginx\
nginx -s stop # 快速关闭\
nginx -s quit # 等待工作进程处理完成后关闭\
nginx -T # 查看当前 Nginx 最终的配置\
nginx -t -c <配置路径> # 检查配置是否有问题,如果已经在配置目录,则不需要-c

Nginx 配置

Nginx 的主配置文件是 /etc/nginx/nginx.conf,你可以使用 cat -n nginx.conf 来查看配置

nginx.conf 结构图

main # 全局配置,对全局生效\
├── events # 配置影响 Nginx 服务器或与用户的网络连接\
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置\
│ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分\
│ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块\
│ ├── server
│ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri\
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...

Nginx 语法规则

  • 每条指令以 ; 分号结尾,指令与参数间以空格符号分隔;
  • 指令块以 {} 大括号将多条指令组织在一起;
  • include 语句允许组合多个配置文件以提升可维护性;
  • 使用 # 符号添加注释,提高可读性;
  • 使用 $ 符号使用变量;

Nginx初始配置

# Nginx 进程数,一般设置为和 CPU 核数一样
worker_processes  1; 

# Nginx 的错误日志存放目录
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

# Nginx 服务启动时的 pid 存放位置
#pid        logs/nginx.pid;


events {
# 每个进程允许最大并发数
    worker_connections  1024;
}


http {
# 文件扩展名与类型映射表
    include       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"';

# Nginx访问日志存放位置
    #access_log  logs/access.log  main;
    
# 开启高效传输模式
    sendfile        on;
    
# 减少网络报文段的数量
    #tcp_nopush     on;

# 保持连接的时间,也叫超时时间,单位秒
    #keepalive_timeout  0;
    keepalive_timeout  65;

# gzip压缩
    gzip  on;
    gzip_min_length 1k;
    gzip_comp_level 3;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
    gzip_static on;
    gzip_vary on;
    gzip_buffers 2 4k;
    gzip_http_version 1.1;

# 加载子配置项
    include /usr/local/nginx/conf/conf.d/*.conf;
    server {
    
    # 配置监听的端口
        listen       80;
       
    # 配置的域名
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
        
        # 网站根目录
            root  html;
            
        # 默认首页文件
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        
        # 默认50x对应的访问页面
        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$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        
        # 禁止访问的ip地址,可以为all
        #    deny  all;
        
        # 允许访问的ip地址,可以为all
        #    allow 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 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;
    #    }
    #}

}

  • = 精确匹配路径,用于不含正则表达式的 uri 前,如果匹配成功,不再进行后续的查找;
  • ^~ 用于不含正则表达式的 uri 前,表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找;
  • ~ 表示用该符号后面的正则去匹配路径,区分大小写;
  • ~* 表示用该符号后面的正则去匹配路径,不区分大小写。跟 ~ 优先级都比较低,如有多个location的正则能匹配的话,则使用正则表达式最长的那个;

全局变量

配置一个web服务器你需要了解的全局变量

变量名称含义
$host请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名,不包含端口
$request_method请求类型,如 GETPOST
$remote_addr客户端的 IP 地址
$remote_port客户端的端口
$args请求参数
$arg_PARAMETERGET 请求中变量名 PARAMETER 参数的值,例如:$http_user_agent(Uaer-Agent 值), $http_referer...
$content_length请求头中的 Content-length 字段
$http_user_agentagent信息
$http_cookiecookie信息
$server_protocol请求使用的协议,如 HTTP/1.0HTTP/2.0
$server_addr服务器地址
$server_name服务器名称
$server_port服务器端口
$request_filename当前连接请求的文件路径,由root或alias指令与URI请求生成。

配置反向代理

vim /etc/nginx/nginx.conf

server {
    listen 80;
    server_name arc.com;
    location / {
        proxy_pass https://www.baidu.com;
    }
}

改完保存退出,nginx -s reload 重新加载,进入默认网址,那么现在就直接跳转到 baidu 站了

image.png

反向代理一些常用的指令

  • proxy_set_header:在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息;
  • proxy_connect_timeout:配置 Nginx 与后端代理服务器尝试建立连接的超时时间;
  • proxy_read_timeout:配置 Nginx 向后端服务器组发出 read 请求后,等待相应的超时时间;
  • proxy_send_timeout:配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;
  • proxy_redirect:用于修改后端服务器返回的响应头中的 Location 和 Refresh。

反向代理解决跨域

server {
    listen 80;
    server_name arc.com;
    location / {
        proxy_pass https://www.baidu.com;
    }
}

这样就将对前一个域名 arc.com 的请求全都代理到了 https://www.baidu.com;,前端的请求都被我们用服务器代理到了后端地址下,绕过了跨域。

配置 header 解决跨域


server
{
    listen 80;
    server_name arc.com;
    location /hello {
        proxy_pass http://localhost:3000;

        #   指定允许跨域的方法,*代表所有
        add_header Access-Control-Allow-Methods *;

        #   预检命令的缓存,如果不缓存每次会发送两次请求
        add_header Access-Control-Max-Age 3600;
        #   带cookie请求需要加上这个字段,并设置为true
        add_header Access-Control-Allow-Credentials true;

        #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
        #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号
        add_header Access-Control-Allow-Origin $http_origin;

        #   表示请求头的字段 动态获取
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;

        #   OPTIONS预检命令,预检命令通过时才发送请求
        #   检查请求的类型是不是预检命令
        if ($request_method = OPTIONS){
            return 200;
        }
    }
}

gzip 压缩

gzip 是一种常用的网页压缩技术,传输的网页经过 gzip 压缩之后大小通常可以变为原来的一半甚至更小(官网原话),更小的网页体积也就意味着带宽的节约和传输速度的提升,特别是对于访问量巨大大型网站来说,每一个静态资源体积的减小,都会带来可观的流量与带宽的节省。

    gzip  on;
    gzip_min_length 1k;
    gzip_comp_level 3;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
    gzip_static on;
    gzip_vary on;
    gzip_buffers 2 4k;
    gzip_http_version 1.1;
    gzip_proxied on;
  • gzip: 开启或关闭gzip压缩
  • gzip_min_length:允许压缩的页面最小字节数,页面字节数从header头中的 Content-Length 中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大;
  • gzip_comp_level:gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6;
  • gzip_types:要采用 gzip 压缩的 MIME 文件类型,其中 text/html 被系统强制启用;
  • gzip_static:默认 off,该模块启用后,Nginx 首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容;
  • gzip_vary:用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩;
  • gzip_buffers:获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得;
  • gzip_http_version:默认 1.1,启用 gzip 所需的 HTTP 最低版本;
  • gzip_proxied:默认 off,nginx做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩;

服务器文件2306491B,gzip压缩后浏览器得到599617B

image.png

image.png

Webpack 的 gzip 配置

webpack提供了compression-webpack-plugin插件来打包gzip

image.png

打包后

image.png

看到这里,大家可能会有个疑问,nginx提供了gzip压缩,webpack又提供了gzip压缩,是不是重复劳动了呢?实际上,如果全都是使用 Nginx 来压缩文件,会耗费服务器的计算资源,如果服务器的 gzip_comp_level 配置的比较高,就更增加服务器的开销,相应增加客户端的请求时间,得不偿失。因此你可以开始gzip_static on;

配置负载均衡

http {
    upstream myserver {
        # ip_hash; # ip_hash 方式
        # fair; # fair 方式
        server 127.0.0.1:8081; # 负载均衡目的服务地址
        server 127.0.0.1:8080;
        server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1
    }
    
    server {
        location / {
            proxy_pass http://myserver;
            proxy_connect_timeout 10;
        }
    }
}

Nginx 提供了好几种分配方式,默认为轮询,就是轮流来。有以下几种分配方式:

  • 轮询,默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;
  • weight,权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;
  • ip_hash,每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的;
  • fair(第三方),按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;

一些常用技巧

图片防盗

server {
    listen 80;
    server_name arc.com;

    # 图片防盗链
    location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
        valid_referers none blocked 192.168.0.2; # 只允许本机 IP 外链引用
        if ($invalid_referer) {
            return 403;
        }
    }
}

请求过滤

# 非指定请求全返回 403
if ($request_method !~ ^(GET|POST|HEAD)$ ) {
    return 403;
}

location / {
    # IP访问限制(只允许IP是 192.168.0.2 机器访问)
    allow 192.168.0.2;
    deny all;
 
    root html;
    index index.html index.htm;
}

配置静态文件缓存

# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
    expires 10d;
}

# 如果不希望缓存
expires -1;

单页面项目 history 路由配置

server {
    listen 80;
    server_name arc.com;
    
    location / {
        root /usr/share/nginx/html/dist; # vue 打包后的文件夹
        index index.html index.htm;
        try_files $uri $uri/ /index.html @rewrites;
        
        expires -1; # 首页一般没有强制缓存
        add_header Cache-Control no-cache;
    }
    
    # 接口转发,如果需要的话
    #location ~ ^/api {
        # proxy_pass http://www.baidu.com;
    #}
    
    location @rewrites {
        rewrite ^(.+)$ /index.html break;
    }
}

参考链接

Nginx 从入门到实践,万字详解!

segmentfault.com/a/119000001…

跨域资源共享 CORS 详解