如何configure定制出属于你的Nginx
1.0k 次浏览
发表于 2020-06-24 07:30

上一篇文章中,我介绍了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开源社区基础培训系列课程第一季,即611日晚第2次视频直播课前半部分的文字总结。

configure脚本有哪些选项?

Linux系统(包括各种类Unix操作系统)下,编译复杂的C语言软件工程是由Makefile文件完成的。你一定注意到Nginx源码中并没有Makefile文件,这是因为Makefile是由configure脚本即时生成的。接下来我们看看,configure脚本悄悄的做了哪些事,这些工作又会对Nginx产生哪些影响。

configure脚本支持很多选项,掌握它们就可以灵活的定制Nginx。为了方便理解,从功能上我把它们分为5类:

l    改变Nginx编译、运行时各类资源的默认存取路径

configure既可以设置Nginx运行时各类资源的默认访问路径,也可以设置编译期生成的临时文件存放路径。比如:

n    --error-log-path=定义了运行期出现错误信息时写入error.log日志文件的路径。

n    --http-log-path=定义了运行期处理完HTTP请求后,将执行结果写入access.log日志文件的路径。

n    --http-client-body-temp-path=定义了运行期Nginx接收客户端的HTTP请求时,存放包体的磁盘路径。

n    --http-proxy-temp-path=定义了运行期负载均衡使用的Nginx,临时存放上游返回HTTP包体的磁盘路径。

n    --builddir=定义了编译期生成的脚本、源代码、目标文件存放的路径。

等等。

对于已经编译好的Nginx,可以通过nginx -V命令查看设置的路径。如果没有显式的设置选项,Nginx便会使用默认值,例如官方Nginx--prefix的默认值设为/usr/local/nginx,而OpenRestyconfigure脚本则将--prefix的默认值设为/usr/local/openresty/nginx

l    改变编译器选项

NginxC语言开发,因此默认使用的C编译器,由于C++向前兼容C语言,如果你使用了C++编写的Nginx模块,可以通过--cc-opt等选项,将C编译器修改为C++编译器,这就可以支持C++语言了。

Nginx编译时使用的优化选项是-O,如果你觉得这样优化还不够,可以调大优化级别,比如OpenResty就将gcc的优化调整为-O2。当某些模块依赖其他软件库才能实现需求时,也可以通过--with-ld-opt选项链接其他库文件。

l    修改编译时依赖的中间件

Nginx执行时,会依赖pcreopensslzlib等中间件,实现诸如正则表达式解析、TLS/SSL协议处理、解压缩等功能。通常,编译器会自动寻找系统默认路径中的软件库,但当系统中含有多个版本的中间件时,就可以人为地通过路径来指定版本。比如当我们需要使用最新的TLS1.3时,可以下载最新的openssl源码包,再通过--with-openssl=选项指定源码目录,让Makefile使用它去编译Nginx

l    选择编译进Nginx的模块

Nginx是由少量的框架代码、大量的C语言模块构成的。当你根据业务需求,需要通过某个模块实现相应的功能时,必须先通过configure脚本将它编译进NginxNginx被设计为按需添加模块的架构),之后你才能在nginx.conf配置文件中启用它们。下一小节我会详细介绍这部分内容。

l    其他选项

还有些不属于上述4个类别的选项,包括:

n    定位问题时,最方便的是通过error.log查看DEBUG级别日志,而打开调试日志的前提,是在configure时加入--with-debug选项。

n    HTTP服务是默认打开的,如果你想禁用HTTP或者HTTP缓存服务,可以使用--without-http--without-http-cache选项。

n    大文件读写磁盘时,并不适宜使用正常的read/write系统调用,因为文件内容会写入PageCache磁盘高速缓存。由于PageCache空间有限,而大文件会迅速将可能高频命中缓存的小文件淘汰出PageCache,同时大文件自身又很难享受到缓存的好处。因此,在Linux系统中,可以通过异步IO、直接IO来处理文件。但开启Linux原生异步IO的前提,是在configure时加入--with-file-aio选项。

n    开启IPv6功能时,需要加入--with-ipv6选项。

n    生产环境中,需要使用master/worker多进程模式运行Nginxmaster是权限更高的管理进程,而worker则是处理请求的工作线程,它的权限相对较低。通过--user=--group=选项可以指定worker进程所属的用户及用户组,当然,你也可以在nginx.conf中通过usergroup指令修改它。

在大致了解configure提供的选项后,下面我们重点看下如何定制Nginx模块。

如何添加Nginx模块?

编译Nginx前,我们需要决定添加哪些模块。在定制化模块前,只有分清了模块的类别才能系统的掌握它们Nginx通常可以分为6类模块,包括:

l    核心模块:有限的7个模块定义了Nginx最基本的功能。需要注意,核心模块并不是默认一定编译进Nginx,例如只有在configure时加入--with-http_ssl_module或者--with-stream_ssl_modul选项时,ngx_openssl_module核心模块才会编译进Nginx

l    配置模块:仅包括ngx_conf_module这一个模块,负责解析nginx.conf配置文件。

l    事件模块:Nginx采用事件驱动的异步框架来处理网络报文,它支持epollpollselect等多种事件驱动方式。目前,epoll是主流的事件驱动方式,选择事件驱动针对的是古董操作系统。

l    HTTP模块:作为Web服务器及七层负载均衡,Nginx最复杂的功能都由HTTP模块实现,稍后我们再来看如何定制HTTP模块。

l    STREAM模块:负责实现四层负载功能,默认不会编译进Nginx。你可以通过--with-stream启用STREAM模块。

l    MAIL模块:Nginx也可以作为邮件服务器的负载均衡,通过--with-mail选项启用。

在上图中,HTTP模块又可以再次细分为3类模块:

l    请求处理模块:Nginx接收、解析完HTTP报文后,会将请求交给各个HTTP模块处理。比如读取磁盘文件并发送到客户端的静态资源功能,就是由ngx_http_static_module模块实现的。为了方便各模块间协同配合,NginxHTTP请求的处理过程分为11个阶段,如下图所示:


l    响应过滤模块:当上面的请求处理模块生成合法的HTTP响应后,将会由各个响应过滤模块依次对HTTP头部、包体做加工处理。比如返回HTMLJSCSS等文本文件时,若配置了gzip on;指令,就可以添加content-encoding: gzip头部,并使用zlib库压缩包体。

l    upstream负载均衡模块:当Nginx作为反向代理连接上游服务时,允许各类upstream模块提供不同的路由策略,比如ngx_http_upstream_hash_module模块提供了哈希路由,而ngx_http_upstream_keepalive_module模块则允许复用TCP连接,降低握手、慢启动等动作提升的网络时延。

对于这3类模块,你可以从模块名中识别,比如模块中出现filterhttp字样,通常就是过滤模块,比如ngx_http_gzip_filter_module。如果模块中出现upstreamhttp字样,就是负载均衡模块。

我们可以使用--with-模块名,将其编译进Nginx,也可以通--without-模块名,从Nginx中移出该模块。需要注意的是,当你通过configure --help帮助中看到--with-打头的选项,都是默认不编译进Nginx的模块,反之,--without-打头的选项,则是默认就编译进Nginx的模块。

还有一些HTTP模块并不属于上述3个类别,比如--with-http_v2_module是加入支持HTTP2协议的模块。当你需要添加第三方模块时,则可以通过--add-module=或者--add-dynamic-module=(动态模块将在后续文章中再介绍)选项指定模块源码目录,这样就可以将它编译进Nginx

如何安装并运行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种参数:

l    build:编译Nginx,这也是make不携带参数时的默认动作。它会在objs目录中生成可执行的二进制文件nginx

l    clean:通过删除Makefile文件和objs目录,将configuremake的执行结果清除,方便重新编译。

l    install:将Nginx安装到configure时指定的路径中,注意install只针对从头安装Nginx,如果是升级正在运行的服务,请使用upgrade参数。

l    upgrade:替换可执行文件nginx,同时热升级运行中的Nginx进程。

因此,当我们首次安装Nginx时,只需要先执行make命令编译出可执行文件,再执行make install安装到目标路径即可。

启动Nginx也很简单,进入Nginx目录后(比如/usr/local/nginx),在sbin目录下执行nginx程序即可,Nginx默认会启用Daemon守护者模式(参见daemon on;指令),这样shell命令行不会被nginx程序阻塞。

至此,Nginx已经编译、安装完成,并成功运行。

小结

最后做个小结,本文介绍了定制化编译、安装及运行Nginx的方法。

如果你想定制符合自己业务特点的Nginx,那就必须学会使用configure脚本,它会根据输入选项、系统环境生成差异化的编译环境,最终编译出功能、性能都不一样的Nginxconfigure支持的选项分为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日志文件的方法。


如果您觉得不错,就打赏支持一下吧〜
已有 2 人进行打赏
  • 阿尔巴
  • wangjinzhou
点击标签,发现更多精彩
发表评论
  • 守望

    好文章支持一下

    2020-12-29 09:57
    0
    回复
发表者

陶辉

暂无个人介绍

  • 15

    文章

  • 1

    关注

  • 86

    粉丝

活动推荐
版权所有©F5 Networks,Inc.保留所有权利。京ICP备16013763号-5