openresty 学习记录

本篇是从https://legacy.gitbook.com/book/moonbingbing/openresty-best-practices 学习记录的,目的是为了查询方便。

openresty 学习记录

openresty与nginx的区别

  • OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项
  • OpenResty的目标是让你的Web服务直接跑在Nginx服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
  • 理解为openresty是进阶封装版的nginx

run

使用docker运行镜像

docker run --name openresty -d -p 80:80 -v /Users/zhangyong/Documents/docker/openresty/openresty/conf:/usr/local/openresty/nginx/conf openresty/openresty:focal-nosse42

测试一个lua写法,包括了并发请求。

server {
    listen 80;
    location / {
        default_type text/html;
        content_by_lua_block {
            ngx.say("HelloWorld")
            local res_add = ngx.location.capture(
            	"/add",{args={a=2, b=7}}
            )
            ngx.say(res_add.body)

			local res1,res2 = ngx.location.capture_multi({
            	{"/add",{args={a=3, b=7}}},
            	{"/del",{args={a=3, b=7}}}
            })
            ngx.say(res1.body,"---",res2.body)

        }
    }
    location /add {
		internal; #内部调用的路由
		content_by_lua_block{
			local args = ngx.req.get_uri_args()
			ngx.say(tonumber(args.a) + tonumber(args.b))
		}
    }
    location /del {
		internal; #内部调用的路由
		content_by_lua_block{
			local args = ngx.req.get_uri_args()
			ngx.say(tonumber(args.a) - tonumber(args.b))
		}
    }
}

玩法

  • ngx.location.capture_multi 是并发执行请求
  • ngx.exec 方法与 ngx.redirect 是完全不同的,前者是个纯粹的内部跳转并且没有引入任何额外 HTTP 信号
  • 对于location 中带有正则。 在里面可以用 $var_1 $1 $1 $2来接收。 ngx.var.var_1 来使用 var_1是变量名。
	location = / {
	    rewrite_by_lua_block {
	        return ngx.redirect('/add'); # 重定向
	    }
	}
  • ngx.req.get_uri_args、ngx.req.get_post_args前者来自 uri 请求参数,而后者来自 post 请求内容。由于 Nginx 是为了解决负载均衡场景诞生的,所以它默认是不读取 body 的行为,post参数需要加 ngx.req.read_body() 或者在外层指定lua_need_request_body on; 如下发送post到location的请求。ngx.location.capture是异步的、
res = ngx.location.capture(
     '/foo/bar',
     { method = ngx.HTTP_POST, body = 'hello, world' }
 )

得到响应返回一个包含四个元素的 Lua 表 (res.status, res.header, res.body, 和 res.truncated)。res.truncated是截断,布尔值标记来判断 res.body 是否包含截断的数据。这种数据截断的原因只可能是因为子请求发生了不可恢复的错误,例如远端在发送响应体时过早中断了连接,或子请求在接收远端响应体时超时。

  • 对于大文件分段返回可以
while true do
    data = file:read(1024)
    if nil == data then
        break
    end
    ngx.print(data)
    ngx.flush(true)
end
  • 对于日志输出,常规外围的nginx配置 error_log logs/error.log info; 指定info为error/其他日志级别
    ngx.log(ngx.ERR, "this is error log")
  • 可以通过access_by_lua_file做参数校验。
location ~ ^/api/([-_a-zA-Z0-9/]+) {
    access_by_lua_file  lua/access_check.lua;
    content_by_lua_file lua/$1.lua;
}
  • 模拟下载请求限速 返回结果
location /download {
        access_by_lua_block {
            ngx.var.limit_rate = 1000
        }
        content_by_lua_block{
			ngx.say(1111)
		}
    }

通过wget '127.0.0.1/download/1.cab' 访问可以将返回结果保存到 1.cab里面。

  • 创建新的HTTP请求,使用 resty.http模块
local http = require "resty.http"   
local httpc = http.new()
local data = {}
local res, err = httpc:request_uri(
    "http://127.0.0.1:81/hello",
        {
        method = "POST",
        body = data,
      }
)
  • 注意Redis缓冲池中的select(1) 可能会导致多个请求用到同一个Redis连接的时候使用的都是 select指定的库。
  • 异常处理,pcall 接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值 true 或者 false
local ok, t = pcall(test_method, str)
if not ok then
  return nil
end
return t
  • openresty的执行阶段
set_by_lua*: 流程分支处理判断变量初始化
rewrite_by_lua*: 转发、重定向、缓存等功能(例如特定请求代理到外网)
access_by_lua*: IP 准入、接口权限等情况集中处理(例如配合 iptable 完成简单防火墙)
content_by_lua*: 内容生成
header_filter_by_lua*: 响应头部过滤处理(例如添加头部信息)
body_filter_by_lua*: 响应体过滤处理(例如完成应答内容统一成大写)
log_by_lua*: 会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)
  • 热加载:lua_code_cache off 改完lua 不用重启
  • openresty使用缓存 在http模块配置lua_shared_dict my_cache 128m; 这个 cache 是 Nginx 所有 worker 之间共享的
location / {
    default_type text/html;
    content_by_lua_block {
        local cache_ngx = ngx.shared.my_cache
        cache_ngx:set('key', 111, 1000)
		local value = cache_ngx:get('key')
		ngx.say(value)
    }
}
  • 关于sleep ngx.sleep(1) 秒
  • 关于 定时器:ngx.timer.at(delay,function)
  • 返回给客户端结果,还可以做后续操作 ngx.eof() 之前可以ngx.say返回结果,然后后续做日志等操作,降低响应时间。但是不能是阻塞的操作。阻塞会占用 worker
  • 在 OpenResty 里面,只有在init_by_lua* 和 init_worker_by_lua* 阶段才能定义真正的全局变量。
  • 在将连接加入连接池的时候要保证这个连接是正常的,if not nil 否则连接池就脏了。只有数据传输完毕了,才能放到池子里,代码写到最后面。red:set_keepalive(10000, 100)
  • 使用resty的库,只需将对应的代码加入对应的目录中就行了。
  • keepalive_disable none; 设置完不会根据user-agent 中的浏览器信息来决定是否keepalive

你可能感兴趣的:(nginx)