【得物技术】前端工程师要知道的Nginx知识

890 阅读5分钟

平常我们在工作之中,遇到的许多问题其实都是与Nginx有关的问题,例如 跨域问题、请求过滤、配置gzip、负载均衡、或者与静态资源服务器有关等等的问题。

虽然nginx一般都由运维配置,我们不会直接配置,但是了解它在我们线上程序中所起到的作用,并且能够知道如何排查问题,也是非常重要的。

那么nginx到底是什么呢?

一、什么是Nginx

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。 截屏2021-04-02 下午5.55.22.png

上图大概描述了Nginx在整个浏览访问中起到的作用,有一点像入口网关。Nginx其实就是一个高性能的反向代理服务器,那么什么是反向代理,什么是正向代理呢?

1. 正向代理

截屏2021-04-02 下午5.55.48.png

由于防火墙的原因,我们不能直接访问www.google.com ,所以我们需要借助vpn来完成这次访问。通过这个例子,我们能发现,所谓的正向代理,代理的是客户端,客户端知道他访问的目标究竟是什么,但对于目标服务端来说,并不知道自己收到的是来自代理的访问还是来自真实客户端的访问。

官方解释如下:

是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

2. 反向代理

截屏2021-04-02 下午5.56.51.png

从图中我们可以看出,我们从外网访问www.baidu.com 的时候,会进行一个转发,代理到内网。因此反向代理其实代理的是服务器端,这一个过程对于客户端来说是透明的。

官方解释如下:

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。

二、Nginx的基本配置

下图是nginx配置文件的基本结构:

截屏2021-04-02 下午5.57.34.png

其中:

  • main:nginx的全局配置,对全局生效
  • events:配置影响nginx服务器或与用户的网络连接
  • http:可以嵌套多个server,配置代理,缓存,日志定义等等功能,还能配置第三方模块的配置。
  • upstream:配置后端服务器的具体地址,与负载均衡息息相关
  • server:配置虚拟主机的相关参数,一个http中可以有多个server
  • location:配置请求的路由,以及各种页面的处理情况

内置变量

截屏2021-04-02 下午5.58.30.png

三、跨域问题

1. 跨域的定义

浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域。

2. Nginx是怎么解决跨域

eg. • 前端server的域名:fast.dewu.com • 后端server的域名:app.dewu.com

如果没有代理,那么在fast.dewu.com对app.dewu.com发起请求一定会产生跨域问题。

如果使Nginx用代理将serve_name设置成fast.dewu.com,然后设置相应的location拦截前端需要跨域的请求,最后将请求代理回app.dewu.com。配置如下:

{ 
    listen 80; 
    server_name fast.dewu.com; 
    location / { 
        proxy_pass app.dewu.com; 
        } 
    }

将这样fast.dewu.com访问nginx的fast.dewu.com属于同源访问,而nginx对服务端转发的请求不会触发浏览器的同源策略。

四、请求过滤

1. 状态码过滤

error_page 500 501 502 503 504 506 /50x.html; 
location = /50x.html { 
  #将跟路径改编为存放html的路径。 
  root /root/static/html; 
}
 

50x就是错误状态码的显示页面,后面是存放具体html的地址。

2. 根据URL名称过滤

location / {
    rewrite  ^.*$ /index.html  redirect;
}

rewrite的指令是这样的:

rewrite regex replacement [flag];

这里使用了正则来匹配请求的url,如果匹配成功,则使用replacement来更改url。最后的redirect表示返回302临时重定向。

所以这里表示的是精准匹配URL,不匹配的URL全部重定向到主页。

3. 请求类型过滤

if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
        return 403;
    }

五、配置gzip

1. 什么是gzip

gzip是GNUzip的缩写,最早用于UNIX系统的文件压缩。HTTP协议上的gzip编码是一种用来改进web应用程序性能的技术,web服务器和客户端(浏览器)必须共同支持gzip。目前主流的浏览器,Chrome,firefox,IE等都支持该协议。常见的服务器如Apache,Nginx,IIS同样支持gzip。

gzip压缩比率在3到10倍左右,可以大大节省服务器的网络带宽。而在实际应用中,并不是对所有文件进行压缩,通常只是压缩静态文件。

截屏2021-04-02 下午6.02.16.png

2. 开启gzip的表现

请求头 截屏2021-04-02 下午6.01.55.png 响应头 截屏2021-04-02 下午6.02.39.png

3. nginx配置

server{ 
gzip on; # 用于开启或 关闭gzip模块 
gzip_buffers 32 4K; # 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 
gzip_comp_level 6; # 压缩级别,1-10,数字越大压缩的越好,压缩级别越高压缩率越大,压缩时间越长。
gzip_min_length 100; # 设置允许压缩的页面最小字节数,页面字节数从相应消息头的Content-length中进行获取。
 
gzip_types application/javascript text/css text/xml; gzip_disable "MSIE [1-6]\."; # IE6对Gzip不友好,对Gzip(可以通过该指令对一些特定的User-Agent不使用压缩功能) 
gzip_proxied on: # 用于设置启用或禁用从代理服务器上收到相应内容gzip压缩。 
gzip_http_version 1.1; # 识别HTTP协议版本,其值可以是 1.1 或 1.0 
gzip_proxied : off; # 用于设置启用或禁用从代理服务器上收到相应内容gzip压缩。
gzip_vary on; # 用于在响应消息头中添加Vary:Accept-Encoding,使代理服务器根据请求头中的Accept-Encoding识别是否启用gzip压缩
}

六、负载均衡

1. 什么是负载均衡

负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。

一个没有负载均衡的 web 架构类似下面这样: 截屏2021-04-02 下午6.03.30.png

在这里用户是直连到 web 服务器,如果这个服务器宕机了,那么用户自然也就没办法访问了。另外,如果同时有很多用户试图访问服务器,超过了其能处理的极限,就会出现加载速度缓慢或根本无法连接的情况。

而通过在后端引入一个负载均衡器和至少一个额外的 web 服务器,可以缓解这个故障。通常情况下,所有的后端服务器会保证提供相同的内容,以便用户无论哪个服务器响应,都能收到一致的内容。

截屏2021-04-02 下午6.03.53.png

2. nginx如何实现负载均衡

Upstream指定后端服务器地址列表

upstream balanceServer {
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

在server中拦截响应请求,并将请求转发到Upstream中配置的服务器列表。

server { 
      server_name fe.server.com; 
      listen 80; 
      location /api { 
          proxy_pass http://balanceServer; 
      }
    }

3. 负载均衡的策略

(1)轮询策略(默认)

将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。 代码如上。

截屏2021-04-02 下午6.04.54.png

(2) 最小连接数策略

将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。

upstream balanceServer { 
  least_conn; 
  server 10.1.22.33:12345; 
  server 10.1.22.34:12345; 
  server 10.1.22.35:12345; 
  }

截屏2021-04-02 下午6.05.28.png

(3) 权重策略

指定不同ip的权重,权重与访问比成正相关,权重越高,访问越大,适用于不同性能的机器。

upstream balanceServer {
    server 192.168.0.1 weight=2;
    server 192.168.0.2 weight=8;
}

(4) 客户端ip绑定 ip_hash

来自同一个ip的请求永远只分配一台服务器,有效解决了动态网页存在的session共享问题。

upstream balanceServer {
    ip_hash;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

(5) 最快响应时间策略 fair(第三方)

会将请求优先分配给相应最快的服务器,这种方式需要依赖到第三方插件 nginx-upstream-fair

upstream balanceServer {
    fair;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

(6) url_hash(第三方)

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

upstream balanceServer { 
  hash $request_uri; 
  server 192.168.244.1:8080; 
  server 192.168.244.2:8080; 
  server 192.168.244.3:8080; 
  server 192.168.244.4:8080; 
  }

4. 健康检查

Nginx 自带 ngx_http_upstream_module(健康检测模块)本质上服务器心跳的检查,通过定期轮询向集群里的服务器发送健康检查请求,来检查集群中是否有服务器处于异常状态。

如果检测出其中某台服务器异常,那么在通过客户端请求nginx反向代理进来的都不会被发送到该服务器上(直至下次轮训健康检查正常)。

upstream balanceServer{ 
  server 192.168.0.1 max_fails=1 fail_timeout=40s; 
  server 192.168.0.2 max_fails=1 fail_timeout=40s; 
  } 
  
server {  
  listen 80; 
  server_name localhost; 
  location / { 
    proxy_pass http://balanceServer; 
  } 
}

涉及两个配置: fail_timeout : 设定服务器被认为不可用的时间段以及统计失败尝试次数的时间段,默认为10s max_fails : 设定Nginx与服务器通信的尝试失败的次数,默认为:1次。

七、静态资源服务器

location ~* \.(png|gif|jpg|jpeg)$ { 
  root  /root/static/; 
  autoindex on; 
  access_log off; 
  expires 10h;# 设置过期时间为10小时 
 }

匹配以png|gif|jpg|jpeg为结尾的请求,并将请求转发到本地路径,root中指定的路径即nginx本地路径。同时也可以进行一些缓存的设置。

八、访问权限控制

可以配置 nginx 白名单,规定哪些ip可以访问服务器。

location / {
        allow  192.168.0.1;  # 允许该ip访问
        deny   all;  # 禁止所有
    }

文|衠灵

关注得物技术,携手走向技术的云端