正向代理和反向代理
正向代理:代理浏览器访问服务器
反向代理(nginx):代理服务器处理浏览器的请求,浏览器只知道反向代理服务器的ip地址,不知道真实的服务器的ip地址,可以起到保护服务器不被攻击的作用。
Nginx如何做到高并发下的高效处理?
Nginx采用了Linux的epoll模型
工作模式:mater&worker
客户端发送一个请求到master后,worker获取任务的机制不是直接分配也不是轮询,而是一种争抢的机制,“抢”到任务后再执行任务,即选择目标服务器tomcat等,然后返回结果。
默认的负载均衡策略。每个请求会按时间顺序逐一分配到不同的后端服务器。
特点
在轮询中,如果服务器down掉了,会自动剔除该服务器。
此策略适合多台服务器配置相当时使用。
参数
参数 | 含义 |
---|---|
fail_timeout和max_fails | 在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,针对该服务器的请求都失败了max_fails 次,那么认为该服务器会被认为是停机了 |
fail_time | 服务器会被认为停机的时间长度,默认为10s。 |
backup | 标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里 |
down | 标记服务器永久停机了 |
权重方式,在轮询策略的基础上指定轮询的几率
例子如下:
#动态服务器组 upstream dynamic_zuoyu { server localhost:8080 weight=2; #tomcat 7.0 server localhost:8081; #tomcat 8.0 server localhost:8082 backup; #tomcat 8.5 server localhost:8083 max_fails=3 fail_timeout=20s; #tomcat 9.0 }
在该例子中,weight参数用于指定轮询几率,weight的默认值为1
weight的数值与访问比率成正比,比如Tomcat 7.0被访问的几率为其他服务器的两倍。
注意
权重越高分配到需要处理的请求越多。
此策略可以与least_conn和ip_hash结合使用。
此策略比较适合服务器的硬件配置差别比较大的情况。
指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
注意:
此策略适合有状态服务,比如session。
当有服务器需要剔除,必须手动down掉。
把请求转发给连接数较少
的后端服务器。
此负载均衡策略适合请求处理时间长短不一
造成服务器过载
的情况。
需要安装第三方插件
1、fair
按照服务器端的响应时间
来分配请求,响应时间短的优先分配。
2、url_hash
按访问url的hash结果来分配请求,使相同的url请求定向到同一个后端服务器,这样就可以很好的利用缓存
因为如果同一个url的资源请求到达同一台服务器,第一次到达时将资源缓存,后面到大的请求就可以直接从缓存中拿资源而不用读取磁盘。
Nginx是什么?
Nginx 是一款轻量级的 HTTP 服务器
,采用 事件驱动
的 异步非阻塞
处理方式框架,这让其具有极好的 IO 性能,时常用于服务端的 反向代理
和 负载均衡
动静分离其实就是 Nginx 服务器将接收到的请求分为动态请求和静态请求
。
静态请求直接从 nginx 服务器所设定的根目录路径去取对应的资源,动态请求转发给应用服务器去处理。
nginx动静分离的好处
api接口服务化
:动静分离之后,后端应用更为服务化,只需要通过提供api接口即可,可以为多个功能模块甚至是多个平台的功能使用,可以有效的节省后端人力,更便于功能维护。
前后端开发并行
:前后端只需要关心接口协议即可,各自的开发相互不干扰,并行开发,并行自测,可以有效的提高开发时间,也可以有些的减少联调时间
减轻后端服务器压力,提高静态资源访问速度
:后端不用再将模板渲染为html返回给用户端,且静态服务器可以采用更为专业的技术提高静态资源的访问速度。
正向代理:代理用户访问服务器
反向代理:代理服务器为用户提供服务
反向代理的作用
保障应用服务器的安全(增加一层代理,可以屏蔽危险攻击,更方便的控制权限)
实现负载均衡
实现跨域(号称是最简单的跨域方式)
nginx 就是充当图中的 proxy。左边的3个 client 在请求时向 nginx 获取内容,是感受不到3台 server 存在的。
此时,proxy就充当了3个 server 的反向代理。
反向代理应用十分广泛,CDN 服务就是反向代理经典的应用场景之一。除此之外,反向代理也是实现负载均衡
的基础,很多大公司的架构都应用到了反向代理。
随着业务的不断增长和用户的不断增多,一台服务已经满足不了系统要求了。这个时候就出现了服务器 集群。
在服务器集群中,Nginx 可以将接收到的客户端请求“均匀地”(严格讲并不一定均匀,可以通过设置权重)分配到这个集群中所有的服务器上。这个就叫做负载均衡。
负载均衡的作用
除此之外,Nginx还带有健康检查(服务器心跳检查)
功能,会定期轮询向集群里的所有服务器发送健康检查请求,来检查集群中是否有服务器处于异常状态。
一旦发现某台服务器异常,那么在这以后代理进来的客户端请求都不会被发送到该服务器上(直到健康检查发现该服务器已恢复正常),从而保证客户端访问的稳定性。
在 Nginx 之前,Web 服务器的工作模式大多是:对每一个请求使用单独的进程或者线程处理。这就存在创建进程或线程的成本,还会有进程、线程“上下文切换”的额外开销。如果请求数量很多,CPU 就会在多个进程、线程之间切换时“疲于奔命”,平白地浪费了计算时间。
Nginx 则完全不同,“一反惯例”地没有使用多线程,而是使用了“进程池 + 单线程”的工作模式。
工作模式图示:
Nginx 在启动的时候会预先创建好固定数量的 worker 进程,在之后的运行过程中不会再 fork 出新进程,这就是进程池,而且可以自动把进程“绑定”到独立的 CPU 上,这样就完全消除了进程创建和切换的成本,能够充分利用多核 CPU 的计算能力。
在进程池之上,还有一个“master”进程,专门用来管理进程池。监控进程,自动恢复发生异常的 worker,保持进程池的稳定和服务能力。
Web 服务器从根本上来说是“I/O 密集型”而不是“CPU 密集型”,处理能力的关键在于网络收发而不是 CPU 计算,而网络 I/O 会因为各式各样的原因不得不等待,比如数据还没到达、对端没有响应、缓冲区满发不出去等等。
这种情形就有点像是 HTTP 里的“队头阻塞”。对于一般的单线程来说 CPU 就会“停下来”,造成浪费。而多线程的解决思路有点类似“并发连接”,虽然有的线程可能阻塞,但由于多个线程并行,总体上看阻塞的情况就不会太严重了。
Nginx 里使用的 epoll,就好像是 HTTP/2 里的“多路复用”技术,它把多个 HTTP 请求处理打散成碎片,都“复用”到一个单线程里,不按照先来后到的顺序处理,而是只当连接上真正可读、可写的时候才处理,如果可能发生阻塞就立刻切换出去,处理其他的请求。
通过这种方式,Nginx 就完全消除了 I/O 阻塞,把 CPU 利用得“满满当当”,又因为网络收发并不会消耗太多 CPU 计算能力,也不需要切换进程、线程,所以整体的 CPU 负载是相当低的。
epoll 还有一个特点,大量的连接管理工作都是在操作系统内核里做的,这就减轻了应用程序的负担,所以 Nginx 可以为每个连接只分配很小的内存维护状态,即使有几万、几十万的并发连接也只会消耗几百 M 内存,而其他的 Web 服务器这个时候早就“Memory not enough”了。
有了“进程池”和“I/O 多路复用”,Nginx 是如何处理 HTTP 请求的呢?
Nginx 在内部也采用的是“化整为零”的思路,把整个 Web 服务器分解成了多个“功能模块”,就好像是乐高积木,可以在配置文件里任意拼接搭建,从而实现了高度的灵活性和扩展性。
Nginx 的 HTTP 处理有四大类模块:
Nginx 依赖于磁盘上的静态配置文件,修改后必须重启才能生效,缺乏灵活性;
OpenResty 基于 Nginx,打包了很多有用的模块和库,是一个高性能的 Web 开发平台;
OpenResty 的工作语言是 Lua,它小巧灵活,执行效率高,支持“代码热加载”;
OpenResty 的核心编程范式是“同步非阻塞”,使用协程,不需要异步回调函数;
OpenResty 也使用“阶段式处理”的工作模式,但因为在阶段里执行的都是 Lua 代码,所以非常灵活,配合 Redis 等外部数据库能够实现各种动态配置。