之前总有人说nginx没办法调试,写多个变量,不知道变量值是啥,写多个location不知道走的是哪个location,今天带来三种方式
1
echo
echo模块是国人编写的第三方模块,官方nginx是没有自带的,在openresty中默认自带,它是在nginx程序上扩展了echo输出字符的功能,对于调试真的是太方便了
我们知道,平常处理nginx问题,都是从日志查看问题,但是nginx的日志,记录的内容有限,而echo基本可以在nginx处理的任何阶段为你输出有用的信息,直白点说,就和你开发过程中debug一样
它包装了很多nginx内部的api,能够处理流的输入输出,并行或顺序执行的子请求,以及nginx内部计时器,甚至可以通过echo_sleep,让执行等待,并能够通过api访问各种元数据
简单说下安装,由于nginx默认不带这个模块,需要重新编译,从官网下载你对应版本的nginx的tar包,解压之后,配置编译参数,这里有两种方式可以安装
静态模块添加
你需要先通过nginx -V查看原本编译参数,使用原先的编译参数,在后面添加--add-module=/path/to/echo-nginx-module
然后执行编译,生成新的nginx可执行文件,然后平滑升级
动态模块添加
你只需要添加--with-compat --add-dynamic-module=/path/to/echo-nginx-module/
之后通过make modules编译模块,就会在objs目录下,生成ngx_http_echo_module.so文件,然后在nginx配置文件中,通过load_module的方式动态加载
加载之后,就可以使用了
比如上面配置,echo出请求的host,然后通过curl请求就可以看到输出结果
因为echo输出的数据,有可能被nginx的缓存区缓存,所以在echo后面加了echo_flush,用来刷新缓存
还有比较常用的echo_sleep,它可以让你指定的location或if中的请求,休眠echo_sleep指定的事件段,这个休眠在服务端是非阻塞的,并不是让Nginx进程等待这么长时间,但是echo_blocking_sleep用的时候就要注意了,它是会让整个nginx worker进程阻塞的,这个在生产环境慎用
通过添加echo_sleep,然后再echo出request_time,做一下对比可以看到如下结果
该模块有以下可选指令,更多的指令请到github查看,有非常详细的文档
除了有以上指令外,它还有很多内置的变量特别好用
比如来输出了request_headers,输出个request_uri等
输出结果
更多详情,移步github
项目地址:https://github.com/openresty/echo-nginx-module
2
lua
lua是一种轻量的脚本语言,用标准的C语言编写,在openresty中集成,在官方nginx中没有集成,需要编译支持,所以我们可以通过编写lua来输出调试
nginx支持lua,需要安装LuaJIT解释器,并重新编译nginx,由于网上很多安装教程,这里只简单说一下,不做详细说明
LuaJIT官网地址:https://luajit.org
首先从官网下载LuaJIT的包,然后解压,直接make && make install编译安装
以上就安装完LuaJIT了
然后再从openresty的github下载lua-nginx-module,以及从github下载NDK(ngx_devel_kit)
地址分别是:
lua-nginx-module:https://github.com/openresty/lua-nginx-module
ngx_devel_kit:https://github.com/simplresty/ngx_devel_kit
接下来就老套路了,重新编译安装nginx,不会往上翻,上面有,动态加载、静态安装,自己看,静态性能肯定好一些,但是动态灵活
编译的时候,找不到luajit,需要在环境变量中把lua的lib和include加上,如果是nginx比较高的版本,那可能安装的时候不会有问题,但是启动nginx的时候,执行lua脚本会报luajit版本不匹配,就别从官网下载,直接从github上下载最新的https://github.com/openresty/luajit2/releases,然后重新编译
之后通过source /etc/profile使环境变量生效,再执行./configure,之后再make modules就可以了
然后通过load_modules加载就可以使用了
lua在nginx中配置有两种方式,一种是直接用lua指令来输出,一种是引入lua脚本文件
通常是通过ngx.say()或ngx.print()来输出想要打印的信息,这两者都是输出响应体内容,区别在于nginx.say()会在结尾输出一个换行符
通过以上两个方法你可以将想要debug的信息输出,或通过ngx.log()将信息写入到日志进行查看
3
njs
njs是nginScript的简称,从这个名称大概你就可以看出来,是nginx官方为了nginx和nginx plus开发的javaScript实现,它是官方nginx支持的,设计用于在服务器端处理请求,通过融入JavaScript代码对nginx的配置语法进行扩展,方便实现一些原生nginx配置无法实现的配置或需求,甚至有人说njs会取代lua,成为新的nginx扩展脚本语言,个人觉得还要一段时间吧
目前它能实现的功能已经很强大了,比如:
目前还仍然有新的特性不断发布,所以对于nginx调试、排查,njs也是完全可以做到的
虽然是融入了JavaScript语法,但是它和javascript不是完全相同的,它是JavaScript/ECMAscript的子集,njs不通过V8引擎实现,而是通过更小的、资源消耗更低的虚拟机(VM)来实现的
njs的安装,和上面加模块一样,也是直接编辑添加模块,然后引入,这里就不多说了,模块下载地址:
http://hg.nginx.org/njs
njs的基本用法是,将实际脚本写入js文件,再在http块中通过js_include引入js文件,接着你就可以在location等块中通过js_content调用函数名来执行js脚本
这个时候去请求,就会返回200状态码,并输出
根据nginx官方提供的njs的对象、方法和属性,见https://nginx.org/en/docs/njs/reference.html
可以很方便的进行调试,比如用error方法将错误写入日志
或通过log方法,将info信息写入日志等,具体方法参见官方文档
有了上述三个方法,对于nginx配置调试,及故障排查得心应手。