全栈前端的nginx使用笔记

1,636 阅读6分钟

全栈前端的nginx使用笔记

简介

Nginx是一款可以通过反向代理实现负载均衡的服务器,使用 Nginx服务实现负载均衡的时候,用户的访问首先会访问到 Nginx服务器,然后 Nginx服务器再从服务器集群表中选择压力较小的服务器,然后将该访问请求引向该服务器。若服务器集群中的某个服务器崩溃,那么从待选服务器列表中将该服务器删除,也就是说一个服务器假如崩溃了,那么 Nginx就肯定不会将访问请求引入该服务器了。那么下面,我们通过实例来讲解一下Ngnx负载均衡的实现。

安装

nginx的安装此处就先跳过,大家可以自行百度,mac 可以直接使用brew install nginx直接安装

如果安装了不知道(或者后面忘了),可以用以下命令看下nginx的配置文件所在位置

nginx -t 测试nginx的配置文件是否正确,同时也可以看出nginx的配置文件所在位置

基础配置

nginx 最简单的反向代理

location ^~ /api/ {
  proxy_pass  http://192.168.8.184:8080/api/;
}

单页应用常用配置

server{
        listen 8888;    静态资源访问端口
        server_name localhost;
        root    /opt/uums_server/dist;    静态资源位置
        index index.html;     资源入口文件
        try_files $uri $uri/ /index.html;    单页应用配置支持URL HTML5 History【单页应用必填项】
        location / {
               proxy_pass http://192.168.78.104:3002;   接口代理的后台服务地址
        }
}

匹配模式及顺序

location = /uri    =开头表示精确匹配,只有完全匹配上才能生效。

location ^~ /uri   ^~ 开头对URL路径进行前缀匹配,并且在正则之前。

location ~ pattern  ~开头表示区分大小写的正则匹配。

location ~* pattern  ~*开头表示不区分大小写的正则匹配。

location /uri     不带任何修饰符,也表示前缀匹配,但是在正则匹配之后。

location /      通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default。

root 与alias区别

此处以如下两种配置来对比,作为案例

配置1:
location /two {
        root   /root/wwwroot/two;
        index  index.html index.htm;
}
配置2:
 location /two {
     alias   /root/wwwroot/two;
     index  index.html index.htm;
 }

这里将root改成alias的区别如下:

使用root会将location后的two追加在路径的尾部,在访问时就会访问到/root/wwwroot/two/two路径下去 将root改成alias则不会将two追加在路径尾部,访问时就为正确路径/root/wwwroot/two

也可以将配置2改成下面的:

配置3:  与配置2等效
 location /two {
     root   /root/wwwroot;
     index  index.html index.htm;
}

总结: root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。

  • root的处理结果是:root路径+location路径
  • alias的处理结果是:使用alias路径替换location路径
  • alias是一个目录别名的定义,root则是最上层目录的定义。

注意:

  1. 使用alias时,目录名后面一定要加"/"。
  2. alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
  3. alias只能位于location块中。(root可以不放在location中)

location加不加斜杠的区别

proxy_pass 末尾有斜杠/ 代理之后地址替换url包含localtion的匹配词;否则只替换匹配词之前url;

下面我们举个生动的🌰: 浏览器请求地址:"http://localhost:8888/proxy/config/getSystemTitle" 下面我们使用不同的配置看一下转发之后的接口到哪里了!!!

情况一:proxy_pass url中无下级路由【**端口末尾有斜杠/ **代理之后地址连localtion的匹配词一起替换;否则只替换匹配词之前url;】

1-1:
server{
        listen 8888;
        server_name localhost;
        location /proxy/ {
                 proxy_pass http://127.0.0.1:3003/;
        }
}

代理到URL:"http://localhost:3003/config/getSystemTitle"

1-2:
location /proxy/ {
    proxy_pass http://127.0.0.1:3003;
}

代理到URL:"http://localhost:3003/proxy/config/getSystemTitle"

情况二:proxy_pass url中没有下级路由【连匹配词一起替换拼接(无论末尾是否有斜杠)】

2-1:
location /proxy/ {
    proxy_pass http://127.0.0.1:3003/config/;
}

代理到URL:"http://127.0.0.1:3003/config/config/getSystemTitle"

2-2(相对于第三种,最后少一个 / )
location /proxy/ {
    proxy_pass http://127.0.0.1:3003/config;
}

代理到URL:"http://localhost:3003/configconfig/getSystemTitle"

情况三:location url末尾是否有斜杠【下面的情况是完整匹配,只要匹配到就该替换替换】

location url末尾有斜杠

3-1 
location /proxy/ {
    proxy_pass http://127.0.0.1:3003/config;
}

代理到URL:"http://127.0.0.1:3003/configconfig/getSystemTitle"

location url末尾无斜杠

3-2 
location /proxy {
    proxy_pass http://127.0.0.1:3003/config;
}

代理到URL:"http://127.0.0.1:3003/config/config/getSystemTitle"

nginx Gzip配置

http {
    gzip  on;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/$
    include /etc/nginx/conf.d/*.conf;
}

nginx转发websocket配置:upgrade

例如:websocket地址:xxxx:port/testt 转发到 http://127.0.0.1:8080/testt

location /testt{
        proxy_pass http://127.0.0.1:8080/testt;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
}

nginx 配置支持URL HTML5 History 模式

try_files $uri /index.html;

server{
        listen 8883;
        server_name localhost;
        location / {
            root    /root/visualize/dist;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
}

单页应用一般都需要配置这个

request_uri 的区别

**request_uri **则指的是请求的整个字符串,包含了后面请求的东西

例如: request_uri: www.baidu.com/document?x=1

try_files指令

try_files 将尝试你列出的文件并设置内部文件指向。

例如:

try_files /app/cache/ $uri @fallback; 
index index.php index.html;

它将检测document_root/app/cache/index.html 和 uri是否存在,如果不存在则内部重定向到 @fallback 。

你也可以使用一个文件或者状态码 (=404)作为最后一个参数,如果是最后一个参数是文件,那么这个文件必须存在。

需要明确的是除最后一个参数外 try_files 本身不会因为任何原因产生内部重定向。

例如nginx不解析PHP文件,以文本代码返回 try_files $uri /cache.php @fallback; 因为这个指令设置内部文件指向到 $document_root/cache.php 并返回,但没有发生内部重定向,因而没有进行location段处理而返回文本 。 (如果加上index指令可以解析PHP是因为index会触发一个内部重定向)

nginx反向代理后获取客户端的真实ip地址:remote_addr

location / {
   proxy_pass http://127.0.0.1:10678;
   proxy_set_header Host $host;
    //加入下面配置
    proxy_set_header X-Real-IP $remote_addr;

    proxy_set_header REMOTE-HOST $remote_addr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

nginx请求转发多机权重与备用配置:weight+backup

配置案例

http{
        upstream web {
             ip_hash; 
             server 192.168.11.123:2009  weight=10;
             server 192.168.11.123:3000  backup;
        }
        server{
                listen 8080;
                localtion / {
                        proxy_pass http://web.com;
                }
        }
}
  • Nginx默认判断失败节点状态以connect refuse和timeout状态为准,不以HTTP错误状态进行判断失败;
  • HTTP只要能返回状态说明该节点还可以正常连接,所以nginx判断其还是存活状态除非添加了proxy_next_upstream指令设置对404、502、503、504、500和time out等错误转到备机处理;
  • ip_hash 配置可以保证某个客户端在本次连接了某个server的时候,会一直访问这个服务端,不断开连接就不会变动;不加这个配置就是每次请求都根据权重随机访问;
  • backup 不能和ip_hash一起使用,backup 参数是指当所有非备机都宕机或者不可用的情况下,就只能使用带backup标准的备机。
  • weight 在不设置的时候默认是1;

nginx限制referer

location ~ /static/ {
    root  /root/zzftest/;
    autoindex on;
    valid_referers none blocked *.nginxcn.com;
    if ($invalid_referer) {
        #rewrite ^/ [www.nginx.cn](http://www.nginx.cn/)
        return 404;
    }
}

ip白黑名单限制

设置IP白名单,allow为允许,deny为拒绝。匹配到之后就不继续往下匹配。

server{
        listen 8888;
        server_name localhost;
        location ^~ /uums {
                # 客户端ip限制
                allow 192.168.78.166;
                allow 127.0.0.1;
                deny all;
                alias /root/zzftest/uums_v3Client/dist;
                 index index.html;
                 try_files $uri $uri/ /index.html;
        }
}

分模块配置多个配置文件共用一个端口的方法:include

如多个不用url 都使用3009端口代理,但是要配置在不同配置文件中实现代理,如我们开发了多个前后端web站点,每次新开发一个web站点就要自动生成一个新的conf文件,来实现nginx转发配置;

目录结构如下: 通过 include /etc/nginx/conf.d/modules/*.conf; 将modules文件夹下的全部配置加载进来

方法一: 配置如下: 外层主配置index.conf

server {
    listen 3099;
    server_name localhost;
    include /etc/nginx/conf.d/modules/*.conf;
}

/modules/test1.conf

location /javaApp1 {
    proxy_pass http://192.168.11.206:9021/;
}

/modules/test2.conf

location /javaApp2 {
    proxy_pass http://192.168.11.206:9022/;
}

方法二: 注意:如果不采用上面的方法,而是写多个配置文件(如下),则需要配置不同的server_name,而且访问的浏览器url要采用server_name (域名的方式)来访问;如果没有域名解析服务器,需要在客户端host文件下配置好各个域名解析的地址

a.conf
server {
    listen 3099;
    server_name www.javaApp1.com;
    location /javaApp1 {
        proxy_pass http://192.168.11.206:9021/;
    }
}

b.conf server { listen 3099; server_name www.javaApp2.com; location /javaApp2 { proxy_pass http://192.168.11.206:9022/; } }

缓存优化

last-Modified 上次修改时间

etag on;           开启Etag,毫秒级别控制    if-Modified-since      if-None-Match过期时间
expires   30d;     过期时间30天,强制缓存,一般不怎么改变的资源,如jQuery.js  
gzip on;
add_header Cache-Control no-cache;     告诉浏览器不缓存资源

也可以利用正则设置相关文件的缓存策略

location ~ \.(gif|jpg|jpeg|png|bmp|ico|icon)${
    root /var/www/images/;
    expires 30d;
}

Request Headers与Response Headers 先对比Etag的值,在对比Last-Modified的值

其他

  1. 如果nginx中只配置一个server域的话,则nginx是不会去进行server_name的匹配的。因为只有一个server域,也就是这有一个虚拟主机,那么肯定是发送到该nginx的 所有请求均是要转发到这一个域的,可以直接就省了不用配置。
  2. 如果一个http域的server域有多个,nginx才会根据$hostname去匹配server_name进而把请求转发到匹配的server域中。此时的匹配会按照匹配的优先级进行,一旦匹配成功则不会再进行匹配。

**nginx中文官方文档与示例:**https://wizardforcel.gitbooks.io/nginx-doc/content/Text/7.5_doorchain.html

本文使用 mdnice 排版