上一篇文章中,我介绍了Nginx的特性,如何获取Nginx源代码,以及源代码中各目录的含义。本文将介绍如何定制化编译、安装、运行Nginx。
当你用yum或者apt-get命令安装、启动Nginx后,通过nginx -t命令你会发现,nginx.conf配置文件可能在/etc/目录中。而运行基于源码安装的Nginx时,nginx.conf文件又可能位于/usr/local/nginx/conf/目录,运行OpenResty时, nginx.conf又被放在了/usr/local/openresty/nginx/conf/目录。这些奇怪的现象都源于编译Nginx前,configure脚本设置的–prefix或者–conf-path选项。
Nginx的所有功能都来自于官方及第三方模块,如果你不知道如何使用configure添加需要的模块,相当于放弃了Nginx诞生16年来累积出的丰富生态。而且,很多高性能特性默认是关闭的,如果你习惯于使用应用市场中编译好的二进制文件,也无法获得性能最优化的Nginx。
本文将会介绍定制Nginx过程中,configure脚本的用法。其中对于定制模块的选项,会从模块的分类讲起,带你系统的掌握如何添加Nginx模块。同时,也会介绍configure执行后生成的objs目录,以及Makefile文件的用法。这也是Nginx开源社区基础培训系列课程第一季,即6月11日晚第2次视频直播课前半部分的文字总结。
在Linux系统(包括各种类Unix操作系统)下,编译复杂的C语言软件工程是由Makefile文件完成的。你一定注意到Nginx源码中并没有Makefile文件,这是因为Makefile是由configure脚本即时生成的。接下来我们看看,configure脚本悄悄的做了哪些事,这些工作又会对Nginx产生哪些影响。
configure脚本支持很多选项,掌握它们就可以灵活的定制Nginx。为了方便理解,从功能上我把它们分为5类:
configure既可以设置Nginx运行时各类资源的默认访问路径,也可以设置编译期生成的临时文件存放路径。比如:
等等。
对于已经编译好的Nginx,可以通过nginx -V命令查看设置的路径。如果没有显式的设置选项,Nginx便会使用默认值,例如官方Nginx将–prefix的默认值设为/usr/local/nginx,而OpenResty的configure脚本则将–prefix的默认值设为/usr/local/openresty/nginx。
Nginx由C语言开发,因此默认使用的C编译器,由于C++向前兼容C语言,如果你使用了C++编写的Nginx模块,可以通过–cc-opt等选项,将C编译器修改为C++编译器,这就可以支持C++语言了。
Nginx编译时使用的优化选项是-O,如果你觉得这样优化还不够,可以调大优化级别,比如OpenResty就将gcc的优化调整为-O2。当某些模块依赖其他软件库才能实现需求时,也可以通过–with-ld-opt选项链接其他库文件。
Nginx执行时,会依赖pcre、openssl、zlib等中间件,实现诸如正则表达式解析、TLS/SSL协议处理、解压缩等功能。通常,编译器会自动寻找系统默认路径中的软件库,但当系统中含有多个版本的中间件时,就可以人为地通过路径来指定版本。比如当我们需要使用最新的TLS1.3时,可以下载最新的openssl源码包,再通过–with-openssl=选项指定源码目录,让Makefile使用它去编译Nginx。
Nginx是由少量的框架代码、大量的C语言模块构成的。当你根据业务需求,需要通过某个模块实现相应的功能时,必须先通过configure脚本将它编译进Nginx(Nginx被设计为按需添加模块的架构),之后你才能在nginx.conf配置文件中启用它们。下一小节我会详细介绍这部分内容。
还有些不属于上述4个类别的选项,包括:
在大致了解configure提供的选项后,下面我们重点看下如何定制Nginx模块。
编译Nginx前,我们需要决定添加哪些模块。在定制化模块前,只有分清了模块的类别才能系统的掌握它们。Nginx通常可以分为6类模块,包括:
在上图中,HTTP模块又可以再次细分为3类模块:
对于这3类模块,你可以从模块名中识别,比如模块中出现filter和http字样,通常就是过滤模块,比如ngx_http_gzip_filter_module。如果模块中出现upstream和http字样,就是负载均衡模块。
我们可以使用–with-模块名,将其编译进Nginx,也可以通–without-模块名,从Nginx中移出该模块。需要注意的是,当你通过configure –help帮助中看到–with-打头的选项,都是默认不编译进Nginx的模块,反之,–without-打头的选项,则是默认就编译进Nginx的模块。
还有一些HTTP模块并不属于上述3个类别,比如–with-http_v2_module是加入支持HTTP2协议的模块。当你需要添加第三方模块时,则可以通过–add-module=或者–add-dynamic-module=(动态模块将在后续文章中再介绍)选项指定模块源码目录,这样就可以将它编译进Nginx。
当configure脚本根据指定的选项执行时,会自动检测体系架构、系统特性、编译器、依赖软件等环境信息,并基于它们生成编译Nginx工程的Makefile文件。同时,还会生成objs目录,我们先来看看objs目录中有些什么:
objs
|-- autoconf.err #configure自动检测环境时的执行纪录
|-- Makefile #编译C代码用到的脚本
|-- ngx_auto_config.h #以宏的方式,存放configure指定的配置,供安装时使用
|-- ngx_auto_headers.h#存放编译时包含的头文件中默认生成的宏
|-- ngx_modules.c #根据configure时加入的模块,生成ngx_modules数组
`-- src #存放编译时的目标文件
|-- core #存放核心模块及框架代码生成的目标文件
|-- event #存放事件模块生成的目标文件
|-- http #存放HTTP模块生成的目标文件
|-- mail #存放MAIL模块生成的目标文件
|-- misc #存放ngx_google_perftools_module模块生成的目标文件
|-- os #存放与操作系统关联的源代码生成的目标文件
`-- stream #存放STREAM模块生成的目标文件
接着,执行make命令就可以基于Makefile文件编译Nginx了。make命令可以携带4种参数:
因此,当我们首次安装Nginx时,只需要先执行make命令编译出可执行文件,再执行make install安装到目标路径即可。
启动Nginx也很简单,进入Nginx目录后(比如/usr/local/nginx),在sbin目录下执行nginx程序即可,Nginx默认会启用Daemon守护者模式(参见daemon on;指令),这样shell命令行不会被nginx程序阻塞。
至此,Nginx已经编译、安装完成,并成功运行。
最后做个小结,本文介绍了定制化编译、安装及运行Nginx的方法。
如果你想定制符合自己业务特点的Nginx,那就必须学会使用configure脚本,它会根据输入选项、系统环境生成差异化的编译环境,最终编译出功能、性能都不一样的Nginx。configure支持的选项分为5类,它允许用户修改资源路径、编译参数、依赖软件等,最重要的是可以选择加入哪些官方及第三方模块。
定制模块前,先要掌握模块的类别。Nginx模块分为6类,作为Web服务器使用时,其中最复杂、强大的自然就是HTTP模块,它又可以再次细分为3小类:请求处理模块、响应过滤模块、负载均衡模块。我们可以使用–with或者–without选项增删官方模块,也可以通过–add-module或者–add-dynamic-module添加第三方模块。
configure会生成源代码、脚本、存放目标文件的临时目录,以及编译C工程的Makefile文件。其中,Makefile支持4个选项,允许我们编译、安装、升级Nginx。由于Nginx支持Daemon模式,启动它时直接运行程序即可。
下一篇将会介绍nginx.conf的配置语法,以及使用命令行或者免费的可视化工具分析access.log日志文件的方法。