《用OpenResty搭建高性能服务端》笔记 (4)

shared.dict 使用的是共享内存,每次操作都是全局锁,如果高并发环境,不同 worker 之间容易引起竞争。所以单个 shared.dict 的体积不能过大。lrucache 是 worker 内使用的,由于 Nginx 是单进程方式存在,所以永远不会触发锁,效率上有优势,并且没有 shared.dict 的体积限制,内存上也更弹性,但不同 worker 之间数据不同享,同一缓存数据可能被冗余存储。

你需要考虑的,一个是 Lua lru cache 提供的 API 比较少,现在只有 get、set 和 delete,而 ngx shared dict 还可以 add、replace、incr、get_stale(在 key 过期时也可以返回之前的值)、get_keys(获取所有 key,虽然不推荐,但说不定你的业务需要呢);第二个是内存的占用,由于 ngx shared dict 是 workers 之间共享的,所以在多 worker 的情况下,内存占用比较少。

本节内容参考来自:https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx_lua/cache.html

FFI和第三方模块 FFI

FFI是 LuaJIT 中的一个扩展库,它允许我们使用 Lua 代码调用C语言的数据结构和函数。

FFI库在很大程度上避免了在C中编写繁琐的手动 Lua/C 绑定的需要。无需学习单独的绑定语言 - 它解析普通的C声明!这些可以从C头文件或参考手册中剪切粘贴。

如何调用外部C库函数呢?
1、加载FFI库。
2、为函数添加C声明。
3、调用命名的C函数。

看一个官方提供的简单示例:

-- test_ffi.lua local ffi = require("ffi") ffi.cdef[[ int printf(const char *fmt, ...); ]] ffi.C.printf("Hello %s!", "world")

我们运行:

$ luajit test_ffi.lua Hello world!

详见:

增加第三方模块

默认的 resty 库所在位置:

$ pwd /usr/local/openresty $ ls lualib/ cjson.so ngx/ rds/ redis/ resty/ $ ls lualib/resty/ aes.lua limit/ md5.lua redis.lua sha384.lua upload.lua core/ lock.lua memcached.lua sha1.lua sha512.lua upstream/ core.lua lrucache/ mysql.lua sha224.lua sha.lua websocket/ dns/ lrucache.lua random.lua sha256.lua string.lua

现在以安装 lua-resty-http 为例:

$ cd /opt # 下载并解压 $ wget https://github.com/ledgetech/lua-resty-http/archive/v0.13.tar.gz && tar zxvf v0.13.tar.gz # 复制到resty目录即可 $ cp -r lua-resty-http-0.13/lib/resty/* /usr/local/openresty/lualib/resty/ # 查看安装的模块 $ cd /usr/local/openresty/lualib/resty/ && ls http* http_headers.lua http.lua

使用示例:

local http = require "resty.http" local httpc = http.new() local res, err = httpc:request_uri("http://example.com/helloworld", { method = "POST", body = "a=1&b=2", headers = { ["Content-Type"] = "application/x-www-form-urlencoded", }, keepalive_timeout = 60, keepalive_pool = 10 }) if not res then ngx.say("failed to request: ", err) return end ngx.status = res.status for k,v in pairs(res.headers) do -- end ngx.say(res.body) 子查询

子查询只是模拟 HTTP 接口的形式, 没有 额外的 HTTP/TCP 流量,也 没有 IPC (进程间通信) 调用。所有工作在内部高效地在 C 语言级别完成。

子查询只能在一个 location 里调用其它 一个或多个 `location。

res = ngx.location.capture(uri, options?) 发起子查询
返回一个包含四个元素的 Lua 表 (res.status, res.header, res.body, 和 res.truncated)。
作用域:rewrite_by_lua *,access_by_lua *,content_by_lua *。

示例:

res = ngx.location.capture( '/foo/bar', { method = ngx.HTTP_POST, body = 'hello, world' } )

res1, res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ... }) 发起多个并发子查询
作用域:rewrite_by_lua *,access_by_lua *,content_by_lua *。

示例:

res1, res2, res3 = ngx.location.capture_multi{ { "/foo", { args = "a=3&b=4" } }, { "/bar" }, { "/baz", { method = ngx.HTTP_POST, body = "hello" } }, } if res1.status == ngx.HTTP_OK then ... end if res2.body == "BLAH" then ... end

作用:
减少网络请求。
方便配置降级服务。

子查询文档参考:

执行阶段

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwzwd.html