首页技术文章正文

openrestry中的常用Lua API介绍【黑马java培训】

更新时间:2020-10-13 来源:黑马程序员 浏览量:

和一般的Web Server类似,我们需要接收请求、处理并输出响应。而对于请求我们需要获取如请求参数、请求头、Body体等信息;而对于处理就是调用相应的Lua代码即可;输出响应需要进行响应状态码、响应头和响应内容体的输出。因此我们从如上几个点出发即可。

接收请求

获取nginx变量:ngx.var

 server {
        listen 8080;
        location / {
        	#定义nginx变量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
            	local var = ngx.var; -- 获取nginx变量
				ngx.say("ngx.var.b : ", var.b, "<br/>")
				ngx.var.b = 2; -- 设置变量值
				ngx.say("ngx.var.b : ", var.b, "<br/>")
				ngx.say("<br/>")
            }
        }
    }


获取请求头:ngx.req.get_headers()

server {
        listen 8080;
        location / {
        	#定义nginx变量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				local headers = ngx.req.get_headers()
				ngx.say("headers begin", "<br/>")
				ngx.say("Host : ", headers["Host"], "<br/>")
				ngx.say("user-agent : ", headers["user-agent"], "<br/>")
				ngx.say("user-agent : ", headers.user_agent, "<br/>")
				ngx.say("=======================================","</br>")				
				for k,v in pairs(headers) do
					if type(v) == "table" then
						ngx.say(k, " : ", table.concat(v, ","), "<br/>")
					else
						ngx.say(k, " : ", v, "<br/>")
					end
				end
				ngx.say("headers end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }


get请求uri参数:ngx.req.get_uri_args()

server {
        listen 8080;
        location / {
        	#定义nginx变量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				ngx.say("uri args begin", "<br/>")
				local uri_args = ngx.req.get_uri_args()
				ngx.say("param:username=",uri_args['username'], "<br/>")
				ngx.say("param:password=",uri_args['password'], "<br/>")
				ngx.say("uri args end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }


post请求参数:ngx.req.get_post_args()

server {
        listen 8080;
        location / {
        	#定义nginx变量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				ngx.say("uri args begin", "<br/>")
				-- 获取请求体中的数据
				ngx.req.read_body()
				local uri_args = ngx.req.get_post_args() --获取key-value格式的数据
				ngx.say("param:username=",uri_args['username'], "<br/>")
				ngx.say("param:password=",uri_args['password'], "<br/>")
				ngx.say("uri args end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }


其他请求相关的方法:

获取请求的http协议版本:ngx.req.http_version()

获取请求方法:ngx.req.get_method()

获取请求头内容:ngx.req.get_headers()

获取请求的body内容体:ngx.req.get_body_data()

输出响应

 server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				--写响应头
				ngx.header.a = "1"
				--多个响应头可以使用table
				ngx.header.b = {"2", "3"}
				--输出响应
				ngx.say("a", "b", "<br/>")
				ngx.print("c", "d", "<br/>")
				--200状态码退出
				return ngx.exit(200)
            }
        }
    }

}


响应相关方法:

ngx.header.xx = yy:输出响应头;

ngx.print():输出响应内容体;

ngx.say():同ngx.print()一样,但是会最后输出一个换行符;

ngx.exit():指定状态码退出;

ngx.send_headers():发送响应状态码,当调用ngx.say/ngx.print时自动发送响应状态码;

ngx.headers_sent( ): 判断是否发送了响应状态码。


重定向

 server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				ngx.redirect("http://jd.com", 302);  
            }
        }
    }


Nginx全局内存

使用过如Java的朋友可能知道如Ehcache等这种进程内本地缓存,Nginx是一个Master进程多个Worker进程的工作方式,因此我们可能需要在多个Worker进程中共享数据,那么此时就可以使用ngx.shared.DICT来实现全局内存共享。

1、首先在nginx.conf的http部分定义一个全局内存,并指定内存大小。

#共享全局变量,在所有worker间共享,如下:定义了一个名为shared_data的全局内存,大小为1m
lua_shared_dict shared_data 1m;


2、使用全局内存

 server {	
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				--1、获取全局共享内存变量
				local shared_data = ngx.shared.shared_data
				--2、获取字典值
				local i = shared_data:get("i")
				if not i then
					i = 1
					--3、惰性赋值
					shared_data:set("i", i)
					ngx.say("lazy set i ", i, "<br/>")
				end
				--递增
				i = shared_data:incr("i", 1)
				ngx.say("i=", i, "<br/>")
            }
        }
    }


3、全局内存常用方法介绍

ngx.shared.DICT

获取共享内存字典项对象

语法:dict = ngx.shared.DICT
	dict = ngx.shared[name_var]
	
其中,DICT和name_var表示的名称是一致的,比如上面例子中,shared_data = ngx.shared.shared_data
就是dict = ngx.shared.DICT的表达形式,
也可以通过下面的方式达到同样的目的:
shared_data = ngx.shared['shared_data']

ngx.shared.DICT:get(key)

获取共享内存上key对应的值。如果key不存在,或者key已经过期,将会返回nil;如果出现错误,那么将会返回nil以及错误信息。

ngx.shared.DICT:get_stale(key)

与get方法类似,区别在于该方法对于过期的key也会返回,第三个返回参数表明返回的key的值是否已经过期,true表示过期,false表示没有过期。

ngx.shared.DICT:set(key, value, exptime?, flags?)

“无条件”地往共享内存上插入key-value对,这里讲的“无条件”指的是不管待插入的共享内存上是否已经存在相同的key。

三个返回值的含义:

success:成功插入为true,插入失败为false

err:操作失败时的错误信息,可能类似"no memory"

forcible:true表明需要通过强制删除(LRU算法)共享内存上其他字典项来实现插入,false表明没有删除共享内存上的字典项来实现插入。

exptime参数表明key的有效期时间,单位是秒(s),默认值为0,表明永远不会过期;

flags参数是一个用户标志值,会在调用get方法时同时获取得到

ngx.shared.DICT.safe_set(key, value, exptime?, flags?)

与set方法类似,区别在于不会在共享内存用完的情况下,通过强制删除(LRU算法)的方法实现插入。如果内存不足,会直接返回nil和err信息"no memory"

ngx.shared.DICT.add(key, value, exptime?, flags?)

与set方法类似,与set方法区别在于不会插入重复的键(可以简单认为add方法是set方法的一个子方法),如果待插入的key已经存在,将会返回nil和和err="exists"

ngx.shared.DICT.safe_add(key, value, exptime?, flags?)

与safe_set方法类似,区别在于不会插入重复的键(可以简单认为safe_add方法是safe_set方法的一个子方法),如果待插入的key已经存在,将会返回nil和和err="exists"

ngx.shared.DICT.replace(key, value, exptime?, flags?)

与set方法类似,区别在于只对已经存在的key进行操作(可以简单认为replace方法是set方法的一个子方法),如果待插入的key在字典上不存在,将会返回nil和错误信息"not found"

ngx.shared.DICT.delete(key)

无条件删除指定的key-value对,其等价于ngx.shared.DICT:set(key, nil)

ngx.shared.DICT.incr(key, value)

对key对应的值进行增量操作,增量值是value,其中value的值可以是一个正数,0,也可以是一个负数。value必须是一个Lua类型中的number类型,否则将会返回nil和"not a number";key必须是一个已经存在于共享内存中的key,否则将会返回nil和"not found".

ngx.shared.DICT.flush_all()

清除字典上的所有字段,但不会真正释放掉字段所占用的内存,而仅仅是将每个字段标志为过期。

ngx.shared.DICT.flush_expired(max_count?)

清除字典上过期的字段,max_count表明上限值,如果为0或者没有给出,表明需要清除所有过期的字段,返回值flushed是实际删除掉的过期字段的数目。

注意:

与flush_all方法的区别在于,该方法将会释放掉过期字段所占用的内存

ngx.shared.DICT.get_keys(max_count?)

从字典上获取字段列表,个数为max_count,如果为0或没有给出,表明不限定个数。默认值是1024个

注意:

强烈建议在调用该方法时,指定一个max_count参数,因为在keys数量很大的情况下,如果不指定max_count的值,可能会导致字典被锁定,从而阻塞试图访问字典的worker进程。


猜你喜欢:

Java如何遍历map?

Java异常处理机制的原理和应用

java中equals和hashcode的区别

Java培训课程



分享到:
在线咨询 我要报名
和我们在线交谈!