大家好,今天小编关注到一个比较有意思的话题,就是关于nginx在网络系统中处于什么位置的问题,于是小编就整理了2个相关介绍nginx在网络系统中处于什么位置的解答,让我们一起看看吧。
深入浅出Nginx,如何做到高并发下的高效处理?如何做到热部署?
01前言
Nginx("engine x")是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。
在高连接并发的情况下,Nginx是Apache服务器不错的替代品。由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。
上图简单展示了Nginx的部署,Nginx类似网关。
02正向代理与反向代理
正向代理与反向代理有什么区别昵?我们就不废话先,直接上图
这两图这么一整,估计也很难理解清楚那个是正向代理,那个是反向代理。那我现在详细解释一下吧。
正向代理形如1图,我们在aws上申请首次注册送12月的服务器,然后它就是我们的VPN了,然后我们通过它就可以访问YouTube了。不知道大伙能不能明白,正向代理是我们客户端发起的,客户端做出调整。
反向代理形如2图,服务器A,服务器B,服务C部署在内网,我们通过Nginx暴露一个外网地址,小伙伴们就可以访问我们了。
这么讲不知道能不能解释清楚,大伙可以继续看一下下面这个比喻:
正向代理:客户端 <一> 代理 一>服务端
正向代理简单地打个租房的比方:
A(客户端)想租C(服务端)的房子,但是A(客户端)并不认识C(服务端)租不到。B(代理)认识C(服务端)能租这个房子所以你找了B(代理)帮忙租到这个房子。
这个过程中C(服务端)不认识A(客户端)只认识B(代理)C(服务端)并不知道A(客户端)租了房子,只知道房子租给了B(代理)。
反向代理:客户端 一>代理 <一> 服务端
反向代理也用一个租房的例子:
A(客户端)想租一个房子,B(代理)就把这个房子租给了他。这时候实际上C(服务端)才是房东。B(代理)是中介把这个房子租给了A(客户端)。
这个过程中A(客户端)并不知道这个房子到底谁才是房东。
03Master-Worker模式
启动Nginx后,其实就是在80端口启动了Socket服务进行监听,如图所示,Nginx涉及Master进程和Worker进程。
1--进程数,建议设置和CPU个数一样或2倍
2--日志级别,默认error级别
3--Nginx 启动后的pid 存放位置
4--配置每个进程的连接数,总的连接数= worker_processes * worker_connections根据物理内存大小来配置,默认1024
Master进程的作用是?
读取并验证配置文件nginx.conf;管理worker进程;
Worker进程的作用是?
每一个Worker进程都维护一个线程(避免线程切换),处理连接和请求;注意Worker进程的个数由配置文件决定,一般和CPU个数相关(有利于进程切换),配置几个就有几个Worker进程。
由图1可以看到,我这边配了两个worker_processes,所以有两个worker进程。
04如何做到高并发下的高效处理?
上文已经提及Nginx的worker进程个数与CPU绑定、worker进程内部包含一个线程高效回环处理请求,这的确有助于效率,但这是不够的。
作为专业的程序员,我们可以开一下脑洞:BIO/NIO/AIO、异步/同步、阻塞/非阻塞...
要同时处理那么多的请求,要知道,有的请求需要发生IO,可能需要很长时间,如果等着它,就会拖慢worker的处理速度。
Nginx采用了Linux的epoll模型,epoll模型基于事件驱动机制,它可以监控多个事件是否准备完毕,如果OK,那么放入epoll队列中,这个过程是异步的。worker只需要从epoll队列循环处理即可。
05如何做到热部署?
所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!(nginx -s reload 重新加载|nginx -t检查配置|nginx -s stop 停止nginx)
通过上文我们已经知道worker进程负责处理具体的请求,那么如果想达到热部署的效果,可以想象:
方案一:
修改配置文件nginx.conf后,主进程master负责推送给woker进程更新配置信息,woker进程收到信息后,更新进程内部的线程信息。(有点valatile的味道)
方案二:
修改配置文件nginx.conf后,重新生成新的worker进程,当然会以新的配置进行处理请求,而且新的请求必须都交给新的worker进程,至于老的worker进程,等把那些以前的请求处理完毕后,kill掉即可。
Nginx采用的就是方案二来达到热部署的!
模拟一个例子:
首先在本地模拟一个线上需要升级 Nginx 的环境,假设旧版本为 nginx-1.0.15,需要升级到 nginx-1.16.0。
开始之前,先牢记一下以下几个命令:
-HUP 平滑启动(相当于reload)
-USR2 平滑升级可执行程序,主要用在版本升级
-WINCH 从容关闭工作进程
-USR1 重新打开日志文件,主要用在日志切割(相当于reopen)
配置旧版本
# 下载 nginx-1.0.15
wget http://nginx.org/download/nginx-1.0.15.tar.gz
# 解压压缩包
tar -zxf nginx-1.0.15.tar.gz
# 进入解压后的目录
cd nginx-1.0.15
# 配置 nginx
./configure --prefix=/home/nginx
# 编译安装
make && make install
# 运行 nginx
sudo /home/nginx/sbin/nginx
此时访问服务器地址应该可以看到 nginx 的欢迎页面了。
获得新版本二进制
# 下载 nginx-1.16.0
wget http://nginx.org/download/nginx-1.16.0.tar.gz
# 解压压缩包
tar -zxf nginx-1.16.0
# 进入解压后的目录
cd nginx-1.16.0/
# 配置 nginx
./configure --prefix=/home/nginx
# 只编译不需要安装
make
在编译后的 objs 目录中,可以看到二进制文件 nginx。
热部署
经过以上步骤,我们实现了一个正在运行的旧版本 nginx 和编译完成的新版本 nginx 二进制执行文件。
热部署的流程是:
备份旧的 nginx 可执行文件
新的 nginx 可执行文件直接替换旧的(此时旧的 nginx 进程还在运行)
向 nginx master 进程发送热部署信号,新的 nginx 进程启动,旧的 worker 不再就收请求。
关闭旧的 worker 进程,完成热部署。
# 备份
cp /home/nginx/sbin/nginx /home/nginx/sbin/nginx.old
# 替换
cp -f objs/nginx /home/nginx/sbin/nginx
# 查看 master pid
ps -ef | grep nginx
root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx
nobody 23715 23712 0 21:21 ? 00:00:00 nginx: worker process
# 发送热部署信号,这里 master pid 替换为自己查询到的
kill -USR2 23712
# 查看当前 nginx 进程情况,27522 就是新的 master 进程
ps -ef | grep nginx
root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx
nobody 23715 23712 0 21:21 ? 00:00:00 nginx: worker process
root 27522 23712 0 21:41 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx
nobody 27524 27522 0 21:41 ? 00:00:00 nginx: worker process
# 关闭旧的 worker
kill -WINCH 23712
# 再次查看进程,可以发现旧的worker进程关闭了
ps -ef | grep nginx
root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx
root 27522 23712 0 21:41 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx
nobody 27524 27522 0 21:41 ? 00:00:00 nginx: worker process
保留旧的 master 进程是为了在新的版本存在问题时,可以快速回退到原版本。如果发现问题要紧急回滚呢?
cp -f nginx.old nginx
# 拉起旧版本的worker进程(-HUP 相当于 -s reload)
kill -HUP old_master_pid
# 让新版本的 worker 不再接受请求
kill -USR2 new_master_pid
# 关闭新版本的 woker 进程
kill -WINCH new_master_pid
如果确认无误要退出老版本的 nginx,可以执行命令
kill -QUIT old_master_pid
域名、主机服务器、ip、网卡与网站之间的关系是什么?
首先,你需要了解三个基础网络知识。
1 DNS
1.1 DNS简单说就是你给它一个域名,它解析一个IP给你。但是实际上情况不是这么简单的。
客户端发起一个DNS查询请求,提交一个完整主机名(例如www.abc.com)到设置的DNS服务器上,DNS服务器如果查询到相关记录,则返回这个记录。对于IPv4,记录分为A记录或者CNAME。A记录表示是一个IPv4的地址,CNAME表示为另外一个主机名(例如server1.realserver.com)。A记录允许同名存在,多个不同的IP被对应到同一个主机名上,也允许使用根记录,本例中即为abc.com,不带任何前缀;CNAME不允许同名存在,不允许根记录,也不允许与A记录同名。如果客户端得到的返回是一个CNAME,则会重新再来一次DNS查询去解析这个CNAME的IP。对于这个CNAME的查询,可能返回另外的CNAME,则这个过程会很长,直至解析出A记录。
1.2如果DNS服务器上没有查询到相关记录,则会询问上一层的DNS服务器。如果上一层服务器解析出结果,则它在返回给用户结果时,顺便自己缓存一份。缓存的时间由域名的TTL决定。
1.3每个域名首先要注册在跟DNS上NS服务器名称。当一个区域中最顶层的DNS也没有用户查询的主机名记录时,则会首先向INTERNET跟DNS获取这个NS服务器名称,并尝试向这个NS服务器发起查询请求。NS服务器必须响应并响应这个查询。如果DNS跟服务器无法被连接到、NS无法被找到、无法被连接到或者NS服务器无法解析,则本主机名最终解析失败。
1.4 DNS如果返回多条A记录时,会生成一个有序集合。这个排序根据历史查询散列,并根据访问者的IP所在区域优化。客户端拿到的集合中的第一条IP通常为一个优化后的地址,但其他地址依旧可作为备选使用。
1.5 DNS服务器通常不归主机管理商所有,并且由于需要快速响应,在查询的时候是无法判断主机状态和负载的。但一些较大的机构,会自己拥有一个重新设计的DNS服务器,考虑到这些信息。而对于这种情况,外部公网的DNS只能解析出一个CNAME,并交由这个DNS来进行后续解析(这个DNS被注册为这个CNAME对应的NS)。这种设计下的DNS通常被认为是NLB(网络负载均衡)设计的一部份。
1.6由于1.2提及的代理查询以及TTL的机制,DNS其实并不能良好的实现服务器的轮询负载均衡,但是可以实现区域优化查询,即对某个特定区域尽量返回其区域内的IP结果。
2 HTTP头
在发起HTTP请求时,客户端会同时提交要访问的文件(一般在GET命令后)以及主机名(HOST字段),对方服务器会根据这个HOST来确定它要访问的域名。所以一个主机在一个IP上并行存在多个不同的主机地址。
3 NLB
通常的NLB有三种解决办法。
3.1本地DNS加速,如1.5所述的方法。
3.2 CDN(内容分发网络)。CDN可以被看做是一个独立的HTTP代理网络。使用CDN的时候,DNS应把域名解析到某个CDN的全球IP群上。CDN服务器得到HTTP请求后,会在转发原真实服务器的数据时,本地缓存一份。甚至可以实现数据的预推送。因此CDN非常适合于静态数据的全球化缓存。例如微软发布补丁、苹果发布新产品、Wordpress、Amazon网站的图片缓存都是使用了CDN技术。
3.3虚拟IP地址。通常情况下,一个IP不应该被设置到超过一个设备上,因为超过这个设置后,上层的路由器就不知道如何转发这个包了。但是,如果路由器经过了设置(例如BGP协议或者专门设计的路由软件等),是可以在多个设备下共享同一个IP的。这种共享既可以是物理的(多个设备同时使用一个IP,由上层路由进行分支选择或者广播、组播数据包),或者是轮询的(多个设备轮流使用一个IP,同时只有一个设备使用这个IP,而这个IP可以在多个设备间高速切换)。如果某个应用必须基于IP地址(例如DNS服务本身),只能使用这种方式来处理。
那么回头看你三个问题。
Q1返回多个A纪录后,客户端会按照集合的顺序依次尝试访问。这些数据在NS服务器上是单一存在的,但是会被多层DNS缓存。
Q2 HTTP头段已经讲述。
Q3希望你看过NLB段后能理解。
到此,以上就是小编对于nginx在网络系统中处于什么位置的问题就介绍到这了,希望介绍关于nginx在网络系统中处于什么位置的2点解答对大家有用。