用户您好!请先登录!

Nginx应用部署那点事

Nginx应用部署那点事

什么是 Nginx?

Nginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。

Nginx 极简教程(快速入门)

什么是反向代理?

反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

Nginx 极简教程(快速入门)

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的时候服务是不中断的

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实现负载均衡

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

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

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

回到Nginx中,首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据。具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,再继续。而阻塞调用会进入内核等待,cpu就会让出去给别人用了,对单线程的worker来说,显然不合适,当网络事件越多时,大家都在等待,cpu空闲下来没人用,cpu利用率自然上不去了,更别谈高并发了。

而非阻塞就是,事件没有准备好,马上返回EAGAIN,告诉调用者,事件还没准备好,过会再来。过一会,再来检查一下事件,直到事件准备好了为止,在这期间,Nginx可以处理其他调用者的读写事件。但是虽然不阻塞了,但Nginx得不时地过来检查一下事件的状态,Nginx可以处理更多请求了,但带来的开销也是不小的。所以,才会有了异步非阻塞的事件处理机制,具体到系统调用就是像select/poll/epoll/kqueue这样的系统调用。它们提供了一种机制,让你可以同时监控多个事件,以epoll为例子,当事件没准备好时,放到epoll里面,事件准备好了,Nginx就去读写,当读写返回EAGAIN时,就将它再次加入到epoll里面。这样,只要有事件准备好了,Nginx就可以去处理它,只有当所有事件都没准备好时,才在epoll里面等着。

这样便实现了所谓的并发处理请求,但是线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。

与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换)。更多的并发数,只是会占用更多的内存而已。现在的网络服务器基本都采用这种方式,这也是nginx性能高效的主要原因。

Nginx负载均衡的算法及参数

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

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

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

upstream localhost { 
ip_hash; 
server 127.0.0.1:8080; 
server 127.0.0.1:8080; 
}

上面是最基本的三种算法,我们还可以通过改变参数来自行配置负载均衡

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; 
}

参数列表如下:

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

 

Nginx 安装(以Ubuntu18上apt安装方式为例)

Nginx的软件包在Ubuntu默认软件仓库中可用。 安装非常简单,只需键入以下命令:

sudo apt update
sudo apt install nginx

安装完成后,请检查Nginx服务的状态和版本:

linuxidc@linuxidc:~$ sudo systemctl status nginx
输出:

如何在Ubuntu 18.04上安装Nginx

sudo nginx -v

输出:

nginx version: nginx/1.14.0 (Ubuntu)

配置防火墙

如果您正在运行防火墙,则还需要打开端口80和443。

linuxidc@linuxidc:~$ sudo ufw allow ‘Nginx Full’
防火墙规则已更新
规则已更新(v6)

如何在Ubuntu 18.04上安装Nginx

您可以通过以下方式验证更改:

linuxidc@linuxidc:~$ sudo ufw status

如何在Ubuntu 18.04上安装Nginx

测试安装

在您选择的浏览器中打开http://localhost,您应该能够看到默认的Nginx登录页面,如下所示: 如何在Ubuntu 18.04上安装Nginx

使用systemctl管理Nginx服务

您可以像任何其他systemd单位一样管理Nginx服务。 要停止Nginx服务,请运行:

sudo systemctl stop nginx

要再次启动,请键入:

sudo systemctl start nginx

重新启动Nginx服务:

sudo systemctl restart nginx

在进行一些配置更改后重新加载Nginx服务:

$sudo systemctl reload nginx

如果你想禁用Nginx服务在启动时启动:

$sudo systemctl disable nginx

并重新启用它:

$sudo systemctl enable nginx

另外,如果您想要在服务器上托管多个域,可以查看以下指南:

如何在Ubuntu 18.04上设置Nginx服务器  https://www.linuxidc.com/Linux/2018-05/152258.htm

如果您想用免费的LetsEncrypt SSL证书保护您的网站,可以查看以下指南:

在Ubuntu 18.04上使用Let’s Encrypt保护Nginx  https://www.linuxidc.com/Linux/2018-05/152259.htm

行走的code
行走的code

要发表评论,您必须先登录