四. 小结
这篇文章简单介绍了一下ngx_lua的基本用法,后一篇会对ngx_lua访问redis、memcached已经连接池进行详细介绍。
在之前的文章
中,已经介绍了ngx_lua的一些基本介绍,这篇文章主要着重讨论一下如何通过ngx_lua同后端的memcached、redis进行非阻塞通信。
1. Memcached
在Nginx中访问Memcached需要模块的支持,这里选用HttpMemcModule
,这个模块可以与后端的Memcached进行非阻塞的通信。我们知道官方提供了Memcached
,这个模块只支持get操作,而Memc支持大部分Memcached的命令。
Memc模块采用入口变量作为参数进行传递,所有以$memc_为前缀的变量都是Memc的入口变量。memc_pass指向后端的Memcached Server。
配置:
-
#使用HttpMemcModule
-
location = /memc {
-
set $memc_cmd $arg_cmd;
-
set $memc_key $arg_key;
-
set $memc_value $arg_val;
-
set $memc_exptime $arg_exptime;
-
-
memc_pass '127.0.0.1:11211';
-
}
输出:
-
$ curl 'http://localhost/memc?cmd=set&key=foo&val=Hello'
-
$ STORED
-
$ curl 'http://localhost/memc?cmd=get&key=foo'
-
$ Hello
这就实现了memcached的访问,下面看一下如何在lua中访问memcached。
配置:
-
#在Lua中访问Memcached
-
location = /memc {
-
internal; #只能内部访问
-
set $memc_cmd get;
-
set $memc_key $arg_key;
-
memc_pass '127.0.0.1:11211';
-
}
-
location = /lua_memc {
-
content_by_lua '
-
local res = ngx.location.capture("/memc", {
-
args = { key = ngx.var.arg_key }
-
})
-
if res.status == 200 then
-
ngx.say(res.body)
-
end
-
';
-
}
输出:
-
$ curl 'http://localhost/lua_memc?key=foo'
-
$ Hello
通过lua访问memcached,主要是通过子请求采用一种类似函数调用的方式实现。首先,定义了一个memc
location用于通过后端memcached通信,就相当于memcached
storage。由于整个Memc模块时非阻塞的,ngx.location.capture也是非阻塞的,所以整个操作非阻塞。
2. Redis
访问redis需要HttpRedis2Module
的支持,它也可以同redis进行非阻塞通行。不过,redis2的响应是redis的原生响应,所以在lua中使用时,需要解析这个响应。可以采用LuaRedisModule
,这个模块可以构建redis的原生请求,并解析redis的原生响应。
配置:
-
#在Lua中访问Redis
-
location = /redis {
-
internal; #只能内部访问
-
redis2_query get $arg_key;
-
redis2_pass '127.0.0.1:6379';
-
}
-
location = /lua_redis { #需要LuaRedisParser
-
content_by_lua '
-
local parser = require("redis.parser")
-
local res = ngx.location.capture("/redis", {
-
args = { key = ngx.var.arg_key }
-
})
-
if res.status == 200 then
-
reply = parser.parse_reply(res.body)
-
ngx.say(reply)
-
end
-
';
-
}
输出:
-
$ curl 'http://localhost/lua_redis?key=foo'
-
$ Hello
和访问memcached类似,需要提供一个redis storage专门用于查询redis,然后通过子请求去调用redis。
3. Redis Pipeline
在实际访问redis时,有可能需要同时查询多个key的情况。我们可以采用ngx.location.capture_multi通过发送多个子请求给
redis
storage,然后在解析响应内容。但是,这会有个限制,Nginx内核规定一次可以发起的子请求的个数不能超过50个,所以在key个数多于50时,
这种方案不再适用。
幸好redis提供pipeline机制,可以在一次连接中执行多个命令,这样可以减少多次执行命令的往返时延。客户端在通过pipeline发送多个命
令后,redis顺序接收这些命令并执行,然后按照顺序把命令的结果输出出去。在lua中使用pipeline需要用到redis2模块的
redis2_raw_queries进行redis的原生请求查询。
配置:
-
#在Lua中访问Redis
-
location = /redis {
-
internal; #只能内部访问
-
-
redis2_raw_queries $args $echo_request_body;
-
redis2_pass '127.0.0.1:6379';
-
}
-
-
location = /pipeline {
-
content_by_lua 'conf/pipeline.lua';
-
}
pipeline.lua
-
-- conf/pipeline.lua file
-
local parser = require(‘redis.parser’)
-
local reqs = {
-
{‘get’, ‘one’}, {‘get’, ‘two’}
-
}
-
-- 构造原生的redis查询,get one\r\nget two\r\n
-
local raw_reqs = {}
-
for i, req in ipairs(reqs) do
-
table.insert(raw_reqs, parser.build_query(req))
-
end
-
local res = ngx.location.capture(‘/redis?’..#reqs, { body = table.concat(raw_reqs, ‘’) })
-
-
if res.status and res.body then
-
-- 解析redis的原生响应
-
local replies = parser.parse_replies(res.body, #reqs)
-
for i, reply in ipairs(replies) do
-
ngx.say(reply[1])
-
end
-
end
输出:
-
$ curl 'http://localhost/pipeline'
-
$ first
-
second
4. Connection Pool
前面访问redis和memcached的例子中,在每次处理一个请求时,都会和后端的server建立连接,然后在请求处理完之后这个连接就会被释放。
这个过程中,会有3次握手、timewait等一些开销,这对于高并发的应用是不可容忍的。这里引入connection pool来消除这个开销。
连接池需要HttpUpstreamKeepaliveModule
模块的支持。
配置:
-
http {
-
# 需要HttpUpstreamKeepaliveModule
-
upstream redis_pool {
-
server 127.0.0.1:6379;
-
# 可以容纳1024个连接的连接池
-
keepalive 1024 single;
-
}
-
-
server {
-
location = /redis {
-
…
-
redis2_pass redis_pool;
-
}
-
}
-
}
这个模块提供keepalive指令,它的context是upstream。我们知道upstream在使用Nginx做反向代理时使用,实际
upstream是指“上游”,这个“上游”可以是redis、memcached或是mysql等一些server。upstream可以定义一个虚拟
server集群,并且这些后端的server可以享受负载均衡。keepalive
1024就是定义连接池的大小,当连接数超过这个大小后,后续的连接自动退化为短连接。连接池的使用很简单,直接替换掉原来的ip和端口号即可。
有人曾经测过,在没有使用连接池的情况下,访问memcached(使用之前的Memc模块),rps为20000。在使用连接池之后,rps一路飙到140000。在实际情况下,这么大的提升可能达不到,但是基本上100-200%的提高还是可以的。
5. 小结
这里对memcached、redis的访问做个小结。
1. Nginx提供了强大的编程模型,location相当于函数,子请求相当于函数调用,并且location还可以向自己发送子请求,这样构成一个递归的模型,所以采用这种模型实现复杂的业务逻辑。
2. Nginx的IO操作必须是非阻塞的,如果Nginx在那阻着,则会大大降低Nginx的性能。所以在Lua中必须通过ngx.location.capture发出子请求将这些IO操作委托给Nginx的事件模型。
3. 在需要使用tcp连接时,尽量使用连接池。这样可以消除大量的建立、释放连接的开销。
分享到:
相关推荐
ngx_lua 允许开发者在 Nginx 的事件驱动、非阻塞 I/O 模型下编写服务器端的 Lua 应用程序,极大地提高了 Web 应用的并发处理能力。 首先,我们要理解 Nginx 的工作原理。Nginx 是一款高性能的 HTTP 和反向代理...
根据提供的文件内容,这篇文档主要围绕在UPYUN云平台上使用ngx_lua模块与Nginx结合进行...特别是结合了OpenResty所集成了大量高性能Lua库,使得Nginx的应用场景更加广泛,尤其适用于需要处理复杂逻辑的高并发Web服务。
综上所述,"Using ngx_lua in UPYUN 2"的主题涵盖了 ngx_lua 模块的使用方法、Lua 语言在 Nginx 中的应用,以及如何在 UPYUN 平台上构建高效的 Web 服务。通过深入学习这些知识点,开发者可以充分利用 ngx_lua 的...
Lua支持轻量级的协程,可以在不引入多线程复杂性的前提下实现并发。 总结,Lua-Nginx-Module 0.10.13是Nginx的强大扩展,它将Lua语言的灵活性和Nginx的高性能结合起来,为Web开发提供了新的可能。通过学习和掌握lua...
【知识点详解】 本文将介绍如何在CentOS 7 64位...通过上述步骤,可以在CentOS 7系统上构建一个具备WAF功能的Nginx服务器,利用ngx_lua模块的强大灵活性来实施自定义的安全策略,保护Web应用程序免受各种网络攻击。
这个架构旨在解决高并发场景下,确保请求按序处理,防止资源争抢,优化服务性能的问题。以下是这个系统架构的关键知识点详解: 1. **Nginx与lua模块**: Nginx是一个高性能的HTTP和反向代理服务器,以其轻量级、...
在Nginx的生态系统中,NDK扮演着至关重要的角色,它提供了一系列的API和宏,帮助开发者更高效地构建自定义模块,从而扩展Nginx的功能。 首先,我们来了解下Nginx的基本架构。Nginx以其高效的事件驱动模型而闻名,它...
1. **基于 cosocket:** `lua-resty-http` 使用 OpenResty 的 cosocket 驱动,提供非阻塞 I/O 操作,能够高效处理高并发请求,提高性能。 2. **HTTP/1.1 支持:** 它支持完整的 HTTP/1.1 协议,包括 GET、POST、PUT...
ngx_openresty是一个高度集成的Nginx发行版,它包含了一个强大的动态脚本语言LuaJIT,并且集成了许多第三方模块,使得开发者能够轻松地构建高性能的Web应用和服务。ngx_openresty-1.9.3.2是该发行版的一个特定版本,...
总的来说,ngx_openresty通过结合Nginx的高性能和Lua的灵活性,为构建高性能、高并发的Web服务提供了一种强大且高效的方式。通过深入学习和掌握OpenResty,开发者可以构建出复杂而强大的Web应用程序。
在实际应用中,`lua-resty-beanstalkd` 可用于构建高性能的 Web 应用,比如处理异步任务(如发送邮件、图片处理等),或者在分布式系统中协调不同组件的工作。通过利用非阻塞 I/O 和 Lua 的简洁性,它可以帮助你构建...
同时,该版本还对内存管理和线程安全进行了优化,确保在高并发场景下的稳定性。 除了基础功能外,lua-nginx-module还支持一些高级特性,如定时任务、持久化存储、与外部服务的异步通信等。例如,通过`ngx.timer.at...
ngx_openresty是一个基于Nginx的全功能Web平台,它集成了LuaJIT脚本语言,使得开发者能够轻松地构建高性能的Web应用。ngx_openresty-1.9.7.1.tar.gz是一个压缩包文件,包含了ngx_openresty在1.9.7.1版本的所有源代码...
使用 `cosocket`,开发者可以在 Lua 脚本中编写高并发、低延迟的网络应用,非常适合于处理大量的并发请求。 Couchbase 是一个分布式文档数据库系统,支持 JSON 文档存储,并提供了丰富的查询语言 N1QL(N1xt Query ...
总之,《Lua程序设计》不仅介绍了Lua语言的基本特性和高级特性,还详细讲解了如何在Nginx环境中运用Lua,帮助读者从零开始,逐步成长为一名熟练的Lua开发者,能够利用Lua和Nginx构建高性能的Web服务。书中的实例和...
在构建高性能和灵活的服务调度系统时,`nginx`作为一个强大的反向代理和负载均衡器,常常被用来处理复杂的网络流量管理。结合`lua`脚本语言以及特定的模块,如`dyups`,可以实现自定义的服务调度策略。本文将详细...
在ngx_devel_kit-0.3.0rc1版本中,它提供了许多实用的API和功能,以便开发者能够更方便地构建自定义模块或扩展Nginx的核心功能。 Nginx是一款高性能的HTTP和反向代理服务器,以其轻量级、高效的处理能力以及强大的...
2. **配置使用**:在Nginx的配置文件(如`nginx.conf`)中,你可以通过`lua_code_cache`指令控制Lua脚本的缓存策略,`init_by_lua_file`或`init_by_lua`用于执行启动时的Lua代码,`set_by_lua_block`、`rewrite_by_...
2. **性能优势**:由于LuaJIT(Just-In-Time编译器)的存在,Lua代码可以被高效地执行,而且在Nginx的非阻塞事件模型下,能够处理大量并发连接,提高了系统性能。 ### 二、Lua在Nginx中的应用 1. **动态配置**:...