编辑推荐

  

  资深技术专家Nginx源码研习书强势升级!

  深入新版Nginx源码(Stable1.12.0)!

  详细剖析Nginx核心运行机制!

  便捷、轻松地开发和定制Nginx!


  

内容简介

  

  Nginx是知名的Web服务器,性能优异,运行效率远超传统的Apache、Tomcat,广泛应用于国内外诸多尖端互联网公司。

  Nginx的一个突出特点是其灵活优秀的模块化架构,可以在不修改核心的前提下增加任意功能,自2004年发布至今,已经拥有百余个官方及非官方的功能模块(如proxy、mysql、redis、rtmp、lua等),使得Nginx成长为了一个近乎“全能”的服务器软件。

  Nginx功能强大,架构复杂,学习、维护和开发的门槛较高。为了帮助读者跨越这一障碍,《Nginx完全开发指南:使用C、C++和OpenResty》深入新版Nginx源码(Stable1.12.0),详细剖析了模块体系、动态插件、功能框架、进程模型、事件驱动、线程池、TCP/UDP/HTTP处理等Nginx核心运行机制,在此基础上讲解如何使用C、C++、Lua、nginScript等语言来增强扩展Nginx,让任何人都能够便捷、轻松地开发和定制Nginx,进而应用到自己的实际工作中,创造出更多的价值。

  《Nginx完全开发指南:使用C、C++和OpenResty》结构严谨、脉络清晰、论述精确、详略得当、图文并茂,值得广大软件开发工程师、系统运维工程师和编程爱好者拥有。


  

作者简介

罗剑锋(网名Chrono)在1996年就读于东北财经大学;1997年开始接触C/C++;1998年参加计算机软件专业技术资格和水平考试,获高级程序员资质;2003年毕业于北京理工大学,获计算机专业硕士学位。主要研究方向为C/C++、设计模式、高性能网络服务器开发,业余爱好是阅读、旅游、欣赏音乐和电影。

精彩书评

  

  我很感谢罗剑锋能在他的这本新书中帮忙推广和普及OpenResty这个开源Web平台的相关技术。我们最初做OpenResty和ngx_lua等模块的目的其实就是希望开发者能尽量少写NGINX的C/C++模块,多写Lua以及我们即将推出的像fanlang和edgelang这样更上层的高级编程语言。毕竟我们自己也深知NGINX级别的C/C++编程的不易。无论如何,能有像罗剑锋这样的热心开发者,把NGINXC/C++编程的主要方面比较详细地写下来,也是非常有意义的事情。

  ——章亦春OpenResty开源平台的作者,OpenRestyInc.公司首席执行官
  

目录

第0章导读1

0.1关于《Nginx完全开发指南:使用C、C 和OpenResty》1

0.2读者对象2

0.3读者要求3

0.4运行环境4

0.5《Nginx完全开发指南:使用C、C 和OpenResty》的结构4

0.6如何阅读《Nginx完全开发指南:使用C、C 和OpenResty》7

0.7《Nginx完全开发指南:使用C、C 和OpenResty》的源码8

第1章Nginx入门9

1.1关于Nginx9

1.2安装Nginx13

1.3配置Nginx19

1.4总结30

第2章Nginx开发准备31

2.1开发环境31

2.2目录结构32

2.3源码特点34

2.4使用C++35

2.5C++包装类38

2.6总结40

第3章Nginx基础设施41

3.1头文件41

3.2整数类型42

3.3错误处理47

3.4内存池50

3.5字符串58

3.6时间与日期64

3.7运行日志70

3.8总结74

第4章Nginx高级数据结构77

4.1动态数组77

4.2单向链表83

4.3双端队列90

4.4红黑树101

4.5缓冲区108

4.6数据块链113

4.7键值对120

4.8总结121

第5章Nginx开发综述123

5.1最简单的模块123

5.2开发基本流程131

5.3编译脚本134

5.4总结137

第6章Nginx模块体系139

6.1模块架构139

6.2配置解析152

6.3源码分析168

6.4C++封装172

6.5C++开发模块180

6.6总结187

第7章NginxHTTP框架综述191

7.1框架简介191

7.2处理引擎198

7.3过滤引擎205

7.4源码分析211

7.5C++封装213

7.6总结219

第8章NginxHTTP请求处理221

8.1状态码221

8.2请求结构体222

8.3请求行223

8.4请求头225

8.5请求体226

8.6响应头227

8.7响应体229

8.8源码分析229

8.9C++封装232

8.10开发handler模块241

8.11开发filter模块246

8.12总结253

第9章NginxHTTP请求转发255

9.1框架简介255

9.2请求转发机制261

9.3负载均衡机制266

9.4源码分析275

9.5C++封装281

9.6开发upstream模块288

9.7开发load-balance模块294

9.8总结299

第10章NginxHTTP子请求301

10.1子请求简介301

10.2子请求运行机制307

10.3C++封装314

10.4数据回传模块317

10.5在模块里使用子请求323

10.6总结328

第11章Nginx变量329

11.1结构定义329

11.2运行机制332

11.3复杂变量334

11.4C++封装335

11.5在模块里使用变量341

11.6在模块里使用复杂变量343

11.7总结345

第12章Nginx辅助设施347

12.1摘要算法347

12.2编码和解码352

12.3正则表达式356

12.4共享内存356

12.5总结359

第13章Nginx进程机制361

13.1基本系统调用361

13.2进程系统调用362

13.3信号系统调用364

13.4结构定义365

13.5全局变量368

13.6启动过程370

13.7信号处理377

13.8单进程模式379

13.9多进程模式382

13.10总结390

第14章Nginx事件机制393

14.1基本系统调用393

14.2socket系统调用395

14.3epoll系统调用399

14.4结构定义403

14.5定时器415

14.6模块体系419

14.7全局变量425

14.8运行机制427

14.9总结452

第15章Nginx多线程机制455

15.1eventfd系统调用455

15.2pthread系统调用456

15.3结构定义457

15.4事件通知460

15.5运行机制463

15.6在模块里使用多线程469

15.7总结474

第16章NginxStream机制477

16.1模块体系477

16.2监听端口483

16.3处理引擎491

16.4过滤引擎495

16.5运行机制496

16.6开发stream模块507

16.7总结514

第17章NginxHTTP机制517

17.1结构定义517

17.2初始化连接519

17.3执行引擎528

17.4处理请求体534

17.5发送数据540

17.6结束请求543

17.7总结548

第18章Nginx与设计模式551

18.1设计模式简介551

18.2框架级别的模式551

18.3业务级别的模式553

18.4代码级别的模式554

18.5总结556

第19章OpenResty开发557

19.1简介557

19.2Lua语言566

19.3LuaJIT577

19.4Lua模块581

19.5功能接口585

19.6应用实例594

19.7StreamLua模块598

19.8lua-resty库601

19.9总结603

第20章结束语605

20.1《Nginx完全开发指南:使用C、C 和OpenResty》的遗憾605

20.2下一步605

20.3临别赠言606

附录A推荐书目607

附录BGDB调试简介609

附录CNginxC++模块简介611

附录DNginx的字符串格式化613

附录EnginScript简介615

前言/序言

  缘起

  最早接触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完全开发指南:使用C、C 和OpenResty》的念头。

  经过近一年的努力,现在这《Nginx完全开发指南:使用C、C 和OpenResty》终于呈现在了读者面前,结构上基本反映了我学习研究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++

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

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

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

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

  我接触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和WebServer,而将成为一个更通用的开发平台,工作语言也不仅限于Lua,可能还会有其他新的语言(例如agentzh正在做的edgelang和fanlang),让我们拭目以待。

  致谢

  首先当然要感谢Nginx的作者IgorSysoev,没有他就不会有如此优秀的Web服务器,也就不会有《Nginx完全开发指南:使用C、C 和OpenResty》的诞生。

  OpenResty创始人章亦春(agentzh)是一位非常亲切随和的人,在Nginx、DSL、DynamicTracing等领域造诣极高,《Nginx完全开发指南:使用C、C 和OpenResty》部分章节有幸经他审阅,在此表示最诚挚的谢意。

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

  最后,我也要感谢读者选择《Nginx完全开发指南:使用C、C 和OpenResty》,希望读者能够在阅读过程中有所收获,在Nginx开发过程中获得乐趣。

  您的朋友罗剑锋

  2017年4月28日于北京亚运村


其他推荐