Nginx是由俄罗斯工程师Igor Sysoev开发的一个高性能Web服务器,运行效率远超传统的Apache、Tomcat,是世界第二大Web服务器,被国内外诸多顶级互联网公司采用。
Nginx的一个突出特点是其灵活优秀的模块化架构,可以在不修改核心的前提下增加任意功能,自2004年发布至今,已经拥有百余个官方及非官方的功能模块(如fastcgi、memcached、mysql等),使得Nginx成长为了一个近乎“全能”的服务器软件。
Nginx以纯C语言实现,开发扩展功能模块也大多使用C语言,但由于C语言固有的过程式特性,编写、调试代码都较麻烦——特别是对于Nginx的初学者。本书深入源码,详细解析了模块体系、配置指令、HTTP框架等Nginx核心运行机制,并在此基础上讲解如何使用C++和Boost程序库来开发Nginx模块,充分利用现代C++里的大量新特性和库组件,让Nginx的模块开发变得更加便捷、轻松和愉快。
前言
缘起
最早接触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是目前这个星球上所能获得的最强劲的Web服务器(没有之一),同时也是目前最成熟、最优秀的TCP/HTTP服务器开发框架。
Nginx资源消耗低,并发处理性能高,配置灵活,能够连接CGI、PHP、MySQL、Memcached等多种后端,还有着出色的负载均衡能力,可以整合封装各种service,构建稳定高效的服务。如今Nginx已经成为了网站架构里不可或缺的关键组件,广泛应用于国内外许多大型IT企业内部。每一个繁忙的网站背后,可能都有Nginx默默工作的身影。
在Nginx出现之前,使用C/C++开发Web服务器是项比较“痛苦”的工作,虽然有很多网络程序库可以使用(例如ACE、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的作者Igor Sysoev,没有他就不会有如此优秀的Web服务器,也就不会有本书的诞生。
亲情永远是人生命中最值得珍惜的部分,我要感谢父母多年来的养育之恩和“后勤”工作,感谢妻子在生活中的陪伴(但因为频繁的加班常常缺少相处的时间),感谢即将上小学的女儿,愿你们能够永远幸福快乐。
我还要感谢工作中共同奋斗拼搏的诸多同事,从他们那里我获取到了很多的经验和知识,度过了很多难忘的岁月,和他们在一起让工作超越了谋生的手段变成了一种享受。
最后感谢读者选择本书,希望读者能够在阅读过程中有所收获,在Nginx开发过程中获得乐趣。
您的朋友 罗剑锋
2015年8月18日 于 北京 酒仙桥