《深入理解Nginx:模块开发与架构解析》一1.2 为什么选择Nginx

1.2 为什么选择Nginx

为什么选择Nginx?因为它具有以下特点:
(1)更快
这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应;另一方面,在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请求。
实际上,本书第三部分中大量的篇幅都是在说明Nginx是如何做到这两点的。
(2)高扩展性
Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须在意其他。而且在HTTP模块中,还设计了HTTP过滤器模块:一个正常的HTTP模块在处理完请求后,会有一串HTTP过滤器模块对请求的结果进行再处理。这样,当我们开发一个新的HTTP模块时,不但可以使用诸如HTTP核心模块、events模块、log模块等不同层次或者不同类型的模块,还可以原封不动地复用大量已有的HTTP过滤器模块。这种低耦合度的优秀设计,造就了Nginx庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样容易使用。
Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模块还是第三方模块都是如此。这使得第三方模块一样具备极其优秀的性能,充分利用Nginx的高并发特性,因此,许多高流量的网站都倾向于开发符合自己业务特性的定制模块。
(3)高可靠性
高可靠性是我们选择Nginx的最基本条件,因为Nginx的可靠性是大家有目共睹的,很多家高流量网站都在核心服务器上大规模使用Nginx。Nginx的高可靠性来自于其核心框架代码的优秀设计、模块设计的简单性;另外,官方提供的常用模块都非常稳定,每个worker进程相对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker子进程提供服务。
(4)低内存消耗
一般情况下,10 000个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5MB的内存,这是Nginx支持高并发连接的基础。
从第3章开始,我们会接触到Nginx在内存中为了维护一个HTTP连接所分配的对象,届时将会看到,实际上Nginx一直在为用户考虑(尤其是在高并发时)如何使得内存的消耗更少。
(5)单机支持10万以上的并发连接
这是一个非常重要的特性!随着互联网的迅猛发展和互联网用户数量的成倍增长,各大公司、网站都需要应付海量并发请求,一个能够在峰值期顶住10万以上并发请求的Server,无疑会得到大家的青睐。理论上,Nginx支持的并发连接上限取决于内存,10万远未封顶。当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的,本书第8~11章将会详细说明如何实现这个特点。
(6)热部署
master管理进程与worker工作进程的分离设计,使得Nginx能够提供热部署功能,即可以在7×24小时不间断服务的前提下,升级Nginx的可执行文件。当然,它也支持不停止服务就更新配置项、更换日志文件等功能。
(7)最自由的BSD许可协议
这是Nginx可以快速发展的强大动力。BSD许可协议不只是允许用户免费使用Nginx,它还允许用户在自己的项目中直接使用或修改Nginx源码,然后发布。这吸引了无数开发者继续为Nginx贡献自己的智慧。
以上7个特点当然不是Nginx的全部,拥有无数个官方功能模块、第三方功能模块使得Nginx能够满足绝大部分应用场景,这些功能模块间可以叠加以实现更加强大、复杂的功能,有些模块还支持Nginx与Perl、Lua等脚本语言集成工作,大大提高了开发效率。这些特点促使用户在寻找一个Web服务器时更多考虑Nginx。
当然,选择Nginx的核心理由还是它能在支持高并发请求的同时保持高效的服务。
如果Web服务器的业务访问量巨大,就需要保证在数以百万计的请求同时访问服务时,用户可以获得良好的体验,不会出现并发访问量达到一个数字后,新的用户无法获取服务,或者虽然成功地建立起了TCP连接,但大部分请求却得不到响应的情况。
通常,高峰期服务器的访问量可能是正常情况下的许多倍,若有热点事件的发生,可能会导致正常情况下非常顺畅的服务器直接“挂死”。然而,如果在部署服务器时,就预先针对这种情况进行扩容,又会使得正常情况下所有服务器的负载过低,这会造成大量的资源浪费。因此,我们会希望在这之间取得平衡,也就是说,在低并发压力下,用户可以获得高速体验,而在高并发压力下,更多的用户都能接入,可能访问速度会下降,但这只应受制于带宽和处理器的速度,而不应该是服务器设计导致的软件瓶颈。
事实上,由于中国互联网用户群体的数量巨大,致使对Web服务器的设计往往要比欧美公司更加困难。例如,对于全球性的一些网站而言,欧美用户分布在两个半球,欧洲用户活跃时,美洲用户通常在休息,反之亦然。而国内巨大的用户群体则对业界的程序员提出更高的挑战,早上9点和晚上20点到24点这些时间段的并发请求压力是非常巨大的。尤其节假日、寒暑假到来之时,更会对服务器提出极高的要求。
另外,国内业务上的特性,也会引导用户在同一时间大并发地访问服务器。例如,许多SNS网页游戏会在固定的时间点刷新游戏资源或者允许“偷菜”等好友互动操作。这些会导致服务器处理高并发请求的压力增大。
上述情形都对我们的互联网服务在大并发压力下是否还能够给予用户良好的体验提出了更高的要求。若要提供更好的服务,那么可以从多方面入手,例如,修改业务特性、引导用户从高峰期分流或者把服务分层分级、对于不同并发压力给用户提供不同级别的服务等。但最根本的是,Web服务器要能支持大并发压力下的正常服务,这才是关键。
快速增长的互联网用户群以及业内所有互联网服务提供商越来越好的用户体验,都促使我们在大流量服务中用Nginx取代其他Web服务器。Nginx先天的事件驱动型设计、全异步的网络I/O处理机制、极少的进程间切换以及许多优化设计,都使得Nginx天生善于处理高并发压力下的互联网请求,同时Nginx降低了资源消耗,可以把服务器硬件资源“压榨”到极致。

时间: 2024-11-05 16:33:33

《深入理解Nginx:模块开发与架构解析》一1.2 为什么选择Nginx的相关文章

《深入理解Nginx:模块开发与架构解析》一1.3 准备工作

1.3 准备工作 由于Linux具有免费.使用广泛.商业支持越来越完善等特点,本书将主要针对Linux上运行的Nginx来进行介绍.需要说明的是,本书不是使用手册,而是介绍Nginx作为Web服务器的设计思想,以及如何更有效地使用Nginx达成目的,而这些内容在各操作系统上基本是相通的(除了第9章关于事件驱动方式以及第14章的进程间同步方式在类UNIX操作系统上略有不同以外). 1.3.1 Linux操作系统 首先我们需要一个内核为Linux 2.6及以上版本的操作系统,因为Linux 2.6及

《深入理解Nginx:模块开发与架构解析》一3.4 HTTP模块的数据结构

3.4 HTTP模块的数据结构 定义HTTP模块方式很简单,例如: ngx_module_t ngx_http_mytest_module; 其中,ngx_module_t 是一个Nginx模块的数据结构(详见8.2节).下面来分析一下Nginx模块中所有的成员,如下所示: typedef struct ngx_module_s ngx_module_t; struct ngx_module_s { /* 下面的ctx_index.index.spare0.spare1.spare2.spare

《深入理解Nginx:模块开发与架构解析》一2.4 用HTTP核心模块配置一个静态Web服务器

2.4 用HTTP核心模块配置一个静态Web服务器 静态Web服务器的主要功能由ngx_http_core_module模块(HTTP框架的主要成员)实现,当然,一个完整的静态Web服务器还有许多功能是由其他的HTTP模块实现的.本节主要讨论如何配置一个包含基本功能的静态Web服务器,文中会完整地说明ngx_http_core_module模块提供的配置项及变量的用法,但不会过多说明其他HTTP模块的配置项.在阅读完本节内容后,读者应当可以通过简单的查询相关模块(如ngx_http_gzip_f

《深入理解Nginx:模块开发与架构解析》一3.1 如何调用HTTP模块

3.1 如何调用HTTP模块 在开发HTTP模块前,首先需要了解典型的HTTP模块是如何介入Nginx处理用户请求流程的.图3-1是一个简化的时序图,这里省略了许多异步调用,忽略了多个不同的HTTP处理阶段,仅标识了在一个典型请求的处理过程中主要模块被调用的流程,以此帮助读者理解HTTP模块如何处理用户请求.完整的流程将在第11章中详细介绍.从图3-1中看到,worker进程会在一个for循环语句里反复调用事件模块检测网络事件.当事件模块检测到某个客户端发起的TCP请求时(接收到SYN包),将会

《深入理解Nginx:模块开发与架构解析》一3.6 处理用户请求

3.6 处理用户请求 本节介绍如何处理一个实际的HTTP请求.回顾一下上文,在出现mytest配置项时,ngx_http_mytest方法会被调用,这时将ngx_http_core_loc_conf_t结构的handler成员指定为ngx_http_mytest_handler, 另外,HTTP框架在接收完HTTP请求的头部后,会调用handler指向的方法.下面看一下handler成员的原型ngx_http_handler_pt: typedef ngx_int_t (ngx_http_han

《深入理解Nginx:模块开发与架构解析》一3.9 用C++语言编写HTTP模块

3.9 用C++语言编写HTTP模块 Nginx及其官方模块都是由C语言开发的,那么能不能使用C++语言来开发Nginx模块呢?C语言是面向过程的编程语言,C++则是面向对象的编程语言,面向对象与面向过程的优劣这里暂且不论,存在即合理.当我们由于各种原因需要使用C++语言实现一个Nginx模块时(例如,某个子功能是用C++语言写成,或者开发团队对C++语言更熟练,又或者就是喜欢使用C++语言),尽管Nginx本身并没有提供相应的方法支持这样做,但由于C语言与C++语言的近亲特性,我们还是可以比较

《深入理解Nginx:模块开发与架构解析》一3.2 准备工作

3.2 准备工作 Nginx模块需要使用C(或者C++)语言编写代码来实现,每个模块都要有自己的名字.按照Nginx约定俗成的命名规则,我们把第一个HTTP模块命名为ngx_http_mytest_module.由于第一个模块非常简单,一个C源文件就可以完成,所以这里按照官方惯例,将唯一的源代码文件命名为ngx_http_mytest_module.c. 实际上,我们还需要定义一个名称,以便在编译前的configure命令执行时显示是否执行成功(即configure脚本执行时的ngx_addon

《深入理解Nginx:模块开发与架构解析》一3.3 如何将自己的HTTP模块编译进Nginx

3.3 如何将自己的HTTP模块编译进Nginx Nginx提供了一种简单的方式将第三方的模块编译到Nginx中.首先把源代码文件全部放到一个目录下,同时在该目录中编写一个文件用于通知Nginx如何编译本模块,这个文件名必须为config.它的格式将在3.3.1节中说明.这样,只要在configure脚本执行时加入参数--add-module=PATH(PATH就是上面我们给定的源代码.config文件的保存目录),就可以在执行正常编译安装流程时完成Nginx编译工作.有时,Nginx提供的这种

《深入理解Nginx:模块开发与架构解析》一3.5 定义自己的HTTP模块

3.5 定义自己的HTTP模块 上文中我们了解了定义HTTP模块时需要定义哪些成员以及实现哪些方法,但在定义HTTP模块前,首先需要确定自定义的模块应当在什么样的场景下开始处理用户请求,也就是说,先要弄清楚我们的模块是如何介入到Nginx处理用户请求的流程中的.从2.4节中的HTTP配置项意义可知,一个HTTP请求会被许多个配置项控制,实际上这是因为一个HTTP请求可以被许多个HTTP模块同时处理.这样一来,肯定会有一个先后问题,也就是说,谁先处理请求谁的"权力"就更大.例如,ngx_

《深入理解Nginx:模块开发与架构解析》一2.2 Nginx配置的通用语法

2.2 Nginx配置的通用语法 Nginx的配置文件其实是一个普通的文本文件.下面来看一个简单的例子. user nobody; worker_processes 8; error_log /var/log/nginx/error.log error; #pid logs/nginx.pid; events { use epoll; worker_connections 50000; } http { include mime.types; default_type application/o