新書推薦:
《
漫画三国一百年
》
售價:HK$
55.2
《
希腊文明3000年(古希腊的科学精神,成就了现代科学之源)
》
售價:HK$
82.8
《
粤行丛录(岭南史料笔记丛刊)
》
售價:HK$
80.2
《
岁月待人归:徐悲鸿自述人生艺术
》
售價:HK$
61.4
《
女人的中国医疗史:汉唐之间的健康照顾与性别
》
售價:HK$
103.8
《
资治通鉴熊逸版:第四辑
》
售價:HK$
470.8
《
中国近现代名家精品——项维仁:工笔侍女作品精选
》
售價:HK$
66.1
《
宋瑞驻村日记(2012-2022)
》
售價:HK$
115.6
|
編輯推薦: |
精心雕琢,认真原创!
专注、深入、聚集!
资深技术专家Nginx源码研习书强势升级!
深入新版Nginx源码(Stable1.16.0)!
详细剖析Nginx核心运行机制!
便捷、轻松地开发和定制Nginx!
|
內容簡介: |
Nginx是著名的Web服务器,性能优异,运行效率远超传统的Apache、Tomcat,广泛应用于国内外诸多*互联网公司。Nginx的一个突出特点是其灵活优秀的模块化架构,可以在不修改核心的前提下增加任意功能,自2004年发布至今,已经拥有百余个官方及非官方的功能模块(如proxy、mysql、redis、rtmp、lua等),使得Nginx成长为了一个近乎全能的服务器软件。Nginx功能强大,架构复杂,学习、维护和开发的门槛较高。为了帮助读者跨越这一障碍,本书深入*的Nginx源码(Stable 1.16.0),详细剖析了模块体系、动态插件、功能框架、内存分配、进程模型、事件驱动、线程池、TCPUDPHTTP处理等Nginx核心运行机制,在此基础上讲解如何使用C、C、JavaScript、Lua等语言来增强扩展Nginx,让任何人都能够便捷、轻松地开发和定制Nginx,进而应用到自己的实际工作中,创造出更多的价值。本书结构严谨、脉络清晰、论述精确、详略得当、图文并茂,值得广大软件开发工程师、系统运维工程师和编程爱好者拥有。
|
關於作者: |
罗剑锋(网名Chrono)1996年就读于东北财经大学;1997年开始接触CC;1998年参加计算机软件专业技术资格和水平考试,获高级程序员资质;2003年毕业于北京理工大学,获计算机专业硕士学位。主要研究方向为CC、设计模式、高性能网络服务器开发,业余爱好是阅读、欣赏音乐和旅游。
|
目錄:
|
目录
第0章导读1
0.1于本书1
0.2读者对象3
0.3读者要求4
0.4运行环境5
0.5本书的结构5
0.6如何阅读本书6
0.7本书的源码7
第1章Nginx入门8
1.1关于Nginx8
1.1.1历史9
1.1.2特点9
1.1.3进程模型10
1.1.4版本12
1.2安装Nginx12
1.2.1准备工作13
1.2.2快速安装13
1.2.3运行命令14
1.2.4验证安装15
1.2.5定制安装16
1.3配置Nginx18
1.3.1语法格式19
1.3.2进程管理20
1.3.3动态模块22
1.3.4运行日志22
1.3.5事件机制22
1.4HTTP服务23
1.4.1基本配置24
1.4.3location配置25
1.4.4file配置26
1.5TCPUDP服务27
1.6反向代理28
1.6.1上游集群28
1.6.2负载均衡29
1.6.3代理转发30
1.7变量30
1.8总结32
第2章Nginx开发准备33
2.1源码结构33
2.2源码特点34
2.2.1代码风格34
2.2.2代码优化35
2.2.3面向对象思想35
2.3头文件36
2.4总结36
第3章Nginx基础设施37
3.1常数37
3.1.1环境信息37
3.1.2版本信息38
3.1.3错误码38
3.2整数类型39
3.2.1标准整数类型39
3.2.2自用整数类型40
3.2.3无效值40
3.3内存池42
3.3.1结构定义42
3.3.2操作函数43
3.3.3用法示例44
3.4字符串44
3.4.1结构定义44
3.4.2操作函数45
3.4.3用法示例48
3.5时间49
3.5.1结构定义49
3.5.2操作函数49
3.5.3用法示例50
3.6日期50
3.6.1结构定义50
3.6.2操作函数51
3.6.3用法示例52
3.7运行日志52
3.7.1结构定义52
3.7.2操作函数53
3.7.3用法示例54
3.8摘要算法54
3.8.1Times3355
3.8.2CRC55
3.8.3MurmurHash56
3.8.4MD557
3.8.5SHA-157
3.9数据编码58
3.9.1Base6458
3.9.2HTMLJSON59
3.10总结60
第4章Nginx高级数据结构61
4.1动态数组61
4.1.1结构定义62
4.1.2操作函数63
4.1.3用法示例64
4.2单向链表65
4.2.1结构定义65
4.2.2操作函数66
4.2.3用法示例66
4.3双端队列68
4.3.1结构定义68
4.3.2操作函数69
4.3.3用法示例71
4.4红黑树72
4.4.1结构定义73
4.4.2操作函数75
4.4.3用法示例76
4.5缓冲区78
4.5.1结构定义78
4.5.2操作函数80
4.5.3用法示例81
4.6数据块链82
4.6.1结构定义82
4.6.2操作函数83
4.6.3用法示例83
4.7总结84
第5章Nginx开发概述85
5.1开发示例85
5.1.1模块设计85
5.1.2配置解析86
5.1.3处理函数88
5.1.4模块集成90
5.1.5编译脚本91
5.1.6测试验证92
5.2开发流程92
5.2.1设计93
5.2.2开发93
5.2.3编译94
5.2.4测试验证94
5.2.5调优94
5.2.6流程图95
5.3编译脚本95
5.3.1运行机制96
5.3.2脚本变量96
5.3.3添加模块97
5.3.4脚本格式97
5.3.5旧式脚本98
5.4总结99
第6章Nginx模块体系100
6.1模块架构100
6.1.1结构定义100
6.1.2模块的签名102
6.1.3模块的种类103
6.1.4模块的函数指针表104
6.1.5模块的类图105
6.1.6模块的组织形式106
6.1.7模块的静态加载108
6.1.8模块的动态加载110
6.2配置解析113
6.2.1结构定义113
6.2.2基本流程116
6.2.3存储模型118
6.2.4访问配置数据122
6.2.5配置数据的位置123
6.2.6配置数据的解析124
6.2.7配置数据的合并126
6.2.8配置指令的类型127
6.3源码分析128
6.3.1ngx_core_module128
6.3.2ngx_errlog_module130
6.4总结132
第7章Nginx功能框架134
7.1框架简介134
7.1.1模块分类134
7.1.2处理流程135
7.1.3请求的处理阶段137
7.1.4请求结构体138
7.1.5请求的环境数据140
7.2处理引擎141
7.2.1函数原型141
7.2.2处理函数的存储方式141
7.2.3内容处理函数142
7.2.4引擎的数据结构143
7.2.5引擎的初始化144
7.2.6引擎的运行机制145
7.2.7日志阶段的处理148
7.3过滤引擎148
7.3.1函数原型148
7.3.2过滤函数链表149
7.3.3过滤函数的顺序150
7.3.4过滤链表的运行机制152
7.3.5请求体过滤153
7.4源码分析153
7.4.1ngx_http_static_module154
7.4.2ngx_http_not_modified_filter_module155
7.5总结156
第8章Nginx请求处理158
8.1状态码158
8.2请求结构体159
8.3请求行160
8.3.1请求方法160
8.3.2协议版本号161
8.3.3资源标识符161
8.4请求头162
8.5请求体163
8.5.1结构定义163
8.5.2操作函数164
8.6响应头164
8.6.1结构定义164
8.6.2操作函数165
8.7响应体166
8.8源码分析166
8.8.1ngx_http_static_module166
8.8.2ngx_http_not_modified_filter_module168
8.9开发示例:content handler169
8.9.1模块设计169
8.9.2配置数据169
8.9.3处理函数170
8.9.4注册函数171
8.9.5模块集成172
8.9.6编译脚本173
8.9.7测试验证173
8.10开发示例:filter173
8.10.1模块设计173
8.10.2配置数据174
8.10.3环境数据174
8.10.4注册过滤函数175
8.10.5过滤响应头175
8.10.6过滤响应体176
8.10.7模块集成178
8.10.8编译脚本179
8.10.9测试验证179
8.11总结180
第9章Nginx请求转发181
9.1框架简介181
9.1.1工作原理182
9.1.2请求结构体183
9.1.3上游结构体184
9.1.4上游配置参数185
9.2请求转发186
9.2.1回调函数186
9.2.2初始化188
9.2.3设置参数189
9.2.4启动连接190
9.2.5处理响应头190
9.2.6处理响应体191
9.3负载均衡192
9.3.1结构定义192
9.3.2初始化模块入口196
9.3.3初始化地址列表197
9.3.4初始化算法199
9.3.5执行算法200
9.4源码分析200
9.4.1ngx_http_memcached_module201
9.4.2ngx_http_upstream_ip_hash_module203
9.5开发示例:upstream206
9.5.1模块设计206
9.5.2配置数据206
9.5.3上行数据208
9.5.4下行数据208
9.5.5启动转发209
9.5.6注册函数210
9.5.7模块集成210
9.5.8编译脚本211
9.5.9测试验证212
9.6开发示例:balance212
9.6.1模块设计212
9.6.2配置数据212
9.6.3算法数据结构213
9.6.4模块入口213
9.6.5算法实现214
9.6.6模块集成215
9.6.7编译脚本216
9.6.8测试验证216
9.7总结216
第10章Nginx子请求218
10.1框架简介218
10.1.1工作原理219
10.1.2请求结构体220
10.1.3回调函数221
10.1.4待处理请求链表223
10.1.5子请求存储结构223
10.2运行机制223
10.2.1创建子请求224
10.2.2处理引擎228
10.2.3数据整理229
10.3开发示例230
10.3.1模块设计231
10.3.2配置数据231
10.3.3环境数据231
10.3.4回调函数231
10.3.5处理函数232
10.3.6注册函数233
10.3.7测试验证234
10.4总结234
第11章Nginx变量236
11.1结构定义236
11.1.1变量237
11.1.2复杂变量238
11.1.3变量的存储239
11.1.4请求结构体239
11.2操作变量240
11.2.1添加变量240
11.2.2获取变量241
11.2.3修改变量242
11.2.4编译复杂变量242
11.2.5获取复杂变量242
11.3开发示例:变量243
11.3.1模块设计243
11.3.2定义变量243
11.3.3添加变量244
11.3.4获取变量244
11.3.5测试验证245
11.4开发示例:复杂变量246
11.4.1模块设计246
11.4.2定义复杂变量246
11.4.3编译复杂变量246
11.4.4获取复杂变量247
11.4.5测试验证247
11.5总结247
第12章Nginx内存管理机制249
12.1基本系统调用250
12.1.1malloc250
12.1.2posix_memalign251
12.1.3free251
12.2块式内存池252
12.2.1结构定义252
12.2.2常量定义255
12.2.3创建内存池255
12.2.4分配内存257
12.2.5分配大块内存258
12.2.6分配小块内存259
12.2.7释放内存264
12.2.8清理机制264
12.2.9清空内存池265
12.2.10销毁内存池266
12.3页式内存池267
12.3.1结构定义268
12.3.2常量定义270
12.3.3初始化内存池271
12.3.4分配内存273
12.3.5分配大块内存275
12.3.6分配小块内存277
12.3.7释放内存280
12.4总结282
第13章Nginx进程机制284
13.1基本系统调用284
13.1.1errno284
13.1.2getrlimit285
13.2进程系统调用285
13.2.1getpid285
13.2.2fork286
13.2.3waitpid286
13.3信号系统调用287
13.3.1kill287
13.3.2sigactio
|
內容試閱:
|
缘起
最早接触Nginx大概是在2011年,面对着一个全新的Web服务器,和大多数人一样最初我也是一片茫然,能找到的参考资料十分有限,安装、配置、运行几乎都是摸着石头过河,犯过许多低级错误。
随着对Nginx逐渐熟悉,它的高并发处理能力给我留下了深刻的印象,作为一个开源软件的爱好者,很自然地想要探究一下它的内部工作原理。我由此开始了对Nginx源码的钻研之路,中间经过了很多的艰辛曲折,走过了不少的弯路。
我最常用的工作语言是C,所以在阅读Nginx源码时也总以C的面向对象方式来思考和理解,以对象作为切入点记笔记、画UML:从最简单的ngx_str_t、ngx_array_t入手,然后到ngx_request_t、ngx_upstream_t等复杂的结构,再围绕着这些对象研究相关的功能函数和处理流程,梳理代码逻辑的同时也摸索着使用C编写Nginx模块的方法,逐渐积累了一些用起来颇为顺手的小工具当然还是比较初级的形式。
五年多前,我被调到了新的工作岗位,需要重度使用Nginx开发,这让我以前的零散积累终于有了用武之地。那段时间里使用CC陆续做了很多东西,也借着机会重新优化了原有的工具代码。
繁忙的工作之余,我有了种进一步整理经验的迫切感,因为只有系统完整地分享这些知识,才能让更多的人基于Nginx二次开发,让Nginx更好地为网络世界服务。
同一时间,市面上也出现了一些Nginx开发相关的资料、书籍,但在我看来却有粗制滥造之嫌:行文混乱,车轱辘话口头禅满天飞,甚至大段照抄指令说明,还有对源码的曲解,未免有点儿误人子弟,读起来实在是难受。终于,在忍无可忍的心态之下,我动起了写作本书的念头。
经过近一年的努力,现在这本书终于呈现在了读者面前,结构上基本反映了我学习研究Nginx时的心路历程,从最初的一无所知起步,逐渐深入到定制开发的层次,希望能与读者心有戚戚焉。
Nginx随感
毫无疑问,Nginx是目前这个星球上所能获得的最强劲的Web服务器(没有之一),同时也是目前最成熟、最优秀的TCPHTTP服务器开发框架。
Nginx资源消耗低,并发处理性能高,配置灵活,能够连接CGI、PHP、MySQL、Memcached等多种后端,还有着出色的负载均衡能力,可以整合封装各种service,构建稳定高效的服务。如今Nginx已经成为了网站架构里不可或缺的关键组件,广泛应用于国内外许多大型IT企业内部。每一个繁忙的网站背后,可能都有Nginx默默工作的身影。
在Nginx出现之前,使用CC开发Web服务器是项比较痛苦的工作,虽然有很多网络程序库可以使用(例如asio、libevent、thrift等),但它们通常只关注较底层的基础功能实现,离成熟的框架相距甚远,不仅开发过程烦琐低效,而且程序员还必须要处理配置管理、进程间通信、协议解析等许多Web服务之外的其他事情,才能开发出一个较为完善的服务器程序。但即使开发出了这样的服务器,通常性能上也很难得到保证,会受到程序库和开发者水平等因素的限制很长一段时间里,CC在Web服务器领域都没有大展拳脚的机会。
Nginx的横空出世为Web服务器开辟了一个崭新的天地,它搭建了一个高性能的服务器开发框架,而且是一个完整的、全功能的服务器。模块化的架构设计很好地分离了底层支撑模块和上层逻辑模块,底层模块处理了配置、并发等服务器的外围功能,核心支撑模块定义了主体的TCPHTTP处理框架。开发者可以把大部分精力集中在上层的业务功能实现上,再也不必去为其他杂事而分心,提高了软件的开发效率。
在Nginx框架里CC程序员可以尽情发挥自己的专长,充分利用Nginx无阻塞处理的优势,打造出高质量的Web应用服务器,与其他系统一较高下。
Nginx和CC
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等曾经的关键字在C11里就已经被废弃),许多编译器对C的支持程度也有差异,这与Nginx的高可移植性目标明显不符。
但C毕竟还是有很多的优点,类可以更好地封装信息、异常简化了错误处理、模板能够在编译期执行类型计算。在C11标准颁布之后C更是几乎变成了一门全新的语言,autodecltypenullptrnoexcept等新关键字增强了语言的描述能力,标准库也扩充了相当多的组件,易用性和稳定性都大大提升。
在Nginx里使用C时要对C的长处和不足有清醒的认识,避免多层次继承、虚函数等影响效率的编程范式,只使用经过充分验证的、能够切实提高开发效率和性能的语言特性和库,避免华而不实的技术炫耀,尽量做到像Nginx源码那样质朴踏实。只有这样,才能够发挥出1 1>2的作用,让Nginx从C中得到更进一步的发展动力。
Nginx和OpenResty
多年以前Nginx开发使用的语言只能是C和C,而现在,越来越多的开发者开始转向了OpenResty,使用Lua搭建高并发、高性能、高扩展性的Web Server。
我接触OpenResty的时间并不算很长,大约在五年左右。由于CC程序员天生的傲慢,一开始对OpenResty确实有点儿抵触情绪,总觉得脚本程序比不上CC实现。然而随着使用的增多,特别是在研究了它的源码之后,我不得不感慨OpenResty的精致、完美和强大,简直是所有Nginx开发者梦寐以求的至宝。
由于agentzh对Nginx的运行机制了如指掌,OpenResty的核心部分ngx_lua一个模块就涵盖了accessrewritecontentlog等多个处理阶段,再搭配上小巧灵活的Lua和高效的LuaJIT,我们就能够在更高级的业务层次上使用胶水代码来调用组合Nginx底层功能,轻松开发出丰富Web服务,极大地节约了宝贵的时间和精力。
当然,OpenResty并不只有ngx_lua,围绕着ngx_lua还有众多的库和辅助工具,构成了一个相当完善的生态环境,这些组件相互支撑,利用得当可以更好地提高生产效率。
OpenResty现在正处于蓬勃发展的阶段,今后的OpenResty也许不仅限于Nginx和Web Server,而将成为一个更通用的开发平台,工作语言也不仅限于Lua,可能还会有其他新的语言(例如agentzh正在做的edgelang和fanlang),让我们拭目以待。
大事件
2019年,Nginx身上发生了一件了不得的大事件:在独立运营了8年之后,Nginx.Inc公司正式被它的竞争对手F5 Networks收购。
收购的价格并不算高,只有6.7亿美元。可以比较一下去年被微软收购的源码托管网站GitHub,出价是75亿。对于Nginx这个几乎占据了互联网一半份额的顶尖Web服务器来说,感觉实在是有点低。
这也算得上是开源软件商业化的又一个标志性案例了。再往前,还有IBM以340亿美元收购RedHat、Sun以10亿美元收购MySQL(但后来又被Oracle收购)。昔日的一个个免费开源明星软件,怀着使命和愿景陆续走向商业化,但又在这条道路上最终倒下。理想终究败给了现实,令人不得不感慨这个美丽而又残酷的世界。[ 出自《进击的巨人 Season 1》片尾曲美しき残酷な世界。]
目前硕果仅存的同级知名开源软件应该只有Apache和Linux了。值得注意的是它们并没有成立商业公司,而是以基金会的形式运作,通过赞助和会员制等形式来筹措资金。另一方面也确实是因为它们的体量足够大,能够把免费开源的大旗继续打下去。
当然,Nginx和F5都发表了官方声明,表示Nginx会继续保持开源,共同维护开源社区的活力。在这一点上我选择相信他们,相信被收购后的Nginx会有更加光明的未来。
再补上一句私心话:还等着在Nginx上跑HTTP3呢。
新版的变化
我一直是C语言的坚定拥护者,很早就在积极推动使用C开发定制Nginx,但这几年下来感觉收效甚微:一是C语言开发的惯性太大,二是操作系统对C标准支持不力,无法用上1114的特性。几番折腾下来,有点心灰意冷了。
所以这次的新版就改以C作为主力开发语言,同时忍痛割爱,大幅度删减了各章节的C代码,C的全部内容都压缩到一个章节里(第20章),不再详细介绍C封装类的具体实现和内部工作原理,也许这样会更贴近目前Nginx开发的现状。
上一版编写时比较匆忙,有些重要知识没来得及讲,这次清退C后腾出了大量的
|
|