最近和 Nginx 杠上了

【51CTO.com原创稿件】Nginx(enginex)是一个高性能的HTTP和反向代理Web服务器 , 同时也提供了IMAP/POP3/SMTP服务 。
最近和 Nginx 杠上了
文章图片
图片来自包图网
Nginx以高性能和高可用性备受广大程序员的青睐 , 今天我们会从Nginx的整体架构入手 , 介绍Nginx进程结构 , 进程之间的关系以及如何对进程进行控制和管理 。
今天大家会学到如下内容:
Nginx总体架构Nginx进程定义Nginx启动过程Master启动过程进程之间的信号发送方式进程协助处理网络请求Nginx总体架构
对于传统的HTTP和反向代理服务器而言 , 在处理并发请求的时候会使用单进程或线程的模式处理 , 同时会止网络或输入/输出操作 。
这种方式会消耗大量的内存和CPU资源 。 因为每产生一个单独的进程或线程需要准备一套新的运行时环境 , 包括分配堆和堆栈内存 , 以及创建新的执行上下文 。
可以想象在处理多请求时会生成对应数目的线程或进程 , 导致由于线程在不断上下文切换上耗费大量资源 。
由于上面的原因 , Nginx在设计之初就使用了模块化、事件驱动、异步处理 , 非阻塞的架构 。
最近和 Nginx 杠上了
文章图片
图1:Nginx总体架构
让我们通过一张图来了解Nginx的总结架构 , 如图1所示:
①Nginx启动时 , 并不会马上处理网络请求 , 负责调度工作进程 。 包括Loadconfiguration(加载配置) , Launchworkers(启动工作进程)以及Non-stopupgrade(平滑升级) 。
因此在Nginx启动以后 , 在操作系统中会看到Master和Worker两类进程 。 在图上方的Master进程负责加载分析配置文件、启动/管理Worker进程以及平滑升级 。
一个Master进程可以管理多个Worker进程 , 而Worker进程负责处理并响应用户请求 , 也就是来自图左边的HTTP/HTTPS请求 。
②由于网络请求属于IO请求 , 为了应对高并发Nginx采取了kevent/epoll/select模式的多路复用技术 。 由于采取了这种技术每个Worker进程都可以同时处理数以千计的网络请求 。
③为了处理网络请求在Worker中会包含模块 , 分为核心模块和功能性模块 。
核心模块负责维持一个运行循环(run-loop) , 执行网络请求处理的不同阶段的模块功能 , 如网络读写、存储读写、内容传输、外出过滤 , 以及将请求发往上游服务器等 。
而围绕着核心模块会有一些功能模块 , 就是实现具体的请求处理功能的 。 例如有处理http请求的ht_core模块 , 有实现负载均衡的ht_upstream模块 , 以及实现FastCGI的ht_fastcgi模块 。
这些模块会负责与后端的服务器进行交互 , 完成用户请求 , 同时可以根据需要的功能自由加载模块 , 甚至可以扩展第三方的模块 。
④Worker进程可以和本地磁盘进行数据通信 , 支持AdvancedI/O(高级I/O)、sendfile机制、AIO机制、mmap等机制等 。
通过上面的介绍发现Nginx不会为每个连接生成一个进程或线程 , 而是通过Worker进程使用多路复用的方式处理多个请求 。
这里会使用到共享监听套接字的方式接受新请求 , 并在每个Worker内执行高效的运行循环 , 从而达到每个Worker处理成千上万的连接 。
Work启动后将创建一组侦听套接字 , 并且在处理HTTP请求和响应过程中不断接受 , 读取和写入套接字信息 。
运行循环(run-loop)包括全面的内部调用 , 并且在很大程度上依赖异步任务处理 。
通过模块化 , 事件通知 , 回调函数和定时器来支撑异步操作的实现 。 其目的是为了实现高并发请求下的不阻塞(尽可能不阻赛) 。
基于上面的机制 , Nginx通过检查网络和存储的状态并初始化新连接 , 将其添加到运行循环中 , 并异步处理直到其完成 , 处理完毕的连接会被重新分配并从运行循环中删除 。 因此Nginx可以在极端工作负载下实现较低的CPU使用率 。