使用lua调用mongoDB 实例,lua调用mongodb实例


引言
公司需要做一个类似站长统计的项目,给了很多种方案;其中有个方案就是利用ngx_lua(openResty) 调用mongodb 来做日志的存储;在项目之前启动之前,自己研究了这个方案的可行性,编写写了一个demo。


1.准备
(1)看过openresty的都应该知道,openresty只提供redis 的module模块,没有提供mongoDB的驱动模块(不懂openresty;可以看下openresty最佳实现);所以我们这边要先提供一个驱动,去中文论坛找了一番;发现了几个不错的结合lua 的mongodb的libarary项目:
在github上有lua-resty-mongol、还有wuxianglong的lua-mongo等项目;综合考虑了之后,打算用lua-resty-mongol 这个项目;因为这个项目本身就是为了兼容openresty设计的。
(2)这个demo本身是基于openresty中编写的,所以在你的系统上需要安装openresty,我这里用的是centos 6.5 的系统,至于具体的下载 安装,这里就不详细介绍了;如果有需要的话可以看看这篇文章http://www.52yunwei.cn/?p=415;
(3) 前面说到过 lua-resty-mongol 项目,我们要下载github下的这个项目;下载后编译,
make install
把解压的包 解压到 lualib/resty/中下
如果你的openresty默认安装的话是在/usr/local/openresty/lialib 下,我这边的路径是在 opt/openresty/lualib/resty 下;
(4)就是对应的mongodb 服务,我这里的mongodb 服务是在自己的虚拟机中,如果没有的话,先去官网下载一个mongodb,然后启动
这里就不详细介绍了


2.实例
(1).之前lua-resty-mongol 项目还要有一个配置项,就是要在nginx.conf 中配置上 你mongol 的默认初始化路径

# 之前说过了,你要是是默认的openresty的话  这里就可以配置是/usr/local/openresty/lialib/?/了#
 lua_package_path        '/opt/opentresty/lualib/?/init.lua;;';

(2). 对于ngx中的整个nginx.conf 配置如下

user  nginx;
worker_processes  4;
pid                             /opt/logs/nginx/nginx.pid;
error_log               /opt/logs/nginx/error.log;

events {
    use epoll;
    worker_connections  10240;
}
http {
        include       mime.types;
        #default_type           'text/html';
        #定义日志格式
        #default_type           'application/octet-stream';
        #指定lua_mongol 初始化默认路径
        default_type            'text/plain';
        lua_package_path        '/opt/opentresty/lualib/?/init.lua;;';
        charset                         utf-8;
        error_log               /opt/logs/nginx/error.log;

        access_log              off;
        #log_format  main  '$remote_addr\t$uid_got$uid_set\t$http_host\t$time_iso8601\t$request\t$status\t$body_bytes_sent\t$http_referer\t$request_time\t$http_user_agent';
        #log_format  tick '$msec^A$remote_addr^A$u_domain^A$u_url^A$u_title^A$u_referrer^A$u_sh^A$u_sw^A$u_cd^A$u_lang^A$http_user_agent^A$u_utrace^A$u_account';
        log_format tick '$msec ^A^ $remote_addr ^A^ $u_domain ^A^ $u_url ^A^ $u_title ^A^ $u_referrer ^A^ $u_sh ^A^ $u_sw ^A^ $u_cd ^A^ $u_lang ^A^ $http_user_agent ^A^ $u_utrace ^A^ $u_account';

        client_max_body_size 100m;
        sendfile        on;
        keepalive_timeout  60;
        fastcgi_intercept_errors on;
        proxy_connect_timeout 60;
        proxy_send_timeout 90;
        proxy_read_timeout 1800;
        large_client_header_buffers 4 128k;
        proxy_ignore_client_abort on;


        gzip on;
        gzip_min_length 10k;
        gzip_buffers 4 16k;
        gzip_comp_level 2;
        gzip_types text/plain text/javascript application/javascript application/x-javascript text/css  application/xml application/octet-stream;
        gzip_vary on;
        #userid
        userid                          on;
        userid_name                     UUID;
        userid_path                     /;
        userid_expires                  max;

        include _ext.conf;
        include apps/*.conf;
  }

(3).配置需要的location
从上面是nginx.conf 中可以看出,我这里的server都是在apps子文件夹创建,我在apps 文件中有个叫
_mongo.conf 的配置文件,里面配置这lua 调用mongodb 的location

server {
        listen   8081;
        server_name 192.168.1.128;
        #关闭lua_code 缓存
        lua_code_cache off;
        location /lua {
                content_by_lua_file  /opt/openresty/lualib/resty/mongol/test_lua.lua;
        }
        location /lua_mongo {
                content_by_lua_file /opt/openresty/lualib/resty/mongol/test_mongol.lua;
        }
        location /lua_test {
                set $test "hello world";
                #使用acess 阶段做准入条件处理
                access_by_lua '
                        if (ngx.var.test =="hello world") then 
                                ngx.say("验证通过"..ngx.var.test)
                        else 
                                ngx.log(ngx.ERR,"验证失败","")
                        end
                ';
                #业务处理
                content_by_lua '
                        ngx.header.content_type ="text/plain";
                        local a, b =1;
                        ngx.say(ngx.var.test..a);
                ';
        }


}

location lua_mongo 中content_by_lua_file 是lua调用了mongodb具体操作
执行在/opt/openresty/lualib/resty/mongol/下的test_mongol.lua 文件,该文件的内容是:

local mongo =require "resty.mongol"
local json = require "cjson"
--获取连接对象
local conn =mongo:new()
conn:set_timeout(1000)
--获取连接客户端
local ok,err =conn:connect("192.168.1.128",27017)

if not ok then 
        ngx.say("connect failed"..err)
end 
--获取数据库
local db = conn:new_db_handle("leo")
--用户授权
local ok ,err = db:auth("zjf","zjf123456")

if ok then 
        ngx.say("user auth success"..ok)
end 
--获取集合
local coll = db:get_col("leonardo")
--获取document集合
local cursor = coll:find({})

--json 转码
--
function json_decode( str )
        local json_value =nil
        pcall(function (str) json_value = json.decode(str) end, str)
        return json_value 
end

--循环 
for index,item in cursor:pairs() do
        ngx.say('数据: '..index)
        if not item['url'] then 
                ngx.say('数据:'..item["title"])
        else
                ngx.say('数据:'..item["title"]..item['url'])
                ngx.say(json_decode(item['url']))
        end

end
--获取单个集合
local res =coll:find_one({key = 150})

if res then 

        ngx.say(res['title'])
end

--插入集合
local bson1 ={title ='哈哈',url = 'www.baidu.com',key = 300};
--插入table 表中 
local docs ={bson1};

local rsOk,err =coll:insert(docs,0,0)

if err then 
        ngx.say('error--'..err)
else 
        ngx.say('ok---- '..rsOk)
end

--删除操作
local deOk,err = coll:delete({title ='你好'},0,0)

if err then 
        ngx.say('delete error--'..err)
else
        ngx.say('delete ok--'..deOk)
end

--关闭连接
if conn then 

        conn:close()
end 

到这里一个完整的例子就写好了 。
(4).启动mongodb 服务,启动nginx 服务

[root@leoleo apps]# curl 192.168.1.128:8081/lua_mongo
数据: 1
数据:哈哈www.baidu.com
nil
数据: 2
数据:哈哈www.baidu.com
nil
数据: 3
数据:哈哈www.baidu.com
nil
ok---- -1
delete ok---1
[root@leoleo apps]# 

这个demo 就这样写好了


3.后话**
使用lua_nginx+mongodb这个方案最后被我们项目组否决了,原因呢?
虽然用lua 可以实现将网页上收集到用户操作行为通过的nginx写入mongodb中;但是lua 直接操作mongodb 有很多缺陷,比如这里是当实例,就是每次写入都要获取一个连接实例,开启一个连接;网页上的行为收集是一个高并发的,显然这个demo 这样的是不满足的。

相关内容

    暂无相关文章