kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

lua-nginx-module的所有指令以及所有方法

http://www.04007.cn/article/430.html

在使用lua时,也许我们很多时候都只用了它几个基础的方法:比如http://www.04007.cn/article/129.html 这里面的content_by_lua,或者content_by_lua_file方法。在nginx+lua的脚本中,我们常用的ngx.say,以及ngx.log等,但实际ngx.还有很多好用的方法。

lua_nginx_module中可使用的指令列表:

指令名称说明
lua_use_default_type是否使用default_type指令定义的Content-Type默认值
lua_code_cache*_by_lua_file文件是否cache
lua_regex_cache_max_entries 
lua_regex_match_limit 
lua_package_path用Lua写的lua外部库路径(.lua文件)
lua_package_cpath用C写的lua外部库路径(.so文件)
init_by_luamaster进程启动时挂载的lua代码
init_by_lua_file 
init_worker_by_luaworker进程启动时挂载的lua代码,常用来执行一些定时器任务
init_worker_by_lua_file 
set_by_lua设置变量
set_by_lua_file 
content_by_luahandler模块
content_by_lua_file 
rewrite_by_lua 
rewrite_by_lua_file 
access_by_lua 
access_by_lua_file 
header_filter_by_luaheader filter模块
header_filter_by_lua_file 
body_filter_by_luabody filter模块,ngx.arg[1]代表输入的chunk,ngx.arg[2]代表当前chunk是否为last
body_filter_by_lua_file 
log_by_lua 
log_by_lua_file 
lua_need_request_body是否读请求体,跟ngx.req.read_body()函数作用类似
lua_shared_dict创建全局共享的table(多个worker进程共享)
lua_socket_connect_timeoutTCP/unix 域socket对象connect方法的超时时间
lua_socket_send_timeoutTCP/unix 域socket对象send方法的超时时间
lua_socket_send_lowat设置cosocket send buffer的low water值
lua_socket_read_timeoutTCP/unix 域socket对象receive方法的超时时间
lua_socket_buffer_sizecosocket读buffer大小
lua_socket_pool_sizecosocket连接池大小
lua_socket_keepalive_timeoutcosocket长连接超时时间
lua_socket_log_errors是否打开cosocket错误日志
lua_ssl_ciphers 
lua_ssl_crl 
lua_ssl_protocols 
lua_ssl_trusted_certificate 
lua_ssl_verify_depth 
lua_http10_buffering 
rewrite_by_lua_no_postpone 
lua_transform_underscores_in_response_headers 
lua_check_client_abort是否监视client提前关闭请求的事件,如果打开监视,会调用ngx.on_abort()注册的回调
lua_max_pending_timers 
lua_max_running_timers 

在lua程序脚本中可使用的操作方法及可取得的变量和常量列表

操作指令说明
ngx.arg指令参数,如跟在content_by_lua_file后面的参数
ngx.var变量,ngx.var.VARIABLE引用某个变量
ngx.ctx请求的lua上下文
ngx.header响应头,ngx.header.HEADER引用某个头
ngx.status响应码
API说明
ngx.log输出到error.log
print等价于 ngx.log(ngx.NOTICE, ...)
ngx.send_headers发送响应头
ngx.headers_sent响应头是否已发送
ngx.resp.get_headers获取响应头
ngx.timer.at注册定时器事件
ngx.is_subrequest当前请求是否是子请求
ngx.location.capture发布一个子请求
ngx.location.capture_multi发布多个子请求
ngx.exec 
ngx.redirect 
ngx.print输出响应
ngx.say输出响应,自动添加'\n'
ngx.flush刷新响应
ngx.exit结束请求
ngx.eof 
ngx.sleep无阻塞的休眠(使用定时器实现)
ngx.get_phase 
ngx.on_abort注册client断开请求时的回调函数
ndk.set_var.DIRECTIVE 
ngx.req.start_time请求的开始时间
ngx.req.http_version请求的HTTP版本号
ngx.req.raw_header请求头(包括请求行)
ngx.req.get_method请求方法
ngx.req.set_method请求方法重载
ngx.req.set_uri请求URL重写
ngx.req.set_uri_args 
ngx.req.get_uri_args获取请求参数
ngx.req.get_post_args获取请求表单
ngx.req.get_headers获取请求头
ngx.req.set_header 
ngx.req.clear_header 
ngx.req.read_body读取请求体
ngx.req.discard_body扔掉请求体
ngx.req.get_body_data 
ngx.req.get_body_file 
ngx.req.set_body_data 
ngx.req.set_body_file 
ngx.req.init_body 
ngx.req.append_body 
ngx.req.finish_body 
ngx.req.socket 
ngx.escape_uri字符串的url编码
ngx.unescape_uri字符串url解码
ngx.encode_args将table编码为一个参数字符串
ngx.decode_args将参数字符串编码为一个table
ngx.encode_base64字符串的base64编码
ngx.decode_base64字符串的base64解码
ngx.crc32_short字符串的crs32_short哈希
ngx.crc32_long字符串的crs32_long哈希
ngx.hmac_sha1字符串的hmac_sha1哈希
ngx.md5返回16进制MD5
ngx.md5_bin返回2进制MD5
ngx.sha1_bin返回2进制sha1哈希值
ngx.quote_sql_strSQL语句转义
ngx.today返回当前日期
ngx.time返回UNIX时间戳
ngx.now返回当前时间
ngx.update_time刷新时间后再返回
ngx.localtime 
ngx.utctime 
ngx.cookie_time返回的时间可用于cookie值
ngx.http_time返回的时间可用于HTTP头
ngx.parse_http_time解析HTTP头的时间
ngx.re.match 
ngx.re.find 
ngx.re.gmatch 
ngx.re.sub 
ngx.re.gsub 
ngx.shared.DICT 
ngx.shared.DICT.get 
ngx.shared.DICT.get_stale 
ngx.shared.DICT.set 
ngx.shared.DICT.safe_set 
ngx.shared.DICT.add 
ngx.shared.DICT.safe_add 
ngx.shared.DICT.replace 
ngx.shared.DICT.delete 
ngx.shared.DICT.incr 
ngx.shared.DICT.flush_all 
ngx.shared.DICT.flush_expired 
ngx.shared.DICT.get_keys 
ngx.socket.udp 
udpsock:setpeername 
udpsock:send 
udpsock:receive 
udpsock:close 
udpsock:settimeout 
ngx.socket.tcp 
tcpsock:connect 
tcpsock:sslhandshake 
tcpsock:send 
tcpsock:receive 
tcpsock:receiveuntil 
tcpsock:close 
tcpsock:settimeout 
tcpsock:setoption 
tcpsock:setkeepalive 
tcpsock:getreusedtimes 
ngx.socket.connect 
ngx.thread.spawn 
ngx.thread.wait 
ngx.thread.kill 
coroutine.create 
coroutine.resume 
coroutine.yield 
coroutine.wrap 
coroutine.running 
coroutine.status 
ngx.config.debug编译时是否有 --with-debug选项
ngx.config.prefix编译时的 --prefix选项
ngx.config.nginx_version返回nginx版本号
ngx.config.nginx_configure返回编译时 ./configure的命令行选项
ngx.config.ngx_lua_version返回ngx_lua模块版本号
ngx.worker.exiting当前worker进程是否正在关闭(如reload、shutdown期间)
ngx.worker.pid返回当前worker进程的pid
  
常量说明
Core constantsngx.OK (0)
ngx.ERROR (-1)
ngx.AGAIN (-2)
ngx.DONE (-4)
ngx.DECLINED (-5)
ngx.nil
HTTP method constantsngx.HTTP_GET
ngx.HTTP_HEAD
ngx.HTTP_PUT
ngx.HTTP_POST
ngx.HTTP_DELETE
ngx.HTTP_OPTIONS  
ngx.HTTP_MKCOL    
ngx.HTTP_COPY      
ngx.HTTP_MOVE     
ngx.HTTP_PROPFIND 
ngx.HTTP_PROPPATCH 
ngx.HTTP_LOCK 
ngx.HTTP_UNLOCK    
ngx.HTTP_PATCH   
ngx.HTTP_TRACE  
HTTP status constantsngx.HTTP_OK (200)
ngx.HTTP_CREATED (201)
ngx.HTTP_SPECIAL_RESPONSE (300)
ngx.HTTP_MOVED_PERMANENTLY (301)
ngx.HTTP_MOVED_TEMPORARILY (302)
ngx.HTTP_SEE_OTHER (303)
ngx.HTTP_NOT_MODIFIED (304)
ngx.HTTP_BAD_REQUEST (400)
ngx.HTTP_UNAUTHORIZED (401)
ngx.HTTP_FORBIDDEN (403)
ngx.HTTP_NOT_FOUND (404)
ngx.HTTP_NOT_ALLOWED (405)
ngx.HTTP_GONE (410)
ngx.HTTP_INTERNAL_SERVER_ERROR (500)
ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)
ngx.HTTP_SERVICE_UNAVAILABLE (503)
ngx.HTTP_GATEWAY_TIMEOUT (504) 
Nginx log level constantsngx.STDERR
ngx.EMERG
ngx.ALERT
ngx.CRIT
ngx.ERR
ngx.WARN
ngx.NOTICE
ngx.INFO
ngx.DEBUG

Lua-Nginx-Module常用指令

https://blog.51cto.com/xikder/2331336

https://blog.51cto.com/xikder/2331368

https://blog.51cto.com/xikder/2331504

本章将会讲解基于LuaJIT的Lua-Nginx-Module,它作为Nginx的第三方开源软件,拥有十分丰富的功能,可以轻松完成高并发的业务需求。

注意:本书使用的Lua-Nginx-Module版本是0.10.13。Nginx API for Lua将被简称为Lua API,而Lua-Nginx-Module则被简称为Ngx_lua。后面章节中涉及到的Lua API大部分是包含参数的,如果参数以?结尾,代表这个参数是可选的,如在指令ngx.req.get_headers (max_headers?, raw?)中,max_headers和raw是可选的。

一、Nginx和OpenResty

首先,来认识一下OpenResty,它是一个基于Nginx和Lua开发的高性能的Web平台,包含大量成熟的第三方库,可快速搭建出高性能的Web服务器,支持常用的反向代理、网关系统、Web应用等。

如果在Nginx上使用Ngx_lua,需要先进行编译;而OpenResty已经包含此模块,不需要再进行编译了。读者可以自由选择使用Nginx或OpenResty来搭建服务,如果无法抉择,可参考如下场景。

使用Nginx编译Ngx_Lua的场景

HTTP代理服务器:复杂度较小,只需部分组件即可,且代理服务器一般由运维人员进行维护。使用Nginx的稳定版进行编译,在性能方面会更有保障,而OpenResty是Nginx的主线版,可能会不定期更新。

OpenResty的使用场景

API服务:业务需求多,需要大量组件。
网关系统:需要大量组件和指令来实现动态组件功能。
Web应用服务器:业务服务、页面服务等,如详情页业务的开发。
使用Nginx编写的Lua代码都可以直接迁移到OpenResty上;反之却不一定可行,毕竟OpenResty的组件更多。

二、安装Ngx_lua

请先安装LuaJIT 2.1.0-beta3(详见第6.2节)并需要编译ngx_devel_kit模块。 下面是在Nginx上的安装方式(OpenResty自带此模块,不必安装编译):

1
2
3
4
5
6
7
8
9
10
11
# wget 'http://nginx.org/download/nginx-1.12.2.tar.gz'
# git clone https://github.com/simplresty/ngx_devel_kit.git
# git clone https://github.com/openresty/lua-nginx-module.git
# tar -xzvf nginx-1.12.2.tar.gz
# cd nginx-1.12.2/
# ./configure --prefix=/usr/local/nginx_1.12.2 \
     --add-module=../ngx_devel_kit \
     --add-module=../lua-nginx-module
     --with-ld-opt="-Wl,-rpath,$LUAJIT_LIB"

# make && make install

并不是每个Nginx版本都支持最新的Ngx_lua,目前已知支持最新Ngx_lua的Nginx版本如下:

1
2
3
4
5
6
7
8
1.13.x (last tested: 1.13.6)
1.12.x
1.11.x (last tested: 1.11.2)
1.10.x
1.9.x (last tested: 1.9.15)
1.8.x
1.7.x (last tested: 1.7.10)
1.6.x

如需获取最新版本的支持动态,请参考https://github.com/openresty/lua-nginx-module# nginx-compatibility。

三、牢记context标识

Ngx_lua API指令和Nginx的指令一样,都存在配置环境的约束问题,因此在使用过程中要确保指令的环境符合预期,例如:

1
2
3
4
ngx.var.VARIABLE
语法:ngx.var.VAR_NAME
context(配置环境):set_by_lua*,rewrite_by_lua*,access_by_lua*,content_by_lua*,header_ filter_by_lua*,body_filter_by_lua*,log_by_lua*
context即配置环境,第一次接触Ngx_lua的读者看到这样的配置环境可能会觉得难以理解,因为这还涉及到Ngx_Lua的执行阶段(后面会有介绍)。

四、Hello world

首先,还是来一条经典语句“Hello, world”,在Nginx配置中加入一个server:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
    listen       80;
    server_name  testnginx.com;
    charset koi8-r;
    location = /test {
     #设置文件使用的默认MIME-type,将会增加一个Content-Type:text/plain的响应头
     default_type 'text/plain';    
     -- content_by_lua_block执行阶段
     content_by_lua_block {    
         ngx.say('Hello,world!')
     }
    }
}

访问这个server,输出如下:

1
2
#  curl -I http://testnginx.com/test
Hello,world!    

ngx.say将数据作为响应体输出,返回给客户端,并在末尾加上一个回车符。

代码中用到了content_by_lua_block这个指令块,它的主要作用是在HTTP的内容处理阶段生成数据,详见第8.6节。

Nginx Openresty - 读取请求体

https://blog.csdn.net/trustnature/article/details/94417336

由于nginx默认不读取请求体的数据,因此当 Lua 通过 ngx.var.request_body 的方式获取请求体时会发现数据为空,那么,该如何获得请求体的数据呢?

方式一:lua_need_request_body

1
2
3
4
5
语法:lua_need_request_body<on|off>

默认值:off

环境:http、server、location、

含义:默认为off,即不读取请求体。如果设置为on,则表示强制读取请求体,此时,可以通过 ngx.var.request_body 来获取请求体的数据。但需要注意一种情况,$request_body 存在与内存中,如果它的字节大小超过Nginx配置的 client_body_buffer_size 的值,Nginx就会把请求体存放到临时文件中。此时数据就不存在与内存中了,这会导致 $request_body 为空,所以需要设置 client_body_buffer_size 和 client_max_body_size 的值相同,避免出现这种情况。

这种配置方式不够灵活,Ngx_Lua官网也不推荐使用此方法。

方式二:ngx.req.read_body

1
2
3
语法:ngx.req.read_body()

环境:rewrite_by_lua*、access_by_lua*、content_by_lua*

含义:同步读取客户端请求体,且不会阻塞Nginx的事件循环。使用此指令后,就可以通过 ngx.req.get_body_data 来获取请求体的数据了。按如果使用临时文件来存放请求体,就需要先使用函数 ngx.req.get_body_file 来获取临时文件名,再读取临时文件中的请求体数据。

1
2
3
4
5
指令:ngx.req.get_body_data

语法:data = ngx.req.get_body_data()

环境:rewrite_by_lua*、access_by_lua*、content_by_lua*、log_by_lua*

含义:执行 ngx.req.read_body 指令后,可以使用本指令在内存中获取请求体数据,结果会返回一个Lua的字符串类型数据。如果要获取Lua的table类型的数据,则需要使用 ngx.req.get_post_args

1
2
3
4
5
指令:ngx.req.get_post_data

语法:args,err=ngx.req.get_post_args(max_args?)

环境:rewrite_by_lua*、access_by_lua*、content_by_lua*、header_filter_by_lua*、body_filter_by_lua*、log_by_lua*

含义:在执行 ngx.req.read_body 指令后,可以使用本指令读取包含当前请求在内的所有POST值请求的查询参数,返回一个Lua的table类型的数据。max_args 参数的作用时限制参数的数量。为了服务的安全,最多支持使用100个参数(包括重复的参数),超过限制的参数会被忽略。如果max_args为0,则表示关闭此限制;但为了避免被无穷多的参数攻击,不要将max_args设置为0,如果最多支持使用10个参数,则应配置为 ngx.req.get_post_args(10)。

使用场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
content_by_lua_block {
	local ngx = require "ngx"
	ngx.req.read_body()
	local data = ngx.req.get_body_data()
	if data then
		ngx.print('ngx.req.get_body_data:',data,')
		return
	else
		lcoal file = ngx.req.get_body_file()
		if file then
			ngx.say("body is in file",file)
		else
			ngx.say("no body found")
		end
	end
}