文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢个人文章,欢迎关注个人微信公众号。nginx
以前其实写过一篇文章具体介绍过:最基础的Nginx教学,当时有提到过Nginx有一个重要的功能:负载均衡。因此这篇文章主要讲讲Nginx如何实现反向代理以及在Nginx中负载均衡的参数使用。算法
1、代理segmentfault
正向代理后端
正向代理也是你们最常接触的到的代理模式,那究竟什么是正向代理呢?咱们都知道Google在国内是没法正常访问的,可是某些时候咱们因为技术问题须要去访问Google时,咱们会先找到一个能够访问Google的代理服务器,咱们将请求发送到代理服务器,代理服务器去访问Google,而后将访问到的数据返回给咱们,这样的过程就是正向代理。缓存
正向代理的特色安全
正向代理最大的特色是客户端须要明确知道要访问的服务器地址,Google服务器只清楚请求来自哪一个代理服务器,而不清楚来自哪一个具体的客户端,正向代理能够隐藏真实客户端的具体信息。服务器
客户端必须设置正向代理服务器,并且须要知道正向代理服务器的IP地址以及代理程序的端口。一句话来归纳就是正向代理代理的是客户端,是一个位于客户端和Google服务器之间的服务器,为了从Google服务器取得数据,客户端向代理服务器发送一个请求并指定目标(Google服务器),而后代理向原始服务器转交请求并将得到的数据返回给客户端。微信
正向代理的使用:网络
反向代理多线程
说完了什么是正向代理,咱们接下来看看什么叫作反向代理,若是咱们网站每日访问量达到某个上限,单个服务器远远不能符合咱们平常需求,这时候咱们首先会想到分布式部署。经过部署多台服务器来解决访问人数限制的问题,而后咱们功能其实大部分都是经过Nginx反向代理来实现的。咱们能够看下图:
反向代理的特色
咱们能够清楚的看到,多个客户端给服务器发送的请求,Nginx服务器接收到请求之后,按照必定的规则转发到不一样的服务器进行业务逻辑处理。此时请求来源于哪一个客户端是肯定的,可是请求由哪台服务器处理的并不明确,Nginx扮演的就是一个反向代理角色。能够这样来理解,反向代理对外都是透明的,访问者并不知道本身访问的是一个代理。反向代理代理的是服务端,主要用于服务器集群分布式部署的状况下,反向代理隐藏了服务器的信息。
反向代理的使用:
正向代理与反向代理区别
服务端中咱们最常使用的反向代理的工具就是Nginx。
2、基本架构
Nginx在启动后以daemon的方式在后台运行,会有一个master进程和多个worker进程:
master进程:主要用来管理worker进程,包含:
worker进程:处理基本的网络事件了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求只能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是能够设置的,通常咱们会设置与机器cpu核数一致,或者直接设置参数worker_processes auto;
Nginx基本架构以下:
咱们能够输入nginx -s reload来重启Nginx,nginx -s stop来中止Nginx的运行,执行这些命令时其实会启动一个新的Nginx进程,而新的Nginx进程在解析到reload参数后,其实就能够知道用户执行这个命令是控制Nginx从新加载配置文件,因而向master进程发送信号。master进程接到信号会先从新加载配置文件,而后启动新的worker进程并向全部旧worker进程发送信号提示老进程能够中止运行了。新的worker启动成功后就开始接收新的请求,而旧worker在收到来自master的信号后中止接收新的请求,在未处理完的请求处理完成后进程就会退出。因此说使用nginx -s reload命令重启Nginx的时候服务是不中断的。
3、Nginx处理客户端请求方式
刚才有讲到过每一个worker进程都是从master进程分支的,因此在master进程里面须要先创建好须要监听的socket而后再分支出多个worker进程。全部worker进程listenfd事件会在新链接时变成可读,为保证只有一个进程处理该链接,因此须要设置互斥锁,全部worker进程须要抢互斥锁,抢到互斥锁的work进程注册listenfd读事件,在listenfd读事件里调用accept接受该链接。当Nginx监听80端口时,一个客户端的链接请求过来的时候,每一个worker进程都会去抢互斥锁注册listenfd读事件。当一个worker进程在accept这个链接以后,就开始处理请求获取数据,再将数据返回给客户端,而后断开链接,到这里一个请求结束。
一个请求,彻底由worker进程来处理,并且只在一个worker进程中处理。
我下面贴一个简单的配置:
server {
listen 80;server_name aaa.com www.aaa.com;}
server {
listen 80;server_name aaa.cn www.aaa.cn;}
server {
listen 80;server_name aaa.org www.aaa.org;}
当接收到客户端http请求,Nginx根据请求头的Host字段决定请求应该由哪一台服务器处理,若是Host字段的值没有匹配的服务器或者请求中没有Host字段,Nginx会将请求路由至这个端口的默认服务器。没有显示配置默认服务器,则默认服务器则为第一个配置。固然咱们还可使用default_server参数指定默认服务器。
server {
listen 80 default_server; server_name aaa.com www.aaa.com;
}
这里须要注意一下:配置默认服务器是监听端口号,而不是服务器名称。
4、Nginx实现高并发
Nginx内部采用了异步非阻塞的方式处理请求,使用了epoll和大量的底层代码优化。能够同时处理成千上万个请求的。
异步非阻塞:每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,好比向后端服务器转发request,并等待请求返回。这个处理的worke会在发送完请求后注册一个事件:“若是upstream返回了,再进行执行接下来的工做”。此时,若是再有request 进来,他就能够很快再按这种方式处理。而一旦后端服务器返回了,就会触发这个事件,worker进程会来接手request接着往下执行。
而Nginx采用一个master进程,多个woker进程的模式。master进程主要负责收集、分发请求。每当一个请求过来时,master就拉起一个worker进程负责处理这个请求。同时master进程也负责监控woker的状态,保证高可靠性,woker进程通常设置为跟cpu核心数一致。Nginx的woker进程在同一时间能够处理的请求数只受内存限制,能够处理多个请求。Nginx 的异步非阻塞工做方式能够把当中的进程空闲等待时间利用起来,所以表现为少数几个进程就解决了大量的并发问题。
Nginx中以epoll为例子,当事件没准备好时,放到epoll里面,事件准备好了,Nginx就去读写,当读写返回EAGAIN时,就将它再次加入到epoll里面。这样,只要有事件准备好了,Nginx就能够去处理它,只有当全部事件都没准备好时,才在epoll里面等着。这样便实现了所谓的并发处理请求,可是线程只有一个,因此同时能处理的请求固然只有一个了,只是在请求间进行不断地切换而已。
Nginx单线程机制与多线程相比优点:
5、Nginx负载均衡的算法及参数
上面是最基本的4种算法,咱们还能够经过改变参数来自行配置负载均衡:
upstream localhost{
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
欢迎关注个人我的公众号:程序猿周先森