为什么需要网关(nginx)

为什么需要网关
通常后台提供了不同的应用服务,甚至是集群,每种服务每个服务,需要维护不同的请求地址,甚至服务认证、跨域等动作,管理起来比较麻烦。因此,需要一个网关,介于客户端和应用服务之间,所有的外部请求都会先经过网关,网关再把请求分发到目标服务。网关对外提供唯一请求入口,作为对外联系的窗口,易于管理和维护请求。
一、Nginx 概述
Nginx 不仅是一个高性能的Web服务器,还具备访问代理、负载均衡、内容缓存等功能,用于客户端访问流量到后台应用服务器负载均衡和请求转发。其基于模块化的代码架构及可与其它有效集成的可编程特性,使其具有强大的扩展能力。Nginx以资源消耗低、高稳定、高性能的并发处理能力著称。
1.1 Nginx 特性
访问代理:
Nginx 可以通过访问路径、URL 关键字、客户端 IP等多种手段实现访问路由分配。
反向代理:
将接收到的请求再转到后端的目标应用服务器,并把响应数据返回给客户端。支持目前绝大多数的网络协议:HTTP/FastCGI/RPC/UDP/TCP等。
负载均衡:
通过自身的 upstream 模块支持多种负载均衡算法,使后端服务器可以非常方便地进行横向扩展,以应对高并发。
内容缓存:
Nginx支持静态站点和后端分离,可以把静态内容缓存起来,也可以将后端变化不大的响应结果缓存起来,使整体实现了更高速的相应能力。
可扩展性:
可定制的模块化架构方式,更多的语言(C/Perl/JavaScript/Lua)支持开发第三方模块并引入,增强可编程及扩展能力。
1.2 Nginx 进程
首先,进程是CPU管理的运行单元,CPU的单个核心也可以运行多个进程,只不过是交替运行着各个进程,称为时间片,这种方式速度很快,以至于看上去像在同时运行;多核CPU就能同时运行更多的进程。
Nginx是由多个进程运行,一个主进程Master和多个子进程Worker,主进程负责管理子进程,如:重启/重载/创建/销毁等,子进程负责处理具体的请求等业务功能。进程间共享内存数据,更多的进程带来更好的处理能力。
Nginx 进程运行示意图:
1.3 Nginx 重载
Nginx支持配置信息的重载,并以最新的配置内容运行,当Nginx在高速运行的时候,如何做到平稳过渡呢?
相关命令:nginx -s reload
重载过程:
Nginx Master process 负责 fork 出一个新的 Worker process,最新的Worker使用新的配置信息运行,此时,Worker有新旧之分,新 Worker 用新配置运行,旧 Worker 依然用旧配置运行,这时候就销毁一个旧的worker。Master继续 fork 出新的 Worker。。。以同样的方式持续替换旧Worker,直到全部替换完成。整个过程中,Nginx 并没有停止运行,丝滑过渡。
二、安装配置
2.1 编译安装
安装前提:
yum install gcc -y # C语言编译器yum install pcre pcre-devel -y # PCRE Libraryyum install zlib zlib-devel -y # zlib Library
编译安装:
# 进入解压后的目录中 编译安装 [指定用户/组] [--with-追加自带模块名称] ./configure --prefix=/usr/local/nginx [--user=www --group=www] [--with-http_gzip_static_module] make && make install
2.2 启动实例
进入主进程目录:/usr/local/nginx/bin
nginx # 启动nginx -s stop # 停止,立即nginx -s quit # 退出,处理完现有任务后nginx -s reopen # 重启nginx -s reload # 重载配置,交替更新工作进程
docker 运行 nginx 很简单:
拉取镜像:docker pull nginx
启动容器:docker run -d --name=ngx-a -p 80:80 nginx
浏览器打开主机IP显示 NGINX 欢迎页面。
影响 Nginx 的系统关联项
Firewall/UFW 防火墙:端口的开放
SELinux 权限的限制:请求后端的权限
2.3 配置文件结构
nginx 的配置文件默认存于 /etc/nginx/nginx.conf,其中通过 include 引入其它目录子配置文件。
全局块:针对 Nginx 实例的设置,资源及事件的设定。
HTTP:从 Client 到 Nginx 的请求设置,请求过程中要处理的各项配置;
Upstream:代理转发的下个目的地列表,后端服务组地址列表,连接与负载均衡的设定。
Server:从 Nginx 到 Service 的设置,通常对应前后端某种服务或组;限制设定,代理设定,错误机制等。
Location:路由匹配转发通讯,重定向等。
配置模板示例
###### 全局块worker_processes auto; # 工作进程数error_log /var/log/nginx/error.log notice; # 错误级别记录events { worker_connections 1024; # 单个工作进程,可承载的最大连接数}http { ###### MIME 配置
include /etc/nginx/mime.types; # 文件扩展名与文件类型映射表
default_type application/octet-stream; # mime.types 不包含时的默认设置
###### 请求日志配置
log_format log-format-a '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log log-format-a; # 访问日志路径 及引用格式
###### 后端可用服务配置
upstream backend-server-name { server 192.168.1.101:80; server 192.168.1.102:80;
}
server { ###### 请求匹配
listen 80; # 客户端请求的端口
server_name _; # 客户端请求的域名;区分不同服务(可多个空格区分,支持正则)
location / { ###### 重写配置
rewrite ^<规则>$ <目的地> break;
###### 转发到后端配置
proxy_pass http://backend-server-name$request_uri; # 转发到后台服务地址,来自于 upstream 项
proxy_http_version 1.1; # 指明版本(1.1默认为keep-alive长连接,1.0默认为短连接)
proxy_set_header Host $host; # 保持原来的请求域名
proxy_ignore_client_abort on; # 客户端断网时,是否中断对后端的请求
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 从远程客户端IP到服务端的层层代理转发IP,多IP追加空格分隔
###### Cookie 域名/路径
proxy_cookie_domain {backend-domain} {request-domain}; proxy_cookie_path {backend-path} {request-path};
}
###### 指定文件拒绝所有访问
location ~ ^/(\.user.ini|\.ht|\.git|\.svn|\.project|LICENSE|README.md){ deny all;
}
###### 限制的客户端
location \ { deny 172.18.0.101; # 拒绝的ip
allow 172.18.1.10; # 允许的ip
}
###### 客户端缓存配置
location ~* \.(js|css|jpg|svg|gif|png)$ { if (-f $request_filename) { # -f:只能是文件,因为这用-f判断了
expires 30d; # 缓存有效时长 30 天
break;
}
}
###### 防盗链配置
location ~* \.(gif|jpg|png|bmp)$ { # 指定格式禁止的请求来源:google/baidu
valid_referers none blocked *.ttlsa.com server_names ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; # 状态码
#rewrite ^/ http://www.ttlsa.com/403.webp;
}
}
###### (前端) 错误机制
error_page 404 /404.html; # 错误码 转向的 错误页
error_page 500 502 503 504 /50x.html; # 错误码 转向的 错误页
location = /50x.html { # 错误页 指向的 静态页面
root /usr/share/nginx/html;
}
}
}2.4 前后端分离
把前端站点部署到 Nginx:
server { listen 80; server_name xxx.com;
# 前端配置
location / { # 前端站点路径
root /home/vue/dist; index index.html
}
# 后端配置
location /api { proxy_set_header host $HOST; proxy_pass http://192.168.1.101:8081;
}
}2.5 负载均衡模式
在配置项 upstream 中,负责提供可用的服务地址列表,并可指定负载均衡的实现方式。
轮询 Round-Robin:将访问按序依次请求到后端各个服务器上,能确保平均负载
upstream backend-a { server 192.168.1.101:80; server 192.168.1.102:80;
}权重 Weight:按百分比请求到后端服务器上,常用到硬件配置不同的场景
upstream backend-b { server 192.168.1.101:80 weight=3; server 192.168.1.102:80 weight=7;
}最少连接 Least-Connect:处理请求少的后端服务优先接收新请求
upstream backend-c {
least_conn; server 192.168.1.101:80; server 192.168.1.102:80;
}IP-Hash:相同的访问IP落到后端同个服务器上,所以支持会话保持,但不是绝对平均负载
upstream backend-d {
ip_hash; server 192.168.1.101:80; server 192.168.1.102:80;
}第三方的会话保持 sticky_cookie_insert,同时支持负载均衡。
2.6 限流与熔断
限流:通过对并发/请求进行限速来保护系统,防止系统过载瘫痪而不能提供服务;为了更好控制整个系统的负载情况,即使阻止了某些请求,系统继续提供服务。
http_limit_conn:单个IP同时允许的连接限制
http {
# 连接限流定义
# - $binary_remote_addr:限制对象(客户端)
# - zone:限制自定义名称
# - 10:内存中用10兆空间存储连接记录
limit_conn_zone $binary_remote_addr zone={limits-name}:10m;
server { location /search/ {
# 单个IP同时允许建立多少连接(并发限制)
limit_conn {limits-name} 1;
}
}
}http_limit_req:单个IP请求频率的限制;次/每秒;
http { # 请求限流定义
# - $binary_remote_addr:限制对象(客户端)
# - zone:定义限制(策略)名称
# - 10m:用十兆空间记录访问次数
# - rate:每秒10次的请求处理速率
limit_req_zone $binary_remote_addr zone={limits-name}:10m rate=1r/s; # 请求限流定义
# - $server_name:限制对象,对指定服务器请求的限制
limit_req_zone $server_name zone={limits-name}:10m rate=10r/s;
server { location /search/ { # 引用以上定义的限流策略,做以下设定(漏桶方式)
# - burst:最多接收5个排队用户IP,处于等待处理状态(容量)
# - nodelay:超出排队之外的更多请求,拒绝并返回503(溢出)
limit_req zone={limits-name} [burst=5] [nodelay];
}
}
}http_limit_rate:向客户端传输响应的速率限制;字节/每秒/每连接;0不限制
http {
server { location /download/ {
# 带宽限制
limit_rate_after 5m; # 初始限速5m
limit_rate 500k; # 超出后限速500k
}
}
}熔断:当后端服务发生指定频率错误后,Nginx触发熔断措施,不再请求此后端服务,直接返回默认内容到用户端。
upstream http_backend { # 10s内出现3次错误,该服务器将被视为不可用(熔断)
server 192.168.1.101:8080 max_fails=3 fail_timeout=10s; server 192.168.1.102:8080 max_fails=3 fail_timeout=10s;
}当然也有容错机制,Nginx 默认自动转向其它服务再请求,相关配置:proxy_next_upstream
不成文的内存使用计算公式
给 Nginx 预备多大的内存,随着参数的调整而变化,特定缓存排除在外;
预估 Nginx 内存使用计算公式:worker_processes * worker_connections / 1000 = G
三、性能优化
3.1 全局优化
# 工作进程数worker_processes auto; # 建议 CPU核心数|CPU线程数# 最大支持的连接(open-file)数量;最大值受限于 Linux open files (ulimit -n)# 建议公式:worker_rlimit_nofile > worker_processes * worker_connectionsworker_rlimit_nofile 65535;events { use epoll; # 高效的IO多路复用(RedHat6+ 都支持 epoll)
multi_accept on; # 设置一个进程是否同时接受多个网络连接
worker_connections 10240; # 单个工作进程,可承载的最大连接数;}3.2 与客户端之间的优化
http {
###### 零拷贝技术
sendfile on; # 开启不读到(应用本身)内存,直接通过系统发出数据
#sendfile_max_chunk 2m; # 每个进程每次调用传输数量不能大于设定的值,默认0为无上限。
###### 网络传输
# on:累积到一定容量的数据再发,发送次数少
# off:有数据就发,发送次数多,占用网络资源
tcp_nopush on;
###### 长连接;用户端比较分散,keepalive 默认值已经足够,个人不建议重设
###### 响应数据 开启压缩模式
gzip on; gzip_vary on; # 为兼容老浏览器,追加到Header的压缩标注
gzip_proxied any; # 所有代理请求都压缩,也可指定类型
gzip_comp_level 2; # 压缩等级1-9(比例)等级越大 压缩越高 越耗CPU
gzip_min_length 128; # 压缩前提,当返回内容大于指定时再压缩
gzip_types text/css text/xml image/svg+xml; # 指定压缩的文件类型;更多压缩项可参考 mime.types}3.3 与后端服务之间的优化
http { upstream backend_A { # ...
# 长连接;所有请求汇聚到后端服务器,并发时是有必要在此基础上重配 keepalive 的
# 以下 keepalive 需要 http 1.1 版本,并且 header connection close
keepalive 100; # 每个Worker与后端的连接池中,保持指定量的空闲连接数(QPS的10%)
keepalive_time 1h; # 每个长连接的(忙碌+空闲)总时长,超出后强制失效
keepalive_timeout 60s; # 每个长连接,最大空闲时长,超出后自动关闭长连接
keepalive_requests 1000; # 每次长连接支持的 Request 次数,超出后自动关闭
}
server { loc为什么需要网关(nginx)
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



