文章目录
概述
一、nginx是一款轻量级的web服务器/反向代理服务器及电子邮件imap/pop3/smtp服务器,在bsd-like协议下发行。其特点是占有内存少,并发能力强。
二、核心应用场景:
- 高性能的静态web服务器:只能处理静态资源
静态资源:图片、样式、flash等不会随着用户的请求改变而改变的资源
动态资源:账户余额、商品剩余货源等,这些依赖于后端应用服务器在数据库查询、处理后返回的结果
- 反向代理:客户端点击一个网页后,本质上是向nginx发送了一个http/https请求,nginx可以将静态资源返回客户端,虽然nginx无法返回动态资源,但是他可以将请求代理的发送给后端的应用服务器,由应用服务器查询数据库并处理完数据后返回给nginx,nginx将动态资源、静态资源通过http/https返回给客户端,由客户端在浏览器展示。在这个过程中,对于动态资源来说,nginx就是一个反向代理,反向代理的过程中就有负载均衡,比如在应用服务器是多台的情况下,nginx能够将这些请求负载均衡的以此转发给每个应用服务器。后面讲到的限速、动静分离都是nginx的辅助能力
应用服务器:有很多种类型,如果后端是基于Java开发的,那么应用服务器可能是tomcat,还有些商用的应用服务器:weblogic
三、nginx为什么出现并流行:
主要应用场景
一、一个http请求的全流程
用户在浏览器上输入一个网站的地址,客户端会发送一个http请求到nginx,nginx会将动态资源请求转发给应用服务器,应用服务器与数据库交互进行业务逻辑处理,处理完后,将数据返回给nginx,nginx将动态资源和自身的静态资源进行封装后返回给客户端。
二、nginx处理请求的过程
说明:
- 红色箭头表示客户端发送到nginx的请求,静态资源放在本地文件系统(Linux系统下的某个目录),nginx对于静态资源的响应非常高,但是应用服务器对动态资源的响应急剧下降,数据库对请求的处理就更低了,为了缓解nginx、应用服务器、数据库之间的处理差异,我们需要部署一个缓存服务器(具体还是需要根据系统的规模决定要不要部署缓存服务器)。
- 反向代理代理中还有缓存加速、负载均衡:假如应用服务器有多台,反向代理就不能代理给某一台应用服务器了,而需要通过一些算法将请求进行分发,以达到负载均衡;nginx可以将应用服务器从数据库获取到的数据缓存起来,下次请求过来时,就不需要再去应用服务器获取结果,可以直接返回结果
- api服务:nginx诞生初期是没有这个能力的,随着nginx不断发展,有了openResty后才有的能力。openResty是nginx和弱脚本的结合,可以通过api服务自己开发一个高性能的web服务器
nginx核心优势
一、高并发、高性能:随着互联网数据和用户量的增长,之前使用的apache的web服务器已无法满足。高并发的场景下我们只用增加进程数就能解决,依赖于事件驱动模型、进程处理请求模型,他是用一个进程来处理多个请求;高性能依赖于良好的设计;
二、扩展性好:
- nginx自身是模块化设计的,模块化设计最强的优点就是解耦,所有功能的耦合性是很低的,意味着一个模块出现问题,是不会对其他模块造成影响的;
- nginx允许开发第三方模块,如openResty、阿里巴巴的tngine
- 生态圈发展好
三、异步非阻塞的事件驱动模型:比如餐厅点餐这一场景,在阻塞式场景中,第一个顾客点完餐,就在那里等,等厨师做完并交付给这个顾客后,顾客走了,老板才能接待下一个客户,对于异步来说,顾客点完餐后拿了个号牌,下一个顾客可以继续上前点单,对于老板来说,他可以接待的人更多了(处理的请求更多了),后续老板可以增加个叫号器,这就是编程开销,所以,对于异步非阻塞的事件驱动模型增加了编程难度、编程开销,但是处理更高效
四、高可靠性:nginx通常运行在系统的边缘节点,用于接收用户的请求,nginx连续运行几年可能都不需要重启服务,但是对于其他服务器(如apache),可能运行几周就需要重启服务器,为保证业务连续性,我们是不能接受这种情况的。
五、热部署、平滑升级:不需要关机就能对后端应用程序进行更换,同时不中断连接请求的处理
六、bsd许可:允许nginx使用者根据自己的需求对nginx进行二开,并将二开代码运用到nginx中,同时能运用到商业场景
安装第一个rpm包形式的nginx
nginx进程结构与热部署
nginx的进程结构
nginx采用多进程的进程结构,不采用多线程是因为nginx设计之初就是为了高可用性、高可靠性而设计的:多线程间最大的问题是,某一个线程因为代码不够健壮导致某一段地址空间越界,出现段错位时,可能导致整个线程的不可用,我们知道多线程间是通过采用共享同一个地址空间来实现的
说明:
- master process不处理请求,而是管理各模块,如下方的缓存模块、worker process子进程(处理请求),用于监控各模块是否宕掉,如果宕掉了,会启动一个新的worker process来维持原有的进程结构,假如我们在配置文件定义了worker process启动4个,而有一个突然宕掉了,在Linux系统中,子进程会自动发送一个信号给主进程,主进程收到后会自动检测到这个worker process已经宕掉了,他会自动再启一个,从而来维持4个worker process这一结构;假如我们修改了配置文件,加了一些静态资源、重写了url等,master process检测到了后,会通知worker process拿新的配置文件并生效,这就是热部署;
- 前面我们说过,nginx具有缓存功能,其实真正需要缓存哪些内容(缓存这一动作)是worker process做的,cache loader用于加载缓存,cache manager用于管理缓存
- 所有的子进程(cm、cl、worker process)使用共享内存进行通信
- 在实际生产环境中worker process不一定是4个,这一点稍后说明
- nginx是模块化设计的,虽然nginx允许修改master process,但是在开发第三方模块时,尽量不修改master process主程序模块,因为(由进程结构图可知)master process挂了整个服务就挂了
Linux的信号量管理机制
Linux操作系统中,通过信号量进行进程管理,比如我们可以通过q命令向某一进程的pid发送很多信号量,使用kill pid
相当于给Linux发送了一个kill -15
命令(-15
是一个代号)
在执行kill pid
实际上是发送了一个send sigterm信号给Linux的进程,Linux的进程收到信号后,先结束自己的工作,再关闭这个进程,同理,kill -9
实际上是发送了sigkill
信号,该信号不管当前的进程处于什么状态,不管是在处理数据还是在等待磁盘的io,都会被无条件终止,所以这个信号可能会对处理数据的进程有影响
说明:
- sigchld:用于父子进程间通信,某一子进程宕掉或者终止掉了,会自动发送sigchld给父进程,让父进程采取相应的措施,比如重新启动一个新的子进程
- sigterm:等进程处理完数据后再终止。
kill [-15] pid
- sigkill:使用
kill [-15] pid
终止不掉数据时使用该信号立即杀死进程。在使用shutdown关闭操作系统时,操作系统对正在运行的进程也是使用kill -9杀死,但是他是先向所有进程发送kill命令,等待应用程序自己处理完数据后关闭,操作系统会有个等待时间,假如这个等待时间到了还有进程没有关闭,操作系统才会发送kill -9
给应用程序立即终止程序,然后操作系统关机 - sighup:重读配置文件,关闭之前的worker子进程,重新生成新的worker子进程
- sigusr1、sigusr2:Linux提供给用户自定义的信号量
利用信号量管理nginx
一、nginx的哪些子进程可以使用信号量进行管理:
- master进程:我们给master发送信号量,让master管理所有子进程
- worker进程:虽然我们可以给worker进程发送信号量,但是不推荐这么做
- 命令行:通过nginx的二进制程序和一些参数对命令行进行管理,可用参数:
(1)reload:重新加载配置文件,本质上是给master进程发送hup信号
(2)reopen:重新打开日志文件,本质上是给master进程发送user1信号
(3)stop:停止nginx,本质上是给master进程发送term信号
(4)quit:停止nginx,本质上是给master进程发送quit信号
通常在启动nginx后,pid会保存在nginx.pid文件中,当执行reload命令时,其实也是通过Kill发送hup信号给nginx.pid文件中的进程
二、nginx采用事件驱动模型处理机制,该机制要求nginx的worker子进程从始至终都要和CPU绑定在一块(cpu有多少核,就会启动多少个worker子进程,通常在nginx.conf里面配置:worker_processea auto;),从而减少cpu的切换,提高cpu缓存命中效率
三、代码演示
终止26733进程:
sighup:重读26747master进程的配置文件,关闭其之前的worker子进程(26748、26749、26759、26751),重新生成新的worker子进程(26754、26755、26756、26757)
终止26754子进程,主进程为保持配置文件里既定的结构,会自动重启一个子进程26761
通过/opt/nginx/sbin/nginx -h
查看可以使用的命令行
说明:
-s
用于发送信号,也就是说可以使用/opt/nginx/sbin/nginx -s 参数
(本质上还是通过给master进程发送信号量进行管理)
- -v:查看nginx版本
- -V:查看nginx版本号、nginx编译安装时的一些参数(configure argument),如安装目录(-- prefix)、用户(–user)、组(–group)、程序目录(–sbin-path)、配置文件目录(-- config-path)
- -t:检查配置文件nginx.conf语法是否正确
配置文件重载的原理
一、reload重载配置文件的流程
- 向master进程发送
kill -s sighup
或者使用/opt/nginx/sbin/nginx -s reload
命令 - master进程检查nginx.config配置语法是否正确,如果nginx.config引入了其他配置文件,还会检查其他配置文件语法是否正确
- 配置语法正确后,如果配置文件中增加了端口,master进程会打开监听端口,如果没增加则不会打开
- master进程使用新的配置文件启动新的worker子进程
- 新的worker子进程启动完成后,master进程向老的worker子进程发送quit信号,从而保障用户请求始终能得到处理
- 旧的worker子进程继续处理当前的用户请求(新的请求由新的子进程处理),等当前连接处理完请求后,关闭监听句柄,处理完当前连接后关闭进程,从而实现nginx平滑过度的过程
二、不停机生效新的配置
nginx的热部署
一、热部署:在不中断现有业务的情况下,平滑的将新开发的应用程序版本升级完成。
二、nginx热升级的流程
- 将旧的nginx文件(主程序文件,即sbin文件夹下的nginx文件)替换成新的nginx文件,这要求li b库目录、配置文件目录、log目录都不变
- 向master进程发送usr2信号:
(1)旧的master进程主动修改自己的pid文件,给pid文件(/logs/nginx.pid)加后缀.oldbin
(2)master进程使用新的nginx文件生效新的配置,启动一个新的master进程 - 此时服务器上,旧的master进程和新的master进程同时存在,两个都会接收用户的请求并处理,此时需要验证新版本nginx是否满足预期,运行一段时间后发现能够满足,再向旧的master进程发送winch信号,旧的worker子进程退出,如果发送quit信号,旧的master进程及其worker子进程都会退出,这里用winch信号是为了避免接收新的用户请求,保证新的用户请求都由新的master进程生成的新的worker子进程处理,确保新的请求都是由新版本的nginx处理,之所以这样做,是为了保证回滚
- 如果新版本的nginx不满足预期的话,可以将新版本nginx下线,让旧版本nginx上线:向旧master发送hup,sighup信号发送后,旧的master进程会根据旧的配置文件把旧的worker子进程拉起来,旧的用户子进程会开始处理用户请求,同时需要向新master发送quit让其下线
nginx热部署完整步骤演示
- 备份nginx程序,替换nginx程序
- 向旧的master进程发送sur2信号,可以看到有两个master进程,每个master进程下面又有各自的worker子进程,此时新旧进程并存
- 查看/logs目录,可以看到nginx.pid.oldbin,里面保存着旧的master进程的pid,而新的nginx.pid里面保存着新的master进程的pid
- 给旧的master进程发送winch信号,显然旧的master下面没有worker子进程了,但是旧master主进程依旧存在,此时可以测试新的nginx是否满足预期
- 给旧的master进程发送quit信号,可以看到,旧的master进程及其worker子进程全部退出
而logs文件夹下面的nginx.pid.oldbin也被删除了
如果想回滚,本步骤应为:向旧的master进程发送hup信号
给新master进程发送quit信号
nginx的模块化管理机制
nginx编译安装的配置参数
说明:
- –prefix指定的是总的目录
- –user:指定由谁来启动worker子进程
- –group:指定启动nginx的worker子进程的组
- –conf-path、–error-log-path、–pid-path、–http-log-path默认值放在–prefix下面
- –with-pcre:如果配置文件为某些特定的url写了正则表达式,必须安装pcre库,该参数用于指定指定pcre库源代码的位置。下载pcre库源码并解压,编译安装nginx时,将pcre库的解压地址配置到这个参数中即可
- –with-lib:gzip模块会用到
内置参数默认原则:
- –with表示nginx不内置,不加这个参数,这个模块不会被编译进nginx
- –without表示nginx内置了该模块,该模块默认会被编译进ngixn,加上该参数,该模块就不会被编译进nginx
定制编译安装第一个nginx
- 解压pcre、gzip、nginx:
- 进入nginx文件夹,查看配置参数:
./configure --help
- 指定编译参数(path可以不
用指定),并指定哪些模块要编译进来,哪些不用
- 如果有报错,则安装相应的模块
yum install 模块名
,因为ssl相关的模块有两个,所以这里安装了openssl和openssl-devel
- 输入
make
进行编译完成后,使用make install
进行安装
- 安装完毕,启动nginx
- 查看日志
nginx配置文件结构
一、nginx.conf文件整体可以分为三大模块:events模块、http模块、server模块
说明:
- main模块:定义全局设置,如nginx运行的用户是谁,该用户属于哪个组,应该启动几个worker进程
- events模块:配置影响nginx服务器与用户的网络连接,如配置与nginx或者Linux事件驱动模型处理有关的指令
worker_connections:每个worker子进程可以处理的并发连接请求数,具体值需要根据对服务器进行测试得到,不是随意写的
- http模块:配置http核心指令。对http端来说,可以嵌套多个server,server对应的可能是虚拟主机。假如有3个不同域名部署了不同的网站服务,这3个网站服务可以部署在同一台nginx上,只要我们在server中定义对应的域名,就可以解析到对应的server端。也可以配置缓存、反向代理、第三方模块、日志定义等绝大多数功能。
- server模块:location端只能嵌套在server中,主要用于配置请求的路由、各种页面的处理情况,location可以理解为,访问某个url,应该去location指定的磁盘路径下获取静态资源,相当于是静态文件的映射路由
二、配置文件示例
三、
虚拟主机
虚拟主机:利用单台服务器构筑出多个不同类型的网站
分类
一、基于多ip的虚拟主机:单台服务器通常有多个网卡,在每个网卡上配置对应的ip地址,每个IP地址都可以给他构建个虚拟主机
二、基于多端口的虚拟主机:单台服务器部署,网卡只有一块,基于不同的端口提供不同的服务
三、基于域名的虚拟主机:一台物理主机上使用不同的域名来区分不同的网站服务