OpenResty-Lua模块开发

fengchao000 2017-07-26

原创地址:http://jinnianshilongnian.iteye.com/blog/2190344

常用命令

# vi /usr/local/nginx/conf/nginx.conf

# vi /usr/server/example/example.conf

# /usr/local/nginx/sbin/nginx  -s reload &  tail -f /usr/local/nginx/logs/error.log

目录:

1.OpenRestry(Nginx+Lua)开发环境

2.OpenRestry开发入门

3.Lua模块开发

3.1 常用Lua开发库1-redis、mysql、http客户端 附-Redis/SSDB+Twemproxy安装与使用

3.2 常用Lua开发库2-JSON库、编码转换、字符串处理

3.3 常用Lua开发库3-模板渲染

4.实战

4.1 Web开发实战1——HTTP服务

4.2 Web开发实战2——商品详情页

4.3 流量复制/AB测试/协程

 一.Lua模块开发

在实际开发中,不可能把所有代码写到一个大而全的lua文件中,需要进行分模块开发;而且模块化是高性能Lua应用的关键。

使用require第一次导入模块后,所有Nginx进程全局共享模块的数据和代码,每个Worker进程需要时会得到此模块的一个副本(Copy-On-Write),即模块可以认为是每Worker进程共享而不是每Nginx Server共享;

另外注意之前我们使用init_by_lua中初始化的全局变量是每请求复制一个;

如果想在多个Worker进程间共享数据可以使用ngx.shared.DICT或如Redis之类的存储。

1.大量第三方开发库如cjson、redis客户端、mysql客户端:/usr/server/example/lualib

 # ls -l /usr/server/example/lualib

cjson.so

resty/

   aes.lua

   core.lua

   dns/

   lock.lua

   lrucache/

   lrucache.lua

   md5.lua

   memcached.lua

   mysql.lua

   random.lua

   redis.lua

   ……

2.如何使用

1.在使用前需要将库在nginx.conf中导入:

    #lua模块路径,其中”;;”表示默认搜索路径,默认到/usr/local/nginx下找  

    lua_package_path   "/usr/server/example/lualib/?.lua;;";  #lua 模块  

    lua_package_cpath "/usr/server/example/lualib/?.so;;";  #c模块   

2.使用方式是在lua中通过如下方式引入

    local cjson = require(“cjson”)  

    local redis = require(“resty.redis”)   

3.案例:

(1) 开发一个简单的lua模块。

# vi  /usr/server/example/lualib/module1.lua

    local count = 0  

    local function hello()  

       count = count + 1  

       ngx.say("count : ", count)  

    end  

      

    local _M = {  

       hello = hello  

    }  

      

    return _M  

开发时将所有数据做成局部变量/局部函数;通过 _M导出要暴露的函数,实现模块化封装。

(2) 使用该模块

test_module_1.lua

#  vi /usr/server/example/lua/test_module_1.lua

    local module1 = require("module1")     

    module1.hello()  

 使用 local var = require("模块名"),该模块会到 lua_package_path 和 lua_package_cpath 声明的的位置查找我们的模块,对于多级目录的使用require("目录1.目录2.模块名")加载。

(3)配置example.conf

# vi  /usr/server/example/example.conf

    location /lua_module_1 {  

        default_type 'text/html';  

        lua_code_cache on;  

        content_by_lua_file /usr/server/example/lua/test_module_1.lua;  

    }  

访问如 http://192.168.1.106/lua_module_1 进行测试,会得到类似如下的数据,count会递增

count : 1

count :2

……

count :N

此时可能发现count一直递增,假设我们的worker_processes  2,我们可以通过kill -9 nginx worker process 杀死其中一个Worker进程得到count数据变化。

假设我们创建了vi /usr/example/lualib/test/module2.lua模块,可以通过local module2 = require("test.module2")加载模块

基本的模块开发就完成了,如果是只读数据可以通过模块中声明local变量存储;如果想在每Worker进程共享,请考虑竞争;如果要在多个Worker进程间共享请考虑使用ngx.shared.DICT或如Redis存储。

目前对于互联网公司不使用Redis的很少,Redis不仅仅可以作为key-value缓存,而且提供了丰富的数据结果如set、list、map等,可以实现很多复杂的功能;但是Redis本身主要用作内存缓存,不适合做持久化存储,因此目前有如SSDB、ARDB等,还有如京东的JIMDB,它们都支持Redis协议,可以支持Redis客户端直接访问;而这些持久化存储大多数使用了如LevelDB、RocksDB、LMDB持久化引擎来实现数据的持久化存储;京东的JIMDB主要分为两个版本:LevelDB和LMDB,而我们看到的京东商品详情页就是使用LMDB引擎作为存储的,可以实现海量KV存储;当然SSDB在京东内部也有些部门在使用;另外调研过得如豆瓣的beansDB也是很不错的。具体这些持久化引擎之间的区别可以自行查找资料学习。

二.常用Lua开发库1-redis、mysql、http客户端 附-Redis/SSDB+Twemproxy安装与使用

1.附-Redis/SSDB+Twemproxy安装与使用

1.1Redis安装与使用

 见:Redis介绍及安装集群使

1.2 twemproxy

见:Twemproxy-缓存代理分片机制 OpenResty-Lua模块开发

因为我们所有的Twemproxy配置文件规则都是一样的,因此我们应该将其移到我们项目中。

cp /usr/servers/twemproxy-0.4.0/conf/nutcracker.yml  /usr/example/ 

6.Redis执行Lua脚本

Redis客户端支持解析和处理lua脚本,因为Redis的单线程机制,我们可以借助Lua脚本实现一些原子操作,如扣减库存/红包之类的。此处不建议使用EVAL直接发送lua脚本到客户端,因为其每次都会进行Lua脚本的解析,而是使用SCRIPT LOAD+ EVALSHA进行操作。未来不知道是否会用luajit来代替lua,让redis lua脚本性能更强。

到此基本的Redis知识就讲完了。

 1.3 SSDB

见:SSDB介绍与使用

相关推荐