渐进深刻理解Nginx

文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢个人文章,欢迎关注个人微信公众号。
filenginx

以前其实写过一篇文章具体介绍过:最基础的Nginx教学,当时有提到过Nginx有一个重要的功能:负载均衡。因此这篇文章主要讲讲Nginx如何实现反向代理以及在Nginx中负载均衡的参数使用。算法

1、代理segmentfault

正向代理后端

正向代理也是你们最常接触的到的代理模式,那究竟什么是正向代理呢?咱们都知道Google在国内是没法正常访问的,可是某些时候咱们因为技术问题须要去访问Google时,咱们会先找到一个能够访问Google的代理服务器,咱们将请求发送到代理服务器,代理服务器去访问Google,而后将访问到的数据返回给咱们,这样的过程就是正向代理。缓存

正向代理的特色安全

正向代理最大的特色是客户端须要明确知道要访问的服务器地址,Google服务器只清楚请求来自哪一个代理服务器,而不清楚来自哪一个具体的客户端,正向代理能够隐藏真实客户端的具体信息。服务器

file

客户端必须设置正向代理服务器,并且须要知道正向代理服务器的IP地址以及代理程序的端口。一句话来归纳就是正向代理代理的是客户端,是一个位于客户端和Google服务器之间的服务器,为了从Google服务器取得数据,客户端向代理服务器发送一个请求并指定目标(Google服务器),而后代理向原始服务器转交请求并将得到的数据返回给客户端。微信

正向代理的使用:网络

  • 访问国外没法访问的网站
  • 作缓存,加速访问资源
  • 对客户端访问受权,上网进行认证
  • 代理能够记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理多线程

说完了什么是正向代理,咱们接下来看看什么叫作反向代理,若是咱们网站每日访问量达到某个上限,单个服务器远远不能符合咱们平常需求,这时候咱们首先会想到分布式部署。经过部署多台服务器来解决访问人数限制的问题,而后咱们功能其实大部分都是经过Nginx反向代理来实现的。咱们能够看下图:
file

反向代理的特色

咱们能够清楚的看到,多个客户端给服务器发送的请求,Nginx服务器接收到请求之后,按照必定的规则转发到不一样的服务器进行业务逻辑处理。此时请求来源于哪一个客户端是肯定的,可是请求由哪台服务器处理的并不明确,Nginx扮演的就是一个反向代理角色。能够这样来理解,反向代理对外都是透明的,访问者并不知道本身访问的是一个代理。反向代理代理的是服务端,主要用于服务器集群分布式部署的状况下,反向代理隐藏了服务器的信息。

反向代理的使用:

  • 保证内网的安全,一般将反向代理做为公网访问地址,Web服务器是内网
  • 负载均衡,经过反向代理服务器来优化网站的负载

正向代理与反向代理区别
file

  • 在正向代理中,隐藏了请求来源的客户端信息;
  • 在反向代理中,隐藏了请求具体处理的服务端信息;

服务端中咱们最常使用的反向代理的工具就是Nginx。

2、基本架构

Nginx在启动后以daemon的方式在后台运行,会有一个master进程和多个worker进程:

  1. Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
  2. 接收来自外界的信号,向各worker进程发送信号,每一个进程都有可能来处理这个链接。
  3. master 进程能监控 worker 进程的运行状态,当 worker 进程退出后(异常状况下),会自动启动新的 worker 进程。

master进程:主要用来管理worker进程,包含:

  1. 接收来自外界的信号
  2. 向各worker进程发送信号
  3. 监控worker进程的运行状态
  4. 当worker进程异常退出后,会自动从新启动新的worker进程。

worker进程:处理基本的网络事件了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求只能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是能够设置的,通常咱们会设置与机器cpu核数一致,或者直接设置参数worker_processes auto;

Nginx基本架构以下:
file

咱们能够输入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负载均衡的算法及参数

  • weight轮询(默认):接收到的请求按照请求顺序逐一分配到不一样的后端服务器,若是在使用过程当中,某一台服务器宕机,Nginx会自动将该服务器剔除出队列,请求受理状况不会受到任何影响。这种方式下,能够给不一样的后端服务器设置一个权重值,权重数据越大,服务器被分配到请求的概率越大。
  • ip_hash:每一个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器。
  • fair:智能调整调度算法,动态的根据后端服务器的请求响应时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的几率高,响应时间长处理效率低的服务器分配到的请求少。
  • url_hash:按照访问的url的hash结果分配请求,每一个请求的url会指向后端固定的某个服务器,能够在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;
}
  • down表示当前的服务器中止参与负载。
  • weight默认为1,weight越大,负载的权重就越大。
  • backup表示其它全部的非backup机器down或者忙的时候,请求backup机器。因此这台机器压力会最轻。

file

欢迎关注个人我的公众号:程序猿周先森
file

相关文章
相关标签/搜索