平常我们在工作之中,遇到的许多问题其实都是与Nginx有关的问题,例如 跨域问题、请求过滤、配置gzip、负载均衡、或者与静态资源服务器有关等等的问题。
虽然nginx一般都由运维配置,我们不会直接配置,但是了解它在我们线上程序中所起到的作用,并且能够知道如何排查问题,也是非常重要的。
那么nginx到底是什么呢?
一、什么是Nginx
Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。
上图大概描述了Nginx在整个浏览访问中起到的作用,有一点像入口网关。Nginx其实就是一个高性能的反向代理服务器,那么什么是反向代理,什么是正向代理呢?
1. 正向代理
由于防火墙的原因,我们不能直接访问www.google.com ,所以我们需要借助来完成这次访问。通过这个例子,我们能发现,所谓的正向代理,代理的是客户端,客户端知道他访问的目标究竟是什么,但对于目标服务端来说,并不知道自己收到的是来自代理的访问还是来自真实客户端的访问。
官方解释如下:
是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。
2. 反向代理
从图中我们可以看出,我们从外网访问www.baidu.com 的时候,会进行一个转发,代理到内网。因此反向代理其实代理的是服务器端,这一个过程对于客户端来说是透明的。
官方解释如下:
反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。
二、Nginx的基本配置
下图是nginx配置文件的基本结构:
其中:
- main:nginx的全局配置,对全局生效
- events:配置影响nginx服务器或与用户的网络连接
- http:可以嵌套多个server,配置代理,缓存,日志定义等等功能,还能配置第三方模块的配置。
- upstream:配置后端服务器的具体地址,与负载均衡息息相关
- server:配置虚拟主机的相关参数,一个http中可以有多个server
- location:配置请求的路由,以及各种页面的处理情况
内置变量
三、跨域问题
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倍左右,可以大大节省服务器的网络带宽。而在实际应用中,并不是对所有文件进行压缩,通常只是压缩静态文件。
2. 开启gzip的表现
请求头
响应头
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 架构类似下面这样:
在这里用户是直连到 web 服务器,如果这个服务器宕机了,那么用户自然也就没办法访问了。另外,如果同时有很多用户试图访问服务器,超过了其能处理的极限,就会出现加载速度缓慢或根本无法连接的情况。
而通过在后端引入一个负载均衡器和至少一个额外的 web 服务器,可以缓解这个故障。通常情况下,所有的后端服务器会保证提供相同的内容,以便用户无论哪个服务器响应,都能收到一致的内容。
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)轮询策略(默认)
将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
代码如上。
(2) 最小连接数策略
将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
upstream balanceServer {
least_conn;
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
(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; # 禁止所有
}
文|衠灵
关注得物技术,携手走向技术的云端