Nginx负载均衡原理
Nginx负载均衡的几种算法
目前nginx提供3种自带的负载均衡,还有2种常用的第三方策略。
- 安装轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。虽然这种方式简便、成本低,但缺点是:可靠性低和负载分配不均衡。
- 权重:指定轮询几率,weight和访问比例成正比,用于后端服务器性能不均的情况。如下图,8080和8081分别占90%和10%。
- ip_hash:上面2种方式都有一个问题,就是下一个请求来的时候,请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用session保存数据),这个时候,就有一个很大的问题,比如把登录信息保存到了session中,那么跳转到另外一个服务器的时候就需要重新登录了,所以很多时候,我们只需要一个客户只访问一个服务器,那么就需要用到iphash。iphash的每个请求按访问ip的hash结果分配,这个每个访客访问一个后端服务器,可以解决session问题。
- fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配。
- url_hash(第三方):按访问URL的hash结果进行分配请求,使每个URL定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用hash算法。
Nginx处理请求
Nginx在启动时会以daemon形式在后台运行,采用多进程+异步非阻塞IO事件模型来处理各种连接请求。
多进程模型
多进程模型包括一个master进程,多个worker进程,一般worker进程个数是根据服务器CPU核数来决定的。master进程负责管理Nginx本身和其他worker进程。
从上图中可以很明显地看到,4个worker进程的父进程都是master进程,表明worker进程都是从父进程fork出来的,并且父进程的ppid为1,表示其为daemon进程。Master进程的作用是?
读取并验证配置文件nginx.conf;管理worker进程,包括:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
Worker进程的作用是?
处理基本的网络事件,在nginx多进程中,每个worker都是平等的,因此每个进程处理外部请求的机会权重都是一致的。
每一个Worker进程都维护一个线程(避免线程切换),处理连接和请求;注意Worker进程的个数由配置文件决定,一般和CPU个数相关(有利于进程切换),配置几个就有几个Worker进程。
一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
多进程模型的优点
- 对于每个worker进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销。
- 采用独立的进程,可以让worker互相之间不会影响,一个worker退出后,其它worker还在工作,服务不会中断,master进程则很快启动新的worker进程。
异步非阻塞IO事件模型
nginx采用了异步非阻塞的方式来处理请求,也就是说,nginx是可以同时处理成千上万个请求的。
Nginx采用了Linux的epoll模型,epoll模型基于事件驱动机制,它可以监控多个事件是否准备完毕,如果OK,那么放入epoll队列中,这个过程是异步的。worker只需要从epoll队列循环处理即可。
和Java的NIO类似。
Nginx如何做到热部署
所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!(nginx -s reload 重新加载/nginx -t检查配置/nginx -s stop)
通过上文我们已经知道worker进程负责处理具体的请求,那么如果想达到热部署的效果,有两种方法:
- 方案一,修改配置文件nginx.conf后,主进程master负责推送给woker进程更新配置信息,woker进程收到信息后,更新进程内部的线程信息。
- 方案二,修改配置文件nginx.conf后,重新生成新的worker进程,当然会以新的配置进行处理请求,而且新的请求必须都交给新的worker进程,至于老的worker进程,等把那些以前的请求处理完毕后,kill掉即可。
Nginx采用的就是方案二来达到热部署的!
Nginx挂了怎么办?
Nginx既然作为入口网关,很重要,如果出现单点问题,显然是不可接受的。
答案是:Keepalived+Nginx实现高可用。
Keepalived是一个高可用解决方案,主要是用来防止服务器单点发生故障,可以通过和Nginx配合来实现Web服务的高可用。(其实,Keepalived不仅仅可以和Nginx配合,还可以和很多其他服务配合)
Keepalived+Nginx实现高可用的思路:
- 请求不要直接打到Nginx上,应该先通过Keepalived(这就是所谓虚拟IP,VIP)。
- Keepalived应该能监控Nginx的生命状态,提供一个用户自定义的脚本,定期检查Nginx进程状态,进行权重变化,,从而实现Nginx故障切换。