转载 深刻理解Nginx及使用Nginx实现负载均衡

转载:https://developer.51cto.com/art/202001/609322.htmhtml

 

正向代理是代理客户端,也就是客户端能真正接触到的,好比访问外网时须要使用***软件,在这个软件中用户能够选择链接哪里的服务器。nginx

 

 

前言算法

最近在部署项目时要求实现负载均衡,有趣的是发现网上一搜所有都是如下相似的配置文件服务器

  1. upstream localhost{ 
  2.  server 127.0.0.1:8080 weight=1; 
  3.  server 127.0.0.1:8081 weight=1; 
  4.  } 
  5.  server { 
  6.  listen 80; 
  7.  server_name localhost; 
  8.  location / { 
  9.  proxy_pass http://localhost; 
  10.  index index.html index.htm index.jsp; 
  11.   
  12.  } 
  13.  } 

因此打算来看看Nginx内部原理,这篇博客主要介绍Nginx如何实现反向代理以及在Nginx中负载均衡的参数使用网络

1、正向代理与反向代理session

正向代理是代理客户端,也就是客户端能真正接触到的,好比访问外网时须要使用***软件,在这个软件中用户能够选择链接哪里的服务器。架构

反向代理则是代理服务端,用户感知不到,只是客户端把请求发到服务端的端口时,Nginx监听到了便把该端口的请求转发到不一样的服务器上。就以上面配置文件来说解,当在网址中输入http://localhost:80/时(不加80同样时默认进入80端口,这里为了表示清楚),然后Nginx监听到80端口的请求以后,就会查找对应的location来执行。由上面的配置文件咱们能够看出是将请求转发到了不一样的端口。这是在服务器中执行的,用户不可见。并发

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

2、Nginx内部基本架构异步

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

master进程:主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常状况下),会自动从新启动新的worker进程。

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

深刻理解Nginx及使用Nginx实现负载均衡

因此Nginx基本的架构就以下:

深刻理解Nginx及使用Nginx实现负载均衡

当咱们输入./nginx -s reload,就是来重启nginx,./nginx -s stop,就是来中止nginx的运行,这里面是如何作到的?执行命令时,咱们是启动一个新的nginx进程,而新的nginx进程在解析到reload参数后,就知道咱们的目的是控制nginx来从新加载配置文件了,它会向master进程发送信号。master进程在接到信号后,会先从新加载配置文件,而后再启动新的worker进程,并向全部老的worker进程发送信号,告诉他们能够光荣退休了。新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就再也不接收新的请求,而且在当前进程中的全部未处理完的请求处理完成后,再退出。因此使用上面命令重启Nginx的时候服务是不中断的。

3、Nginx如何处理客户端请求

首先来解释一下上面的架构图:每一个worker进程都是从master进程分支过来的,在master进程里面,先创建好须要监听的socket以后,而后再分支出多个worker进程。全部worker进程的listenfd(socket中listenfd是指客户端链接本机时的fd,是用来和客户端通讯用的)会在新链接到来时变得可读,为保证只有一个进程处理该链接,全部worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该链接。

在Nginx中worker进程之间是平等的,每一个进程,处理请求的机会也是同样的。当Nginx监听80端口时,一个客户端的链接请求过来,每一个进程都有可能处理这个链接,上面说到是每一个worker进程都会去抢注listenfd读事件。当一个worker进程在accept这个链接以后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开链接,这样一个完整的请求就是这样的了。这里须要注意的是一个请求,彻底由worker进程来处理,并且只在一个worker进程中处理。

下面两幅流程图能很好的帮咱们理解

深刻理解Nginx及使用Nginx实现负载均衡
深刻理解Nginx及使用Nginx实现负载均衡

4、Nginx如何处理事件而且实现高并发

Nginx内部采用了异步非阻塞的方式来处理请求,也就是说,Nginx是能够同时处理成千上万个请求的。

异步非阻塞:当一个网络请求过来时,咱们并不依赖于这个请求才能作后续操做,那么这个请求就是异步操做,也就是调用者在没有获得结果以前一样能够执行后续的操做。非阻塞就是当前进程/线程没有获得请求调用的结果时也不会妨碍到进程/线程后续的操做。能够看出异步和非阻塞的对象是不一样的。

5、Nginx负载均衡的算法及参数

round robin(默认):轮询方式,依次将请求分配到后台各个服务器中,适用于后台机器性能一致的状况,若服务器挂掉,能够自动从服务列表中剔除

weight:根据权重来分发请求到不一样服务器中,能够理解为比例分发,性能较高服务器分多点请求,较低的则分少点请求

IP_hash:根据请求者ip的hash值将请求发送到后台服务器中,保证来自同一ip的请求被转发到固定的服务器上,解决session问题

  1. upstream localhost {  
  2. ip_hash;  
  3. server 127.0.0.1:8080;  
  4. server 127.0.0.1:8080;  
  5. }  

上面是最基本的三种算法,咱们还能够经过改变参数来自行配置负载均衡

  1. upstream localhost{  
  2. ip_hash;  
  3. server 127.0.0.1:9090 down;  
  4. server 127.0.0.1:8080 weight=2;  
  5. server 127.0.0.1:6060;  
  6. server 127.0.0.1:7070 backup;  

参数列表以下:

深刻理解Nginx及使用Nginx实现负载均衡