Nginx完全开发指南:使用C、C++和OpenResty(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-16 08:04:32

点击下载

作者:罗剑锋

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Nginx完全开发指南:使用C、C++和OpenResty

Nginx完全开发指南:使用C、C++和OpenResty试读:

前言

缘起

最早接触Nginx大概是在2011年,面对着一个全新的Web服务器,和大多数人一样最初我也是一片茫然,能找到的参考资料十分有限,安装、配置、运行几乎都是“摸着石头过河”,犯过许多低级错误。

随着对Nginx逐渐熟悉,它的高并发处理能力给我留下了深刻的印象,作为一个开源软件的爱好者,很自然地想要探究一下它的内部工作原理。我由此开始了对Nginx源码的钻研之路,中间经过了很多的艰辛曲折,走过不少的弯路。

我最常用的工作语言是C++,所以在阅读Nginx源码时也总以C++的面向对象方式来思考和理解,以对象作为切入点记笔记、画UML:从最简单的ngx_str_t、ngx_array_t入手,然后到ngx_request_t、ngx_upstream_t等复杂的结构,再围绕着这些对象研究相关的功能函数和处理流程,梳理代码逻辑的同时也摸索着使用C++编写Nginx模块的方法,逐渐积累了一些用起来颇为顺手的小工具——当然还是比较初级的形式。

三年多前,我被调到了新的工作岗位,需要重度使用Nginx开发,这让我以前的零散积累终于有了用武之地。那段时间里使用C/C++陆续做了很多东西,也借着机会重新优化了原有的工具代码。

繁忙的工作之余,我有了种进一步整理经验的迫切感,因为只有系统完整地分享这些知识,才能让更多的人基于Nginx二次开发,让Nginx更好地为网络世界服务。

同一时间,市面上也出现了一些Nginx开发相关的资料、书籍,但在我看来却有“粗制滥造”之嫌:行文混乱,“车轱辘话”“口头禅”满天飞,甚至大段照抄指令说明,还有对源码的曲解,未免有点儿“误人子弟”,读起来实在是难受。终于,在“忍无可忍”的心态之下,我动起了写作本书的念头。

经过近一年的努力,现在这本书终于呈现在了读者面前,结构上基本反映了我学习研究Nginx时的心路历程,从最初的“一无所知”起步,逐渐深入到定制开发的层次,希望能与读者“心有戚戚焉”。

Nginx随感

毫无疑问,Nginx是目前这个星球上所能获得的最强劲的Web服务器(没有之一),同时也是目前最成熟、最优秀的TCP/HTTP服务器开发框架。

Nginx资源消耗低,并发处理性能高,配置灵活,能够连接CGI、PHP、MySQL、Memcached等多种后端,还有着出色的负载均衡能力,可以整合封装各种service,构建稳定高效的服务。如今Nginx已经成为了网站架构里不可或缺的关键组件,广泛应用于国内外许多大型IT企业。每一个繁忙的网站背后,可能都有Nginx默默工作的身影。

在Nginx出现之前,使用C/C++开发Web服务器是项比较“痛苦”的工作,虽然有很多网络程序库可以使用(例如asio、libevent、thrift等),但它们通常只关注较底层的基础功能实现,离成熟的“框架”相距甚远,不仅开发过程烦琐低效,而且程序员还必须要处理配置管理、进程间通信、协议解析等许多Web服务之外的其他事情,才能开发出一个较为完善的服务器程序。但即使开发出了这样的服务器,通常性能上也很难得到保证,会受到程序库和开发者水平等因素的限制——很长一段时间里,C/C++在Web服务器领域都没有大展拳脚的机会。

Nginx的横空出世为Web服务器开辟了一个崭新的天地,它搭建了一个高性能的服务器开发框架,而且是一个完整的、全功能的服务器。模块化的架构设计很好地分离了底层支撑模块和上层逻辑模块,底层模块处理了配置、并发等服务器的外围功能,核心支撑模块定义了主体的TCP/HTTP处理框架。开发者可以把大部分精力集中在上层的业务功能实现上,再也不必去为其他杂事而分心,提高了软件的开发效率。

在Nginx框架里,C/C++程序员可以尽情发挥自己的专长,充分利用Nginx无阻塞处理的优势,打造出高质量的Web应用服务器,与其他系统一较高下。

Nginx和C/C++

Igor Sysoev选择用C语言(准确地说是ANSI C)来实现Nginx肯定是经过了认真的考虑。

作为与UNIX一同诞生的编程语言,C语言一直是系统级编程的首选。和其他高级语言相比,它简单可靠,更接近计算机底层硬件,运行效率更高。指针更是C语言的一大特色,善用指针能够完成许多其他语言无法完成的工作。

以C语言实现的Nginx没有“虚拟机”的成本,省略了不必要的中间环节,直接操纵计算机硬件,从根本上提高了Web服务器的处理能力。虽然C语言不直接支持面向对象,但Nginx灵活运用了指针,采用结构体+函数指针的形式,达到了同样的效果,从而使软件拥有了良好的结构。

C++是仅次于C的系统级编程语言,在兼容C的同时又增加了类、异常、模板等新特性,还支持面向对象、泛型、函数式、模板元等多种编程范式,可以说是计算机语言里的一个“庞然大物”。C++的特性很多,有的也很好用,但总体上的确比较复杂,易学难精,容易被误用和滥用,导致低效、难维护的代码,我想这可能是Igor Sysoev放弃使用C++的一个重要原因。

另一个可能的原因是C语言本身已经非常稳定,几十年来没有太大的变动,在各个系统里都支持得非常好。而C++在1998年才有了第一个标准,并且现在还在发展之中,语言特性还不够稳定(例如export、register等曾经的关键字在C++11里就已经被废弃),许多编译器对C++的支持程度也有差异,这与Nginx的高可移植性目标明显不符。

但C++毕竟还是有很多的优点,类可以更好地封装信息、异常简化了错误处理、模板能够在编译期执行类型计算。在C++11标准颁布之后,C++更是几乎变成了一门“全新”的语言,auto/decltype/nullptr/noexcept等新关键字增强了语言的描述能力,标准库也扩充了相当多的组件,易用性和稳定性都大大提升。

在Nginx里使用C++时要对C++的长处和不足有清醒的认识,避免多层次继承、虚函数等影响效率的编程范式,只使用经过充分验证的、能够切实提高开发效率和性能的语言特性和库,避免华而不实的技术炫耀,尽量做到像Nginx源码那样质朴踏实。只有这样,才能够发挥出1+1>2的作用,让Nginx从C++中得到更进一步的发展动力。

Nginx和OpenResty

多年以前Nginx开发使用的语言只能是C和C++,而现在,越来越多的开发者逐渐转向了OpenResty,使Lua搭建高并发、高性能、高扩展性的Web Server。

我接触OpenResty的时间并不算很长,大约在四年左右。由于C/C++程序员“天生的傲慢”,一开始对OpenResty确实有点儿“抵触情绪”,总觉得脚本程序比不上C/C++实现。然而随着使用的增多,特别是在研究了它的源码之后,我不得不感慨OpenResty的精致、完美和强大,简直是所有Nginx开发者“梦寐以求的至宝”。

由于agentzh对Nginx的运行机制了如指掌,OpenResty的核心部分——ngx_lua一个模块就涵盖了access/rewrite/content/log等多个处理阶段,再搭配上小巧灵活的Lua和高效的LuaJIT,我们就能够在更高级的业务层次上使用“胶水”代码来调用组合Nginx底层功能,轻松开发出丰富Web服务,极大地节约了宝贵的时间和精力。

当然,OpenResty并不只有ngx_lua,围绕着ngx_lua还有众多的库和辅助工具,构成了一个相当完善的生态环境,这些组件相互支撑,利用得当可以更好地提高生产效率。

OpenResty现在正处于蓬勃发展的阶段,今后的OpenResty也许不仅限于Nginx和Web Server,而将成为一个更通用的开发平台,工作语言也不仅限于Lua,可能还会有其他新的语言(例如agentzh正在做的edgelang和fanlang),让我们拭目以待。

致谢

首先当然要感谢Nginx的作者Igor Sysoev,没有他就不会有如此优秀的Web服务器,也就不会有本书的诞生。

OpenResty创始人章亦春(agentzh)是一位非常亲切随和的人,在Nginx、DSL、Dynamic Tracing等领域造诣极高,本书部分章节有幸经他审阅,在此表示最诚挚的谢意。

亲情永远是人生命中最值得珍惜的部分,我要感谢父母多年来的养育之恩和“后勤”工作,感谢妻子在生活中的陪伴,感谢两个可爱的女儿,愿你们能够永远幸福快乐。

最后,我也要感谢读者选择本书,希望读者能够在阅读过程中有所收获,在Nginx开发过程中获得乐趣。您的朋友罗剑锋2017年4月28日于北京亚运村第0章导读0.1关于本书

Nginx{L-End}是由俄罗斯工程师Igor Sysoev开发的一个高性能Web服务器,应用于诸多顶级互联网公司,为全世界数以亿计的网民提供着出色的服务。根据某些权威公司分析统计,现在它已是市场份额第二大的Web服务器,并且仍然在快速增长,在Top 1000的网站中更是超过了Apache而荣登榜首。

除了最引人注目的高性能和高稳定性外,Nginx的另一个突出特点是高扩展性,其灵活优秀的模块化架构允许在不修改核心的前提下增加任意功能。自2004年正式发布以来,Nginx已经拥有了百余个官方及非官方的功能模块(如proxy、rtmp、memcached、redis、mysql、lua等),这使得Nginx超越了一般意义上的Web服务器,成为了一个近乎“全能”的应用服务器。

Nginx功能强大,架构复杂,学习、维护和开发的门槛都很高,导致很多初学者“久仰大名”但却难以入门。本书将深入浅出地解析Nginx源码,详细讲解如何使用C、C++和Lua语言来增强扩展Nginx,并充分利用C++和Lua的高级特性,让读者能够更加便捷、轻松地开发和定制Nginx,应用到自己的实际工作中。0.2读者对象

本书适合以下各类读者:

■ 基于Nginx进行二次开发的软件工程师;

■ 基于Openresty/Lua进行二次开发的软件工程师;

■ Nginx运维工程师;

■ Web服务器开发者;

■ 对Nginx架构、内部实现感兴趣的程序员;

■ C/C++/Lua、计算机编程的爱好者和在校学生。

Nginx采用进程池、事件驱动等方式来支持海量并发连接的处理,搭建了一个高性能高稳定性的服务器框架,在这个框架之内可以利用Nginx内部的各种构件编写模块,自由实现所需的业务功能。因此,国内外都有很多个人和企业以Nginx为平台进行二次开发,编写模块甚至直接定制Nginx,进而提高网站的整体服务能力。本书由浅入深地详细介绍了Nginx模块开发的全过程,并且细致地分析了Nginx的内部运行机制,能够帮助软件工程师较快地熟悉Nginx原理,迅速地投入到实际开发工作中。

OpenResty是由OpenResty社区(创始人agentzh)维护的一个服务器开发包,核心组件是Nginx和ngx_lua模块,可以在Nginx框架内使用动态脚本语言Lua快捷实现业务逻辑,它既保持了Nginx高性能的优势,又没有C语言开发效率低的劣势,是目前服务器开发领域里的新生力量,前途不可限量。本书详细介绍了OpenResty开发相关的各个方面知识,即使是没有C语言基础的开发者也可以很快理解掌握,开发出高质量的网络服务程序。

Nginx项目十分活跃,版本更新较快,新的功能不断增加,这使得市面上的相关书籍和网络资料常常会变得“过时”——只言片语、语焉不详或者答非所问{L-End},Nginx运维工程师很可能会遇到运行、配置出现问题却无法解决的尴尬局面。然而Nginx是开源的,一切问题都可以在源码中找到答案。但十余万行的Nginx源码又有如汪洋大海,如果没有经验丰富的引航员指路,工程师难免会迷失方向,上下求索而不得。本书正是担当了这样的引航员角色,详尽地分析了Nginx的配置解析功能和HTTP/TCP/UDP处理流程,让运维工程师可以快速定位配置指令和它的实现逻辑,深层次地做好Nginx的运维工作。

对于那些自行开发Web服务器的程序员来说,Nginx也是一个非常有意义的借鉴品。它采用epoll/kqueue等异步调用削减了系统成本,充分挖掘了计算机硬件的性能,让CPU、磁盘、网卡等设备并发运行,比传统的多进程、多线程方式的服务器运行得更快,服务能力更强。本书深入剖析 Nginx源码,解析了模块架构、进程模型、事件驱动、多线程等机制,学习借鉴这些大师级、教科书级的经典代码,无疑会让自己的开发功力更上一层楼,写出更好的软件产品。

虽然Nginx功能如此强大,但它的实现却非常清晰易读:文件组织良好,代码格式优美,内部隐藏的大量编程技巧、设计思想和架构更是值得仔细研究的无价之宝。对于每一位喜好编程、准备或者正在投身于软件/互联网行业的人来说,本书都是一个很好的起点,可以从零起步窥探到Nginx内部的真正精髓,学习到各种实用的技术和知识,增加自身的“含金量”。

本书还大量应用了C++11标准和Boost程序库,使用了lambda表达式、模板元编程等许多高级特性,可以看作是现代C++编程范式的一次成功实践,读者可以接触到当前C++最新、最前沿的技术。0.3读者要求

本书要求读者基本了解C语言和网络编程知识。

Nginx本身是用C实现的,而本书主要使用C++作为编程语言,所以读者应该具备足够的C/C++知识,例如宏、指针、类型转换、封装、继承、异常等C/C++特性,如果已有实际编程经验则更好。

在基本的C++之上,本书还使用了C++11标准和Boost程序库来提高开发效率,要求读者对模板、泛型编程和C++标准库有一定的了解,能够运用vector、list等常见的泛型容器和迭代器。

如果读者主要使用OpenResty/Lua开发,那么可以不必过多关心C++,但基本的C语言知识还是必须的,可以更好地理解Nginx/OpenResty的工作原理。

Nginx是一个Web服务器,所以熟悉网络编程对于学习本书是非常有益的。但由于Nginx封装了很多网络通信的底层细节,所以本书不要求读者对网络编程技术有很深刻的认识,但至少应该对TCP和HTTP通信协议有所了解。

此外,因为Nginx大多运行在Linux服务器上,读者还应该再学习一些UNIX/Linux和Shell编程的相关知识,才能够编写Nginx的编译脚本和运行维护。

附录A列出了一些技术书籍,涵盖了大部分本书要求掌握的C/C++语言和网络编程技术知识,建议读者阅读本书时参考。0.4运行环境

Nginx可以跨平台编译和运行,支持Linux、FreeBSD、macOS、Windows等多种操作系统。但就目前市场来看,Linux是应用最普及的服务器操作系统,故本书的开发环境选用Linux。

Linux有很多的发行版本,企业中使用较多的是偏重于稳定性的CentOS和偏重于易用性的Ubuntu,出于个人喜好的原因本书选择了后者(请CentOS支持者见谅)。

下面是本书使用的具体环境:

■ 操作系统:Ubuntu 14.04.05(Linux 4.4.0);

■ Shell:系统自带的dash(注意不是bash);

■ 编译器:系统自带的GCC 4.8.4(支持C++11标准)。0.5本书的结构

Nginx是一个非常庞大的系统,内部结构错综复杂,简单的循序渐进方式难以透彻地讲解清楚,也不利于学习和掌握开发知识,所以本书结合“知其所以然”再“知其然”的方式组织全书的章节:首先介绍Nginx的基本知识作为入门,然后由浅入深地解析Nginx的源码和架构,理解了内部运行机制后再介绍如何开发定制Nginx。

学习Nginx不研究其内部工作原理是不行的,但解析得太深会导致源码太多,文字过于晦涩难懂;介绍得太浅又不能达到“知其所以然”的效果。所以本书只以中等深度研究Nginx源码和框架,讲解关键的流程、原理和函数调用,不涉及过于底层的实现细节。每个章节首先学习结构定义等静态模型,然后配合图示研究工作原理、运行机制等动态模型,最后结合Nginx官方源码,通过实例讲解开发要点,这种方式能够较好地覆盖Nginx开发的各个方面。

全书共20章,大致可分为四部分:

第1章是入门知识,简要介绍Nginx的安装和使用;第2章至第12章重点讲解使用C/C++语言开发定制Nginx,主要是“知其然”;第13章至第18章则深入Nginx的内部,剖析它的底层运行机制,帮助读者深层次地理解Nginx,是“知其所以然”;第19章专门介绍OpenResty,它可以用Lua语言快速开发出高性能的Web应用。

各章的内容简介如下。

■ 第1章:Nginx入门

简要介绍Nginx的历史和特点,以及如何编译、安装和配置Nginx,可以当作是一本浓缩精华的Nginx使用手册。

■ 第2章:Nginx开发准备

本章是开发Nginx模块前的准备工作,介绍本书使用的C++11标准和Boost程序库,还有Nginx源码的目录结构、基本的代码风格和特点。针对Nginx源码的特点提出了C++的解决方案,实现了一个对Nginx数据结构的C++封装类。

■ 第3章:Nginx基础设施

剖析Nginx这样复杂的系统必须从最底层的基础设施开始,本章首先介绍了Nginx框架里基本的整数类型和错误码,然后再研究内存池、字符串、时间日期和运行日志,同时使用C++11标准进行了面向对象的封装,打造出方便易用的基础工具类。

■ 第4章:Nginx高级数据结构

本章研究ngx_array_t、ngx_list_t、ngx_queue_t、ngx_buf_t、ngx_rbtree_t等各种高级Nginx数据结构,它们类似C++的标准容器,在Nginx框架里经常出现,必须很好地理解并掌握它们的特性和用法,C++封装能够让这些数据结构更容易使用。

■ 第5章:Nginx开发综述

本章使用一个简单的例子介绍Nginx开发的基本流程,并讲解了如何编写模块集成脚本。

■ 第6章:Nginx模块体系

本章详细剖析Nginx的模块架构和配置解析原理,这是Nginx开发必需的重要技术,也是理解Nginx架构的关键,最后实现了C++封装类,开发出现代C++风格的Nginx模块。

■ 第7章:Nginx HTTP框架综述

本章深入研究Nginx的HTTP处理框架,解析http模块的核心工作原理和流程,包括处理阶段、处理引擎、过滤链表等重要概念。

■ 第8章:Nginx HTTP请求处理

本章详细解析ngx_http_request_t结构,讲解请求头、请求体、响应头、响应体等数据成员和它们的操作方法,实现Nginx里最常用的handler模块和filter模块。

■ 第9章:Nginx HTTP请求转发

本章解析Nginx的请求转发机制,它是Nginx反向代理的基础,实现转发请求的upstream模块和负载均衡的load-balance模块,访问外部的网络资源。

■ 第10章:Nginx HTTP子请求

本章讲解Nginx的子请求机制,可以让Nginx像调用函数那样调用location里的功能,发起多个子请求实现复杂的业务逻辑,让Nginx变成一台强大的应用服务器。

■ 第11章:Nginx变量

Nginx内置非常灵活的变量机制,是配置指令之外另一种与模块通信的方式,增强了静态的配置文件与动态运行的模块之间的互操作性。本章剖析了变量机制的工作原理,实现了易用的C++封装类。

■ 第12章:Nginx辅助设施

本章介绍Nginx提供的一些实用工具,包括MD5/SHA-1摘要、CRC/Base64/URI编解码、正则表达式、共享内存等,它们是并发处理和协议解析之外实现一个完善的Web服务器所必需的辅助功能。

■ 第13章:Nginx进程机制

Nginx使用了进程池模式,以一个master进程管理多个worker进程,可以充分地利用多核CPU。本章先介绍基本的UNIX系统调用,然后配合图解详细研究Nginx的信号处理、启动过程、单进程和多进程的工作流程及要点。

■ 第14章:Nginx事件机制

事件驱动机制是Nginx高性能的关键,本章详细阐述socket系统调用、epoll工作原理、事件模块体系和相关的数据结构、使用多幅流程图完整解析了连接池、监听端口、接受连接、处理网络和定时器事件、负载均衡等Nginx的核心功能。

■ 第15章:Nginx多线程机制

Nginx主要使用单线程加事件驱动,但也对多线程提供了有限的支持,本章介绍Nginx多线程机制的工作原理:线程池+生产者/消费者,还给出了一个实际的开发示例。

■ 第16章:Nginx Stream机制

Nginx从1.9.0开始引入了Stream框架,支持直接处理TCP/UDP协议,相当于是一个简化版的HTTP框架,研究它可以更好地理解进程机制和事件机制在处理请求时的作用。本章解析Stream机制的模块体系和运行机制,并实现了discard、time等基本的应用协议。

■ 第17章:Nginx HTTP机制

本章是第7章的进阶内容,结合事件机制,使用源码辅以流程图,详细介绍HTTP框架的关键运行机制,包括初始化连接、阶段式处理引擎、读取数据、发送数据和结束请求等。

■ 第18章:Nginx与设计模式

本章综合之前章节的内容,简要总结了在Nginx里应用的一些设计模式,帮助读者从设计模式的角度来进一步理解Nginx架构。

■ 第19章:OpenResty开发

OpenResty是一个“比Nginx更好的Nginx”,它集成了众多优良的Nginx模块和库,可以用动态语言Lua快速开发出高质量高性能的Web应用。本章介绍了OpenResty相关的各方面知识,包括Lua语言、LuaJIT、配置指令、功能接口和开发示例,而且完全从零起步,编程初学者也可以较容易地掌握这些知识。

■ 第20章:结束语

本章给出了读者在阅读完本书后进一步学习研究Nginx的方向。

■ 附录

书末的附录是对本书正文的补充,列出了一些参考书籍,还有就是一些不宜放在正文里的比较琐碎的内容,比如ngx_cpp_module介绍、ngx_sprintf()格式列表等。值得一提的是特别介绍了nginScript,可以使用JavaScript脚本灵活地定制Nginx。0.6如何阅读本书

编程初学者或者初次接触Nginx的读者应当首先阅读第1章,了解什么是Nginx,并在本书的指导下安装配置Nginx,搭建自己的开发环境,然后学习后续章节。

对Nginx比较熟悉的读者可以跳过第1章,从第2章开始顺序阅读,以Nginx源码片段为出发点,学习如何使用C/C++来开发Nginx模块。其中第2章至第4章是C/C++开发的基础,第5章才能开始正式编写Nginx模块。

如果读者已经是一个比较熟练的Nginx开发者,那么可以直接阅读第5、6章及之后的章节,钻研Nginx的内部架构和实现原理,深入理解Nginx的运行机制。不过第2章至第4章也并非可以完全忽略,其中的C++泛型、元编程等崭新的编程范式也许会让你眼前一亮,能够从一个全新的角度来审视Nginx。

使用纯C语言开发的读者可以忽略书中标题含有“C++”的小节,而只阅读与Nginx C接口、源码相关的部分。

如果读者只想使用OpenResty/Lua开发Nginx应用,建议先阅读第1章,了解Nginx安装部署的基本知识,然后跳过之后的Nginx框架源码解析,直接阅读第19章,快速开始OpenResty的学习。不过还是希望读者有了一些实际经验后再回头研究前面的章节,只有深入理解Nginx内部细节,才能更好地开发OpenResty应用。0.7本书的源码

为方便读者利用本书学习研究Nginx和OpenResty,作者在GitHub网站上发布了本书内所有C/C++、OpenResty示例程序和Shell脚本的源代码,地址是:第1章Nginx入门Nginx是一个高性能、高稳定性和高扩展性的轻量级TCP、UDP、HTTP、反向代理和邮件代理服务器。它运行效率高,系统消耗低,使用操作系统提供的异步I/O调用可以无阻塞地处理上万的并发请求,是当今众多Web服务器中的佼佼者,被Airbnb、Dropbox、GitHub、Hulu、WordPress等许多知名网站所采用。本章简要介绍Nginx的历史和特点,讲解如何在Linux上安装和配置Nginx,帮助读者尽快熟悉Nginx。1.1关于Nginx

自20世纪90年代以来,Internet和World Wide Web逐渐在全世界普及。早期并没有Web服务器的概念,Internet上的资源只是一些简单的静态文件。慢慢地,Web服务器出现了,它在用户和文件之间加入了一个中间层,响应用户的HTTP请求,从本地或者其他地方获取对应的资源,再返回给用户。

1995年,著名的Apache诞生了。最开始它只是一个NCSA HTTPd服务器的修改版,但许多志愿者不停地为它添加补丁新增功能,使它迅速成为了那个年代最流行的Web服务器,甚至直到二十多年后的今天也是如此。

由于时代的限制,Apache被设计为“重量级”的服务器,使用fork进程的方式响应HTTP请求。虽然近年来Apache增加了多线程、多核心等新特性,但基本架构无法改变,在动辄成千上万并发的情况下显得有些力不从心,性能严重下降。

本世纪初,随着C10K问题的提出{L-End},计算机界开始认真地研究Web服务器的开发模型。Linux、FreeBSD等操作系统引入了epoll、kqueue等高效异步I/O接口,奠定了解决海量并发的C10K甚至C100K问题的基础,最终导致Nginx这个Web服务器新秀的出现。1.1.1 历史

2002年,在仔细研究了已有的Web服务器之后,当时任职于俄罗斯门户网站Rambler的工程师Igor Sysoev开始编写一个新的Web服务器,目标是解决高并发的C10K问题,并设计了完全不同于以往服务器的全新架构——这就是Nginx。

2004年,Nginx正式开源,版本号为0.1.0,由于其优异的性能、绝佳的稳定性和良好的扩展性等鲜明特点迅速吸引了大量关注。在开源大旗的鼓舞之下,无数开发者加入贡献行列,为它修复错误、编写功能模块,Nginx从此踏上了迅猛发展的道路,从当初默默无闻的小卒成长为如今Web服务器界的巨人。

2011年,Nginx之父Igor Sysoev在旧金山正式成立公司,为Nginx提供商业服务,并发布了商业版本的Nginx Plus。1.1.2 特点

作为Web服务器的后起之秀,Nginx能够战胜Apache、Lighttpd、Jetty、Tomcat等众多对手,获得顶级互联网公司的青睐,必然有它的独到之处。以开发者的视角来看,Nginx的特点是:

■ 高性能

卓越的性能是Nginx最突出的特点。Nginx完全使用C语言编写,采用事件驱动模型,并且有针对性地对操作系统进行了特别优化,可以无阻塞地处理海量并发连接,经过仔细调整配置参数还能够进一步释放潜力,帮助网站应对日益增长的巨大访问压力。

■ 高稳定性

高度的稳定性是Nginx的又一大特点。内存池避免了C程序常见的资源泄漏问题,模块化的架构使得各个功能模块完全解耦,消除了相互间可能造成的不良影响,而独特的one master/multi workers进程池设计则实现了自我监控和管理,保证即使worker进程发生严重错误也可以快速恢复。在实际应用中,Nginx服务器一经启动,就可以稳定地运行数天甚至数月之久。

■ 低资源消耗

Nginx的代码质量极高,不使用传统的进程或线程服务器模型,没有进程或线程切换时的成本,而且它还使用了很多节约系统资源的编程技巧,例如使用accept4来减少内核调用的次数、使用writev集中发送数据、使用字符串引用而不是拷贝,可以把宝贵的CPU和内存资源更多地用于对外提供服务,提高并发支持能力。

■ 高扩展性

Nginx的模块化架构是一个非凡的设计。Nginx本身就是由各种位于不同层次的功能模块组合而成的,它也允许/鼓励任何人依据架构规范开发任意功能的模块——同时充分利用Nginx框架提供的各种高效机制,然后再完美地融合到Nginx之中。

基于高扩展性,Nginx以模块的形式实现了丰富的功能,例如access、flv、gzip、proxy、ssl等,而广大开发者也编写了大量的第三方模块,实现了更多更有用的功能。这些模块都遵循一致的开发原则,可以在配置文件里灵活配置,让Nginx提供更好的网络服务。{L-End}

以上的三高一低四个方面是从开发者的角度总结的Nginx的主要特点。当然Nginx的优势远不止这些,它还能够运行在多种操作系统上,安装和配置都很容易,支持定制日志、平滑升级、策略限速、热部署等许多重要的运维功能。

高性能是品质,高稳定性是保障,低资源消耗是基石,而高扩展性则是Nginx生命力的源泉,使Nginx拥有了近乎“无限”的能力——如果现有的Nginx模块不能满足我们的需求,最佳的解决方案无疑是开发自己的模块,集成到Nginx里,在享受Nginx高性能、高稳定性的同时实现自己的业务逻辑。这正是作者撰写本书的目的。1.1.3 进程模型

Nginx采用了独特的one master/multi workers进程池机制,它是Nginx能够稳定运行、灵活配置的保证。

通常情况下,Nginx会启动一个master进程和多个worker进程对外提供服务{L-End}。master进程又称监控进程,它并不处理具体的TCP/HTTP请求,只接收UNIX信号,管理和监控worker进程,所以工作比较“清闲”。worker进程平等地竞争accept客户端的连接,执行Nginx主要的业务逻辑,使用epoll、kqueue等机制高效率地处理TCP/HTTP请求。

master进程和worker进程使用操作系统提供的进程间通信机制——如信号、UNIX域套接字、共享内存等互相通信,彼此独立又保持一定的联系,形成一个有机的整体。当某个worker进程发生错误意外中止时,master进程会快速重新fork出新的worker进程,保持进程池的稳定(具体工作原理可参见第13章)。

Nginx的进程模型如图1-1所示。图1-1 Nginx的进程模型

在多核心的服务器上,Nginx可以配置为每个进程运行在单独的核心,最大限度地减少CPU进程切换的成本,提高系统运行效率。

Nginx也可以配置为不使用master进程,只有一个worker进程提供服务,这种方式不适用于真正的生产环境,但对于开发测试却很有用。1.1.4 版本

本书不讨论商业版本的Nginx Plus{L-End},只讨论开源版本的Nginx,它的官网是:http://www.nginx.org/。

Nginx官网提供三种类型的版本供用户选择:

■ Mainline:主线开发版本,版本号为奇数。更新速度很快,差不多每个月都会发布新版本,汇集了最新的功能和错误修复,但稳定性可能略差。

■ Stable:当前的稳定版本,版本号为偶数。由Mainline版本fork而来,经过了完全测试,代码有一年的“冻结”期,除非有重要Bug修复否则不会变动,建议在正式生产环境中使用。

■ Legacy:历年曾经发布的稳定版本,有特殊需求的话可以采用。

这三个版本的关系可以用图1-2来表示。图1-2 Mainline、Stable、Legacy三个版本的关系

本书采用的Nginx是2017年4月发布的Stable 1.12.0版,由于Nginx的核心架构和代码一直都比较稳定(但局部实现偶尔会变动),所以书中的讨论也基本适用于较早期的各种版本,对于部分重要的版本差异会加以特别注解。1.2安装Nginx

本节介绍在Linux操作系统上使用源码包的方式安装Nginx,但并不是一个完全的安装部署手册,仅供读者参考。{L-End}1.2.1 准备工作

只要系统里有GCC(或其他C编译器),Nginx就可以编译安装,但几个基本且重要的功能依赖于第三方库:

■ zlib:实现gzip压缩解压缩功能。

■ pcre:实现配置文件里的正则表达式解析功能。

■ openssl:实现SSL功能。

在Ubuntu里安装这些依赖库的命令是:

使用其他操作系统的读者请参考网络相关资料,例如对于CentOS,安装的命令可以是:1.2.2 快速安装

Nginx主要以源码的方式发布,可以从官网上直接下载源码形式的安装包:

这是最简单的Nginx安装方式,没有任何的定制参数。Nginx将会安装到默认的“/usr/local/nginx/”目录,可执行文件是“/usr/local/nginx/sbin/nginx”,默认配置文件是“/usr/local/nginx/conf/nginx.conf”。1.2.3 运行命令

启动和停止Nginx需要以root身份,或者使用sudo。

下面介绍一些常用但不是全部的Nginx命令,更详细的命令说明可以使用-h/-?参数查看,或者查阅网络资料。

不带参数简单地执行程序就可以启动Nginx服务,这将使用默认的配置文件:

我们也可以使用-c参数指定配置文件,这种方式允许启动多个不同的Nginx实例:

-p path是-c的增强版,用来设置工作目录,可以指定完整的Nginx环境:

-s signal参数可以快速地停止或者重启Nginx,signal值可以是stop、quit、reload或reopen:

需要注意的是,如果使用-c/-p参数启动了Nginx,那么在使用-s时也必须使用-c/-p参数,告诉Nginx使用的是哪个配置文件,否则会运行失败。例如:

-t或-T参数可以测试配置文件是否正确,后者同时还会打印出文件内容方便检查:

-v或-V参数可以显示Nginx的版本信息,它不需要root权限,两者的区别是-V可以显示更多的信息,包括GCC版本、操作系统版本、configure参数等定制信息:

-V参数很多时候特别有用,由于它给出了编译Nginx时的全部相关信息,所以我们可以使用其他版本的源码(例如升级或者修复Bug)加上这些参数重新编译出一个功能完全相同的新程序。1.2.4 验证安装

如果已经成功启动了Nginx服务,那么就可以使用wget或者curl这样的工具来验证Nginx是否正常工作。

Nginx的默认配置文件开启了localhost:80服务,在/usr/local/nginx/html下存放有一些示例静态html文件,curl测试命令是:

如果Nginx正在运行,那么curl的部分输出可能如下:

使用Linux的ps命令配合grep可以看到所有Nginx进程,也可以验证Nginx是否正常运行:

从ps的输出我们可以看到当前共有两个Nginx进程,其中进程号为8261的是master进程,而8262号进程则是worker进程。

如果Nginx没有正确运行,我们可以查看它的错误日志以排除故障,默认的位置是“/usr/local/nginx/logs/error.log”。1.2.5 定制安装

make前执行的configure是Nginx的重要组成部件,它检查各种系统参数、命令行参数和依赖库,根据这些参数生成定制的Makefile和一些C源码文件,没有它就无法正确编译安装Nginx。

虽然configure只是一个标准的Shell脚本,但其内部逻辑十分复杂,为了支持各种操作系统、编译器和CPU做了大量工作,复杂程度甚至不逊于Nginx自身的C程序。{L-End}

由于configure的选项很多,本书不能也没有必要完全罗列,仅列出一些个人认为比较重要的选项,其他可参考help或者网络资源。

配置Nginx安装部署的根目录,也就是工作目录。默认值是“/usr/local/nginx/”,可以把它改为其他路径,这样就可以在一个系统里安装多个不同用途的Nginx{L-End},类似的选项还有--sbin-path、--conf-path等。例如:

启用Nginx的stream模块,让Nginx能够直接处理TCP/UDP协议。

启用Nginx的线程池机制,允许Nginx使用多线程来处理数据。

虽然Linux系统通常都内置PCRE、OpenSSL库,但有的时候可能版本比较低,功能不完善(更严重的是有bug),所以可以用这两个选项来指定PCRE、OpenSSL的源码目录,从而使用最新的版本,例如:

这是一系列近百个模块配置选项,用来决定在Nginx里启用或者

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载