全栈前端的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则是最上层目录的定义。
注意:
- 使用alias时,目录名后面一定要加"/"。
- alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
- 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的值
其他
- 如果nginx中只配置一个server域的话,则nginx是不会去进行server_name的匹配的。因为只有一个server域,也就是这有一个虚拟主机,那么肯定是发送到该nginx的 所有请求均是要转发到这一个域的,可以直接就省了不用配置。
- 如果一个http域的server域有多个,nginx才会根据$hostname去匹配server_name进而把请求转发到匹配的server域中。此时的匹配会按照匹配的优先级进行,一旦匹配成功则不会再进行匹配。
**nginx中文官方文档与示例:**https://wizardforcel.gitbooks.io/nginx-doc/content/Text/7.5_doorchain.html
本文使用 mdnice 排版