0

0

使用ngx_lua构建高并发应用

php中文网

php中文网

发布时间:2016-07-30 13:31:38

|

1175人浏览过

|

来源于php中文网

原创

这篇文章主要着重讨论一下如何通过ngx_lua同后端的memcached、redis进行非阻塞通信。

1. Memcached

        在Nginx中访问Memcached需要模块的支持,这里选用HttpMemcModule,这个模块可以与后端的Memcached进行非阻塞的通信。我们知道官方提供了Memcached,这个模块只支持get操作,而Memc支持大部分Memcached的命令。

        Memc模块采用入口变量作为参数进行传递,所有以$memc_为前缀的变量都是Memc的入口变量。memc_pass指向后端的Memcached Server。

  配置:

[plain] view plaincopyprint?

  1. #使用HttpMemcModule  
  2. location = /memc {  
  3.     set $memc_cmd $arg_cmd;  
  4.     set $memc_key  $arg_key;  
  5.     set $memc_value $arg_val;  
  6.     set $memc_exptime $arg_exptime;  
  7.           
  8.     memc_pass '127.0.0.1:11211';  
  9. }  

        输出:

[plain] view plaincopyprint?

  1. $ curl  'http://localhost/memc?cmd=set&key=foo&val=Hello'  
  2. $ STORED  
  3. $ curl  'http://localhost/memc?cmd=get&key=foo'  
  4. $ Hello  
        这就实现了memcached的访问,下面看一下如何在lua中访问memcached。

  配置:

[plain] view plaincopyprint?

  1. #在Lua中访问Memcached  
  2. location = /memc {  
  3.     internal;   #只能内部访问  
  4.     set $memc_cmd get;  
  5.     set $memc_key  $arg_key;  
  6.     memc_pass '127.0.0.1:11211';  
  7. }  
  8. location = /lua_memc {  
  9.     content_by_lua '  
  10.         local res = ngx.location.capture("/memc", {  
  11.             args = { key = ngx.var.arg_key }  
  12.         })  
  13.         if res.status == 200 then  
  14.             ngx.say(res.body)  
  15.         end  
  16.     ';  
  17. }  
        输出:

[plain] view plaincopyprint?

  1. $ curl  'http://localhost/lua_memc?key=foo'  
  2. $ Hello  
        通过lua访问memcached,主要是通过子请求采用一种类似函数调用的方式实现。首先,定义了一个memc location用于通过后端memcached通信,就相当于memcached storage。由于整个Memc模块时非阻塞的,ngx.location.capture也是非阻塞的,所以整个操作非阻塞。

2. Redis

        访问redis需要HttpRedis2Module的支持,它也可以同redis进行非阻塞通行。不过,redis2的响应是redis的原生响应,所以在lua中使用时,需要解析这个响应。可以采用LuaRedisModule,这个模块可以构建redis的原生请求,并解析redis的原生响应。

        配置:

[plain] view plaincopyprint?

  1. #在Lua中访问Redis  
  2. location = /redis {  
  3.     internal;   #只能内部访问  
  4.     redis2_query get $arg_key;  
  5.     redis2_pass '127.0.0.1:6379';  
  6. }   
  7. location = /lua_redis { #需要LuaRedisParser  
  8.     content_by_lua '  
  9.         local parser = require("redis.parser")  
  10.         local res = ngx.location.capture("/redis", {  
  11.             args = { key = ngx.var.arg_key }  
  12.         })  
  13.         if res.status == 200 then  
  14.             reply = parser.parse_reply(res.body)  
  15.             ngx.say(reply)  
  16.         end  
  17.     ';  
  18. }  
        输出:

[plain] view plaincopyprint?

  1. $ curl  'http://localhost/lua_redis?key=foo'  
  2. $ 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的原生请求查询。

网胜B2B电子商务系统蓝色风格 2008 SP6.2 普及版
网胜B2B电子商务系统蓝色风格 2008 SP6.2 普及版

  websenB2B是一套经过完善设计的B2B行业网站程序,是windows nt系列环境下最佳的B2B行业网产站解决方案。精心设计的架构与功能机制,适合从个人到企业各方面应用的要求,为您提供一个安全、稳定、高效、易用而快捷的行业网站商务系统。分普及版和商业版等不同版本。一、网胜B2B电子商务系统SP6.2蓝色风格普及版本升级功能说明:1、邮件群发功能:可以选择某一级别的会员,并放入支持html

下载

        配置:

[plain] view plaincopyprint?

  1. #在Lua中访问Redis  
  2. location = /redis {  
  3.     internal;   #只能内部访问  
  4.   
  5.     redis2_raw_queries $args $echo_request_body;  
  6.     redis2_pass '127.0.0.1:6379';  
  7. }   
  8.       
  9. location = /pipeline {  
  10.     content_by_lua 'conf/pipeline.lua';  
  11. }   
        pipeline.lua

[plain] view plaincopyprint?

  1. -- conf/pipeline.lua file  
  2. local parser = require(‘redis.parser’)  
  3. local reqs = {   
  4.     {‘get’, ‘one’}, {‘get’, ‘two’}   
  5. }  
  6. -- 构造原生的redis查询,get one\r\nget two\r\n  
  7. local raw_reqs = {}  
  8. for i, req in ipairs(reqs)  do  
  9.       table.insert(raw_reqs, parser.build_query(req))  
  10. end  
  11. local res = ngx.location.capture(‘/redis?’..#reqs, { body = table.concat(raw_reqs, ‘’) })  
  12.       
  13. if res.status and res.body then  
  14.        -- 解析redis的原生响应  
  15.        local replies = parser.parse_replies(res.body, #reqs)  
  16.        for i, reply in ipairs(replies)  do   
  17.           ngx.say(reply[1])  
  18.        end  
  19. end  
        输出:

[plain] view plaincopyprint?

  1. $ curl  'http://localhost/pipeline'  
  2. $ first  
  3.   second  

4. Connection Pool

        前面访问redis和memcached的例子中,在每次处理一个请求时,都会和后端的server建立连接,然后在请求处理完之后这个连接就会被释放。这个过程中,会有3次握手、timewait等一些开销,这对于高并发的应用是不可容忍的。这里引入connection pool来消除这个开销。

        连接池需要HttpUpstreamKeepaliveModule模块的支持。

        配置:

[plain] view plaincopyprint?

  1. http {  
  2.     # 需要HttpUpstreamKeepaliveModule  
  3.     upstream redis_pool {  
  4.         server 127.0.0.1:6379;  
  5.         # 可以容纳1024个连接的连接池  
  6.         keepalive 1024 single;  
  7.     }  
  8.       
  9.     server {  
  10.         location = /redis {  
  11.             …  
  12.             redis2_pass redis_pool;  
  13.         }  
  14.     }  
  15. }  
        这个模块提供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构建高并发应用,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

705

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

233

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

117

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

22

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

61

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

30

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

669

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

58

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
深入剖析redis教程
深入剖析redis教程

共55课时 | 8.2万人学习

Memcached手册
Memcached手册

共0课时 | 0.1万人学习

韩顺平Memcached视频教程
韩顺平Memcached视频教程

共10课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号