一、HAProxy Lua运行上下文
lua 代码在haproxy中以两种模式执行,第一种是initialisation mode 第二种是runtime mode
1、在initialisation mode 中,可以执行dns解析,但是不能执行socket i/o,在这个模式中当lua脚本执行时haproxy将会blocked
2、在runtime mode中,不能执行dns解析,但是可以使用socket,执行lua脚本是和请求线程一致。
lua 代码可以在一个或者多个文件中导入,这些文件包括主要的代码和函数,lua有6个执行上下文:
1、body context,它在当haproxy global中load时执行,这个主要用于配置lua绑定到haproxy中。
2、init context,在这个上下文中haproxy中的环境变量已经初始化,在执行检查配置时很有用,或初始化socket连接或任务。这些方法在body context中用core.register_init()声明,方法的属性是没有返回值和没有参数的简单函数,like:function fun()
3、task context,他是一个lua方法,在启动haproxy调度后执行,它使用core.register_task()声明,
4、action context,它是使用core.register_action()声明的lua函数,它接受class TXN参数,
5、sample-fetch context,这个方法接受txn对象并且返回字符串,它使用core
haproxy lua hello world
haproxy 配置文件:
global
lua-load hello_world.lua
listen proxy
bind 127.0.0.1:10000
tcp-request inspect-delay 1s
tcp-request content use-service lua.hello_world
hello_world.lua
core.register_service("hello_world","tcp",function(applet)
applet:send("hello world\n")
end)
二、core class
class core()
这个core对象包含了所有的haproxy核心函数,这些函数包括控制执行,注册钩子,处理全局映射或acl等
这个core是静态的,不用创建一个新的对象
core.emerg
return: integer
这个属性是一个整数,它包含日志级别"emergency"的值0
core.alert
returns:integer
它包含日志级别“alert”的值1
core.crit
return :integer
它包含日志级别“critical”的值2
core.err
return :integer 3
core.warning
return :integer 4
core.notice
return: integer 5
core.info
return: integer 6
core.debug
return:integer 7
core.proxies
context:task,action,sample-fetch,convert
这个属性是一张table声明了frontend和backend proxies,每一个代理给出它的listeners和serviers列表,这个表使用proxy name作为index,
core.backends
context:task,action,sample-fetch,convert
返回一张表,backend name作为index
core.frontends
context:task,action,sample-fetch,convert
返回一张表,frontend name做为index
core.log(loglevel,msg)
context:body,init,task,action,sample-fetch,convert
记录日志,根据haproxy的日志配置
core.Debug(msg)
context:body,init,action,sample-fetch,converter
和core.log(core.debug,msg) 同等
core.Info(msg)
core.Warning(msg)
core.Alert(msg)
core.add_acl(filename,key)
context:init,task,action,sample-fetch,converter
向file中的acls添加acl key
core.del_acl(filename,key)
context:init,task,action,sample-fetch,converter
core,del_map(filename,key)
context:init,task,action,sample-fetch,converter
core.get_info()
context:body,init,task,action,sample-fetch,converter
返回haproxy的信息,可以得到:uptime,pid,memory pool usage,tasks number 等。
core.now()
context:body,init,task,action
返回当前时间。
core.http_date(date)
context:body,init,task,action
这个函数将一个string转换为date,
core.imf_date(date)
context:body,init,task,action
参数imf格式日期
core.rfc850_date(date)
context:body,init,task,action
参数:RFC859格式的日期
core.asctime_date(date)
context:body,init,task,action
参数:http-date格式
core.msleep(milliseconds)
context:body,init,task,action
暂停多少时间
core.register_action(name,actions,func[,nb_args])
context:body
注册lua函数作为action,所有注册的action可以在haproxy中使用通过“lua.”来调用,function使用txn作为输入
like:function(txn,args)
txn:表示当前的请求或tcp流
example:
core.register_action("hello",{"tcp-req","http-req"},function(txn) txn:Info("hello")
end)
haproxy配置:
frontend tcp_frt
mode tcp
tcp-request content lua.hello
frontend http-frt
mode http
http-request lua.hello
带参数:
function hello(txn,arg)
txn:Info("hello"..arg)
end
core.register_action("hello",{"tcp-req","http-req"},hello,2)
配置文件:
frontend tcpfrt
mode tcp
tcp-request content lua.hello everybody
core.register_converters(name,func)
context:body
注册lua函数为converter,注册后可在haproxy中使用“lua.”来进行调用。
function(str,[p1[,p2[,…][,p5]]])
str:输入值自动转化为string
p1.。。p5:string类型的列表,在haproxy 配置中声明,最多5个参数,
core.register_fetches(name,func)
context:body
注册lua函数为fetch,注册后可在haproxy中使用“lua.”来进行调用。返回字符串
string function(txn,[p1[,p2[,…][,p5]]])
txn:表示当前请求对象
example:
core.register_fetches("hello",function(txn)
return "hello"
end)
配置文件:
frontend example
http-request redirect location /%[lua.hello]
core.register_service(name,mode,func)
context:body
注册lua函数为service,注册后使用“lua.”来进行调用。service使用mode作为输入对象。
mode:只能是tcp或者http
function(applet)
applet:将会是applettcp class 或者applethttp class它取决于注册的applet
example:
core.register_service("hello","http",function(applet)
local response ="hello world"
applet:set_status(200)
applet:add_header("content-length",string.len(response))
applet:add_response("content-type","text/plain")
applet:start_reponse()
applet:send(response)
end)
配置文件:
frontend example
http-request use-service lua.hello
core.register_init(func)
context:body
注册一个函数在配置检查后启动,这在检查参数的时候很有用
function()
它没有输入和输出
core.register_task(func)
context:body,init,task,action,sample-fetch,converter
注册并启动一个独立的任务,这个任务在haproxy主进程启动后就启动,这个任务可用与复杂的健康检查
core.register_cli([path],usage,func)
context:body
作用等同于register_task
function(applettcp,[args])
example:
core.register_cli({"show","ssl","stats"},"display ssl stats...",function(applet,arg1,arg2,arg3,arg4,arg5)
end)
arg1…arg3将对应show,ssl,stats,arg4表示all,arg5表示nil
core.set_nice(nice)
context:task,action,sample-fetch,converter
改变当前任务获取session的nice
nice:是一个数值,它位于1-1024之间
core.set_map(filename,key,value)
context:init,task,action,sample-fetch,converter
设置filename中对应key的值
core.sleep(int seconds)
context:body,init,task,actin
暂停执行
core.tcp()
context :init,task,action
返回一个新的socket对象
core.concat()
context:body,init,task,action,sample-fetch,converter
返回concat对象
core.done(data)
context:body,init,task,action,sample-fetch,converter
立即停止当前lua脚本的执行,并返回给调用方,它可以是一个fetch,converter ,oraction。它在lua进程完成了它的工作并且想要将控制权交还给haproxy,它相当于return
core.yield()
context:task,action,sample-fetch,converter
将控制权交还给haproxy,它在lua进程需要大量的时间的时候很有用
core.parse_addr(address)
context:body,init,task,action,sample-fetch,converter
core.match_addr(addr1,addr2)
context:body,init,task,action,sample-fetch,converter
当两个地址相当时返回true,or false
core.tokenize(str,separators[,noblank])
context:body,init,task,action,sample-fetch,converter
这个函数在tokenizing entry,分隔信息,str参数将会被分隔,separators包含分隔符的列表,noblank:忽略空输入,返回 array
example:
local array=core.tokenize("this function is useful,for tokenizing an entry.",".,",true)
print_r(array)
三、Proxy class
class Proxy()
这个类提供了操作proxy的通道,并且可以得到统计信息
Proxy.name
包含proxy的name
Proxy.uuid
包含proxy的唯一id
Proxy.servers
包含一张server表,server name 作为表的index,每一个server是server class 对象
Proxy.stktable
包含proxy的固定表
Proxy.listeners
包含listener的表
Proxy.pause(px)
暂停proxy,
Proxy.resume(px)
恢复proxy
Proxy.stop(px)
停止proxy
Proxy.shut_bcksess(px)
kill session to backup server
Proxy.get_cap(px)
返回proxy的描述信息
Proxy.get_mode(px)
返回proxy的mode
Proxy.get_stats(px)
返回proxy统计的表
四、 Server class
class Server()
这个类提供可以操作servers的方法,
Server.name
包含server name
Server.puid
包含server所属的proxy uuid
Server.is_draining(sv)
如果当前服务处于连接状态返回true
Server.set_maxconn(sv,maxconn)
动态改变服务的最大连接,
Server.get_maxconn(sv)
返回服务的最大连接数
Server.set_weight(sv,weight)
动态设置服务的权重
Server.get_weight(sv)
获取权重
Server.set_addr(sv,addr)
动态改变服务地址
Server.get_addr(sv)
返回服务地址
Server.get_stats(sv)
返回服务statistics
Server.shut_sess(sv)
关闭服务的所有连接
Server.set_drain(sv)
Server.set_maint(sv)
设置为maintenance mode
Server.set_ready(sv)
设置为nomal mode
Server.check_enable(sv)
enable 健康检查
Server.check_disable(sv)
disabel 健康检查
Server.check_force_up(sv)
强制启用健康检查
Server.check_force_nolb(sv)
强制健康检查 nolb模式
Server.check_force_down(sv)
强制不使用健康检查
Server.agent_enable(sv)
启用agent检查
Server.agent_disable(sv)
不启用agent检查
Server.agent_force_up(sv)
强制启用agent
Server.agent_force_down(sv)
强制关闭agent
五、Listener class
Listener.get_stats(ls)
返回server 状态信息
六、Concat class
class Concat()
这个类提供了快速的将string 连接,原生的lua连接… 因为一些原因比较慢
example:
for j =1,100 do
c=core.concat()
for i =1,20000 do
c:add("####")
end
end
Concat.add(concat,string)
将string拼接到concat中。
Concat.dump(concat)
返回concat的string
七、Fetches class
class Fetches()
这个类包含很多的haproxy内部的fetches。
txn.f
txn.fc
fetches 在一下情况比较实用:
- get system time
- get environment variable
- get random number
- known backend status like the number of users in queue or the number of connections established
- client information like ip source or destination
- established ssl information
- http information like headers or method
example:
function action(txn)
local clientip = txn.f:src
end
八、Converers class
class Converters()
这个类包含了很多的haproxy内部的转换器,
txn.c
txn.sc
converter 可用于:
- converting input to base64
- applying hash on input string
- format date
- json escape
- extracting preferred language comparing two lists
- teurn to lower or upper chars
- deal with stick tables
九、Channel class
class Channel()
haproxy使用两个buffer在requests的请求中,第一个用于request data(client to server)。第二个用于response data(server to client)
没个buffer都包含两个类型的数据。第一个类型是等待处理的incoming data,第二是已处理的outgoing data。
接下来的方法提供了工具去处理这些buffer中的数据
Channel.dup(channel)
返回整个buffer的数据,这些数据并没有从buffer中删除。
Channel.get(channel)
返回整个buffer的数据,从buffer中消费数据
Channel.getline(channel)
返回第一行数据,从buffer中消费数据
Channel.set(channel,string)
替换buffer内容,
Channel.append(channel,string)
将string添加到buffer content中,
Channel.send(channel,string)
这个函数需要立即发送数据,除非连接关闭,
Channel.get_in_length(channel)
从input buffer中获取长度
Channel.get_out_length(channel)
返回out buffer 长度
Channel.forward(channel,int)
转换为bytes从input到output
Channel.is_full(channel)
十、Http class
class HTTP()
这个类包含了所有的http操作函数
HTTP.req_get_headers(http)
返回所有请求头
HTTP:req_get_headers()['header-name']['header-index']="header-value"
local hdr=HTTP:req_get_headers()
hdr["host"][0]="www.example.com"
HTTP.res_get_headers(http)
返回响应头信息
HTTP.req_add_header(http,name,value)
添加请求头部信息
HTTP.res_add_header(http,name,value)
添加响应头部信息
HTTP.req_del_header(http,name)
删除请求头
HTTP.res_del_header(http,name)
删除响应头
HTTP.req_set_header(http,name,value)
如果头存在则替换
example:
function fcn(txn)
TXN.http:req_del_header("header")
TXN.http:req_add_header("header","value")
end
HTTP.res_set_header(http,name,value)
替换响应头
HTTP.req_rep_header(http,name,regex,replace)
根据正则匹配头,然后使用replace进行替换,
HTTP.req_rep_header(http,name,regex,replace)
根据正则匹配头,然后使用replace进行替换,
HTTP.req_set_method(http,method)
重写请求方法
HTTP.req_set_query(http,query)
重写查询参数
HTTP.req_set_uri(http,uri)
重写uri
HTTP.res_set_status(http,status [,reason])
重写响应ma
十一、TXN class
class TXN()
txn 包含了所有的方法去解析http或tcp请求
这个类允许去解析请求数据并改变或转发
TXN.c
returns : an converters class
这个属性包含转化实例
TXN.sc
return : an converters class
这个属性包含转化实例,这个实例的方法总是返回string
TXN.f
return: an fetches class
这个属性包含fetches 实例
TXN.sf
return: an fetches class
这个属性包含fetches 实例,这个实例的方法总是返回string
TXN.req
return :an channel class
这个属性包含请求buffer 的channel 实例
TXN.res
return: an channel class
这个属性包含响应buffer 的channel 实例
TXN.http
return : an http class
这个属性包含http实例,仅当mode为http时有效
TXN.log(TXN,loglevel,msg)
该函数发送log
TXN.log(TXN,msg)
发送默认loglevel
TXN.Debug(txn,msg)
TXN.Info(txn,msg)
TXN.Warning(txn,msg)
TXN.Alert(txn,msg)
TXN.get_priv(txn)
返回当前transaction存储的lua数据,如果没有,则返回nil
TXN.set_priv(txn,data)
存储数据到当前transaction。
TXN.set_var(txn,var,value)
将lua type转换为haproxy type并存储在variable
TXN.unset_var(txn,var)
unset 变量
TXN.get_var(txn,var)
返回存储的var,并转化为lua 类型
TXN.done(txn)
终止进程,
TXN.set_loglevel(txn,loglevel)
改变当前请求的日志级别
TXN.set_tos(txn,tos)
它被用于设置tos或dscp
TXN.set_mark(txn,mark)
他被用于设置netfilter mark
TXN.set_priority_class(txn,prio)
设置transaction的优先级,取值范围:-2047-2047
TXN.set_priority_offset(txn,prio)
十二、Socket class
class Socket()
这个类必须与lua socket 一起使用,
Socket.close(socket)
关闭socket,
Socket.connect(socket,address [,port])
网络连接
如果出错则返回nil,正确返回1
Socket.connetc_ssl(socket,address,port)
和connet()一直,只是使用ssl
Socket.getpeername(socket)
返回远程终端信息,
Socket.getsockname(socket)
返回local ip和port
Socket.receive(socket[,pattern[,prefix]])
读取信息,根据pattern,pattern是lua 文件i/o的格式
Socket.send(socket,data[,start[,end]])
发送信息
Socket.setoption(socket,option[,value])
Socket.settimeout(socket,value[,mode])
设置超时时间
十四、Regex class
这个类允许使用haproxy 的正则,因为lua并不提供正则。
example:
st,regex=Regex.new("needle (..)(...)",true)
if st == false then
print "error:" .. regex
end
print(regex:exec("Looking for a needle in the"))--true
print(regex:exec("lookin for a cat in the"))--false
st,list=regex:match("looking for a needle in the")
print(st)--true
print(list[1])--needle in the
print(list[2])--in
print(list[3])--the
Regex.new(regex,case_sensitive)
创建正则匹配
returns:boolean status and Regex class or 失败原因
Regex.exec(regex,str)
进行正则匹配
如果匹配返回true else false
Regex.match(regex,str)
执行正则匹配,并返回匹配
return:boolean status 和匹配的table
十五、Map class
这个类可以在haproxy maps中查找,
default=usa
geo=Map.new('geo.map',Map._ip)
core.register_fetches("country",function(txn)
local src
local loc
src = txn.f:fhdr("x-forwared-for")
if (src == nil) then
src=txc.f:src()
if (src == nil) then
return default
end
end
loc = geo:lookup(src)
if (loc == nil) then
return default
end
return loc
end)
Map._int
Map._ip
Map._str
Map._beg
Map._sub
Map._dir
Map._dom
Map._end
Map._reg
Map.new(file,method)
创建并导入map
Map.lookup(map,str)
执行lookup在map中
Map.slookup(map,str)
十六、AppletHTTP class
这个类用于使用http 模式的applet,http applet能够使用core.register_service()方法注册,它被用于像haproxy后端服务一样处理http 请求。
example:
core.register_service("hello","http",function(applet)
local response="hello"
applet:set_status(200)
applet:add_header("content-length",string.len(response))
applet:start_response()
applet:send(response)
end)
applethttp.c
applethttp.sc
applethttp.f
applethttp.sf
applethttp.method
返回http方法
applethttp.version
返回http请求版本
applethttp.path
返回请求path
applethttp.qs
返回请求query string
applethttp.length
返回请求body长度
applethttp.headers
返回请求头
applethttp.set_status(applet,code[,reason])
设置响应代码,code范围100-599
applethttp.add_header(applet,name,value)
添加响应头,
applethttp.start_response(applet)
这个方法启用http engine 来处理和发送响应头,在这个函数后不能调用 add_header(),send()函数需要在此函数调用后使用。
applethttp.getline(applet)
这个函数返回一行http body内容,
applethttp.receive(applet[,size])
从http body中读取内容,根据size,如果没有设置size则读取全部内容。
applethttp.send(applet,msg)
发送数据到http request body
applethttp.get_priv(applet)
返回存储在当前transaction中的数据,如果没有则返回nil
applethttp.set_priv(applet,data)
存储数据到当前haproxy transaction
applethttp.set_var(applet,var,value)
转换lua 类型为haproxy类型,并存储到var
applethttp.unset_var(applet,var,value)
applethttp.get_var(applet,var,value)
十八、AppletTCP class
这个类用于tcp mode的applet。
applettcp.c
applettcp.sc
applettcp.f
applettcp.sf
applettcp.getline(applet)
applettcp.receive(applet[,size])
applettcp.send(applet,msg)
applettcp.get_priv(applet)
applettcp.set_priv(applet,data)
applettcp.set_var(applet,var,value)
applettcp.unset_var(applet,var)
applettcp.get_var(applet,var)