nginx 学习简记 3

(注:此篇简记源自阅读 The Architecture of Open Source Applications 中的 nginx

为什么高并发很重要

  • 越来越多的网站需要同时为成百上千万的用户同时提供服务
  • 越来越多的设备需要维持长连接,这些设备速度有快有慢

假设一个 Apache 服务器要产生一个 100kb 的响应。生成响应的时间很短,但发送响应的时间会很长(在 80 kbps 下需要 10 秒)。那么 Web 服务器将会花费大量时间在发送响应到客户上。如果有 1000 个客户同时连接,Web 服务器为每一个客户分配 1 MB 内存,那么 Web 服务器将会花费 1 GB 内存在发送 1000 个 100 kb 请求上。如果连接是长连接,这个问题将会被更恶化。

Web 服务器需要能够非线性的适应同时连接数和请求数。

Aapche 的设计思想源自 90 年代,单机服务。

C10K: Web 服务器应当有能力同时响应 10,000+ 客户请求。

Apache 为每个请求新创建一个线程或进程,而 nginx 则不然, nginx 为事件驱动。

nginx 最初是为了搭配 Apache ,响应静态内容访问,但随着各种插件的引入,形成了全功能的服务器。

nginx Windows 版并不堪用。

nginx 架构概述

nginx 受操作系统中事件驱动机制的影响,形成了它模块化,事件驱动,异步,单线程,非阻塞的架构。

nginx 大量使用多路复用和事件通知,将特定的任务分配给不同的进程。每个连接都在 worker (单线程的进程)的事件循环中被处理。每个 nginx worker 可以响应上千个并发连接或请求。

nginx worker 包含核心模块和功能模块。nginx 的核心模块负责维持一个紧凑的时间循环,用来执行各个模块的代码,以及响应各个阶段的请求。

nginx 的模块式架构使得开发者可以在不修改 nginx 核心模块的前提下扩展服务器功能。nginx 模块包含:core modules, event modules, phase handlers, protocols, variable handlers, filters, upstreams, and load balancers.

nginx 通过使用 kqueue, epoll, 和 event ports 来尽可能高效的利用操作系统,实现高性能事件通知和 IO 操作。

nginx architecture

每个 worker 进程通过一个共享的 socket 监听请求,并在一个高效事件循环中处理请求。

nginx 把事件循环做的尽可能高效,非阻塞。由于 nginx 不需要为每个连接创建进程或线程,nginx 的内存占用十分低。

一般来说,一个 CPU 核心一个 worker 即可达到很好的效果。

如果响应为计算密集,一个 core 一个 worker;如果响应为 IO 密集,一个 core 1.5~2 个 worker

worker 可能会被 IO 阻塞,可以通过 sendfile 或 AIO 提升 IO 性能

nginx 包含 1 个 master 进程和多个 worker 进程。每个进程均为单线程。所有的进程使用共享内存进行进程间通信。master 进程按 root 用户权限,其它进程按非 root 权限。

nginx 配置

nginx 配置文件被保存在一个或多个文本文件内。

主配置文件一般是 nginx.conf

master 进程会读取并验证配置文件,然后将其编译为只读形式提供给 worker 进程

nginx 配置包含 main, http, server, upstream, 以及 location 等上下文

配置文件语法使用类 C 风格

nginx 内部结构

nginx 核心模块负责提供 Web 服务,Web 反向代理,以及邮件反向代理的基本功能。协议特定和应用特定的功能由 nginx 功能模块(event modules, phase handlers, output filters, variable handlers, protocols, upstreams, load balancers)完成。

典型的 HTTP 请求处理如下:

  1. 客户发送 HTTP 请求
  2. nginx 核心模块根据配置文件选择合适的 phase handler
  3. 如果配置了负载均衡,负载均衡模块会挑选一个上游服务器进行代理
  4. phase handler 完成处理后,将结果输出至 output filter
  5. output filter 依次处理
  6. 返回最终结果

nginx 允许用户编写自己的模块,在特定时间点执行

经验 教训

Igor Sysoev 在编写 nginx 时,internet 的结构已经成型。但 Igor 的想法并没有受当时的服务器/网络结构制约

开发需要专注,去除不必要的投入

未完待续