前端必备 Nginx 配置
作者:mmseoamin日期:2024-02-02

Nginx (engine x) 是一个轻量级高性能的HTTP和反向代理服务器,同时也是一个通用 代理服务器 (TCP/UDP/IMAP/POP3/SMTP),最初由俄罗斯人Igor Sysoev编写。

基本命令:

nginx -s reopen #重启Nginx
nginx -s reload #重新加载Nginx配置文件,然后以优雅的方式重启Nginx
nginx -s stop #强制停止Nginx服务
nginx -s quit #优雅地停止Nginx服务(即处理完所有请求后再停止服务)
nginx -?,-h #打开帮助信息
nginx -v #显示版本信息并退出
nginx -V #显示版本和配置选项信息,然后退出
nginx -t #检测配置文件是否有语法错误,然后退出
nginx -T #检测配置文件是否有语法错误,转储并退出
nginx -q #在检测配置文件期间屏蔽非错误信息
nginx -p prefix #设置前缀路径(默认是:/usr/share/nginx/)nginx -c filename #设置配置文件(默认是:/etc/nginx/nginx.conf)
nginx -g directives #设置配置文件外的全局指令
killall nginx #杀死所有nginx进程

搭建好nginx服务器并启动过后,先看nginx默认配置,再介绍不同使用场景。

默认配置:

Nginx 安装目录下, 复制一份`nginx.conf`成`nginx.conf.default`作为配置文件备份,然后修改`nginx.conf`

# 工作进程的数量
worker_processes  1;
events {
    worker_connections  1024; # 每个工作进程连接数
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    # 日志格式
    log_format  access  '$remote_addr - $remote_user [$time_local] $host "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" "$clientip"';
    access_log  /srv/log/nginx/access.log  access; # 日志输出目录
    gzip  on;
    sendfile  on;
    # 链接超时时间,自动断开
    keepalive_timeout  60;
    # 虚拟主机
    server {
        listen       8080;
        server_name  localhost; # 浏览器访问域名
        charset utf-8;
        access_log  logs/localhost.access.log  access;
        # 路由
        location / {
            root   www; # 访问根目录
            index  index.html index.htm; # 入口文件
        }
    }
    # 引入其他的配置文件
    include servers/*;
}

搭建站点:

在其他配置文件`servers`目录下,添加新建站点配置文件 xx.conf。

# 虚拟主机
server {
    listen       8080;
    server_name  xx_domian; # 浏览器访问域名
    charset utf-8;
    access_log  logs/xx_domian.access.log  access;
    # 路由
    location / {
        root   www; # 访问根目录
        index  index.html index.htm; # 入口文件
    }
}

类型设置过期时间:

location ~.*\.css$ {
    expires 1d;
    break;
}
location ~.*\.js$ {
    expires 1d;
    break;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
    access_log off;
    expires 15d;    #保存15天
    break;
}
# curl -x127.0.0.1:80 http://www.test.com/static/image/common/logo.png -I #测试图片的max-age
复制代码

禁止缓存:

开发环境经常改动代码,由于浏览器缓存需要强制刷新才能看到效果。这是我们可以禁止浏览器缓存提高效率。

location ~* \.(js|css|png|jpg|gif)$ {
    add_header Cache-Control no-store;
}

防盗链:

防止文件被其他网站调用。

location ~* \.(gif|jpg|png)$ {
    # 只允许 192.168.0.1 请求资源
    valid_referers none blocked 192.168.0.1;
    if ($invalid_referer) {
       rewrite ^/ http://$host/logo.png;
    }
}

静态文件压缩:

server {
    # 开启gzip 压缩
    gzip on;
    # 设置gzip所需的http协议最低版本 (HTTP/1.1, HTTP/1.0)
    gzip_http_version 1.1;
    # 设置压缩级别,压缩级别越高压缩时间越长  (1-9)
    gzip_comp_level 4;
    # 设置压缩的最小字节数, 页面Content-Length获取
    gzip_min_length 1000;
    # 设置压缩文件的类型  (text/html)
    gzip_types text/plain application/javascript text/css;
}

执行命令 nginx -s reload,成功后浏览器访问。

指定错误页面:

# 根据状态码,返回对于的错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
    root /source/error_page;
}

跨域:

跨域的定义

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。通常不允许不同源间的读操作。

同源的定义

如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。

nginx解决跨域的原理

例如:

  • 前端server域名为:http://xx_domain
  • 后端server域名为:https://github.com

    现在http://xx_domain对https://github.com发起请求一定会出现跨域。

    只需要启动一个nginx服务器,将server_name设置为xx_domain,然后设置相应的location以拦截前端需要跨域的请求,最后将请求代理回github.com。如下面的配置:

    ## 配置反向代理的参数
    server {
        listen    8080;
        server_name xx_domain
        ## 1. 用户访问 http://xx_domain,则反向代理到 https://github.com
        location / {
            proxy_pass  https://github.com;
            proxy_redirect     off;
            proxy_set_header   Host             $host;        # 传递域名
            proxy_set_header   X-Real-IP        $remote_addr; # 传递ip
            proxy_set_header   X-Scheme         $scheme;      # 传递协议
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    }
    

    这样可以完美绕过浏览器的同源策略:github.com访问nginx的github.com属于同源访问,而nginx对服务端转发的请求不会触发浏览器的同源策略。

    负载均衡:

    Nginx听到的最多的就是负载均衡,那么什么是负载均衡?

    负载均衡:由于目前现有网络的各个核心部分随着业务量的提高,访问量和数据流量的快速增长,其处理能力和计算强度也相应地增大,使得单一的服务器设备根本无法承担。

    针对此情况而衍生出来的一种廉价有效透明的方法以扩展现有网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性的技术就是负载均衡(Load Balance)。

    Nginx实现负载均衡有几种方案:

    轮询:

    轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器。

    upstream backserver {
        server 192.168.0.14;
        server 192.168.0.15;
    }
    
    权重:

    权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。

    upstream backserver {
        server 192.168.0.14 weight=3;
        server 192.168.0.15 weight=7;
    }
    

    权重越高,在被访问的概率越大,如上例,分别是30%,70%。

    ip_hash:

    前两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,因此如果涉及到会话Session,那么会话会比较复杂。常见的是基于数据库的会话持久化。要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理。

    upstream backserver {
        ip_hash;
        server 192.168.0.14:88;
        server 192.168.0.15:80;
    }
    
    fair:

    按后端服务器的响应时间来分配请求,响应时间短的优先分配。

    upstream backserver {
        server server1;
        server server2;
        fair;
    }
    
    url_hash:

    按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效。

    upstream backserver {
        server squid1:3128;
        server squid2:3128;
        hash $request_uri;
        hash_method crc32;
    }
    

    在需要使用负载均衡的server中增加

    proxy_pass http://backserver/; 
    upstream backserver{ 
        ip_hash; 
        server 127.0.0.1:9090 down; (down 表示单前的server暂时不参与负载) 
        server 127.0.0.1:8080 weight=2; (weight 默认为1.weight越大,负载的权重就越大) 
        server 127.0.0.1:6060; 
        server 127.0.0.1:7070 backup; (其它所有的非backup机器down或者忙的时候,请求backup机器) 
    } 
    

    max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误。fail_timeout:max_fails次失败后,暂停的时间。

    配置实例:
    #user  nobody;
    worker_processes  4;
    events {
    # 最大并发数
    worker_connections  1024;
    }
    http{
        # 待选服务器列表
        upstream myproject{
            # ip_hash指令,将同一用户引入同一服务器。
            ip_hash;
            server 125.219.42.4 fail_timeout=60s;
            server 172.31.2.183;
        }
        server{
            # 监听端口
            listen 80;
            # 根目录下
            location / {
            # 选择哪个服务器列表
                proxy_pass http://myproject;
            }
        }
    }