nginx
nginx是一个强大的web server,它支持反向代理,负载均衡,也是很好的静态文件服务器,下面是其多进程模型。
nginx采用多进程模型,单Master多worker,由Master处理外部信号、配置文件的读取及worker的初始化,Master不需要处理网络事件,不负责业务的执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker进程采用单线程、非阻塞的事件模型(Event Loop,事件循环)来实现端口的监听及客户端请求的处理和响应,同时worker还要处理来自Master的信号。由于worker使用单线程处理各种事件,所以一定要保证主循环是非阻塞的,否则会大大降低worker的响应能力。每个worker进程都是从master进程fork过来,所有worker进程在消息到来时会抢互斥锁,抢到互斥锁的那个处理消息,读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。nginx的每个worker进程都是在epoll或kqueue这样的事件模型之上,封装成协程,每个请求都有一个协程进行处理。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,因为不同的worker进程之间处理并发请求时几乎没有同步锁的限制,因此,当Nginx上的进程数与CPU核心数相等时(最好每一个worker进程都绑定特定的CPU核心),进程间切换的代价是最小的。
当nginx处理一个来自客户端的请求时,先根据请求头的host、ip和port来确定由哪个server处理,确定了server之后,再根据请求的uri找到对应的location,这个请求就由这个location处理,更具体一点nginx将一个请求的处理划分为若干个不同阶段(phase),这些阶段按照前后顺序依次执行:
NGX_HTTP_POST_READ_PHASE, //0读取请求phase
NGX_HTTP_SERVER_REWRITE_PHASE,//1这个阶段主要是处理全局的(server block)的rewrite
NGX_HTTP_FIND_CONFIG_PHASE, //2这个阶段主要是通过uri来查找对应的location,然后根据loc_conf设置r的相应变量
NGX_HTTP_REWRITE_PHASE, //3这个主要处理location的rewrite
NGX_HTTP_POST_REWRITE_PHASE, //4这个主要是进行一些校验以及收尾工作,以便于交给后面的模块。
NGX_HTTP_PREACCESS_PHASE, //5比如流控这种access就放在这个phase,也就是说它主要做一些比较粗粒度的access。
NGX_HTTP_ACCESS_PHASE, //6这个比如存取控制,权限验证就放在这个phase,一般来说处理动作是交给下面的模块做的.这个主要是做一些细粒度的access
NGX_HTTP_POST_ACCESS_PHASE, //7一般来说当上面的access模块得到access_code之后就会由这个模块根据access_code来进行操作
NGX_HTTP_TRY_FILES_PHASE, //8try_file模块,就是对应配置文件中的try_files指令,可接收多个路径作为参数,当前一个路径的资源无法找到,则自动查找下一个路径
NGX_HTTP_CONTENT_PHASE, //9内容处理模块
NGX_HTTP_LOG_PHASE //10log模块
负载均衡也是Nginx常用的一个功能,而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。
1、RR
按照轮询(默认)方式进行负载,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。虽然这种方式简便、成本低廉。但缺点是:可靠性低和负载分配不均衡。
2、权重
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
upstream test{
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}
此时8080和8081分别占90%和10%。
3、ip_hash
上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法。
upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}