OpenResty高并发最佳实践--mysql操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lupengfei1009/article/details/86169560

前言

OpenResty虽然为了提高性能更多的是使用的内存数据库(OpenResty操作redis可参考:OpenResty高并发最佳实践–Redis操作),但是特殊的时候也会存在需要操作数据库的时候,下面介绍如何通过OpenResty操作mysql

准备

不了解OpenResty的可以参考以下文章
OpenResty(Nginx+Lua)高并发最佳实践
Window下基于ZeroBrane Studio开发调试OpenResty

mysql数据库安装可参考以下文章
MySQL安装及可视化工具使用

代码走着

  • mysql连接池(工具类)
    在OpenResty的lualib目录下创建testcode文件夹,用于放置我们的测试lua脚本,并在文件夹下创建mysql_factory.lua,如下图:

    将以下代码拷贝至该文件(不需要做任何修改):
    local mysql = require("resty.mysql")  
     
    local mysql_pool = {}  
      
    --[[  
        先从连接池取连接,如果没有再建立连接.  
        返回:  
            false,出错信息.  
            true,数据库连接  
    --]]  
    function mysql_pool:get_connect(cfg)  
        if ngx.ctx[mysql_pool] then  
            return true, ngx.ctx[mysql_pool]  
        end  
      
        local client, errmsg = mysql:new()  
        if not client then  
            return false, "mysql.socket_failed: " .. (errmsg or "nil")  
        end  
      
        client:set_timeout(10000)  --30秒  
      
        local options = {  
            host = cfg.db.prod.HOST,  
            port = cfg.db.prod.PORT,  
            user = cfg.db.prod.USER,  
            password = cfg.db.prod.PASSWORD,  
            database = cfg.db.prod.DATABASE  
        }  
      
        local result, errmsg, errno, sqlstate = client:connect(options)  
        if not result then  
            return false, "mysql.cant_connect: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..  
                    ", sql_state:" .. (sqlstate or "nil")  
        end  
      
        local query = "SET NAMES " .. "utf8"  
        local result, errmsg, errno, sqlstate = client:query(query)  
        if not result then  
            return false, "mysql.query_failed: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..  
                    ", sql_state:" .. (sqlstate or "nil")  
        end  
      
        ngx.ctx[mysql_pool] = client  
      
        -- 测试,验证连接池重复使用情况  
        --[[ comments by leon1509  
        local count, err = client:get_reused_times()  
        ngx.say("xxx reused times" .. count);  
        --]]  
      
        return true, ngx.ctx[mysql_pool]  
    end  
      
    --[[  
        把连接返回到连接池  
        用set_keepalive代替close() 将开启连接池特性,可以为每个nginx工作进程,指定连接最大空闲时间,和连接池最大连接数  
     --]]  
    function mysql_pool:close()  
        if ngx.ctx[mysql_pool] then  
            -- 连接池机制,不调用 close 而是 keeplive 下次会直接继续使用  
            -- lua_code_cache 为 on 时才有效  
            -- 60000 : pool_max_idle_time , 100:connections  
            ngx.ctx[mysql_pool]:set_keepalive(60000, 80)  
            -- 调用了 set_keepalive,不能直接再次调用 query,会报错  
            ngx.ctx[mysql_pool] = nil  
        end  
    end  
      
    --[[  
        查询  
        有结果数据集时返回结果数据集  
        无数据数据集时返回查询影响  
        返回:  
            false,出错信息,sqlstate结构.  
            true,结果集,sqlstate结构.  
    --]]  
    function mysql_pool:query(sql, flag)  
        local ret, client = self:get_connect(flag)  
        if not ret then  
            return false, client, nil  
        end  
      
        local result, errmsg, errno, sqlstate = client:query(sql)  
      
        while errmsg == "again" do  
            result, errmsg, errno, sqlstate = client:read_result()  
        end  
      
        self:close()  
      
        if not result then  
            errmsg = "mysql.query_failed:" .. (errno or "nil") .. (errmsg or "nil")  
            return false, errmsg, sqlstate  
        end  
      
        return true, result, sqlstate  
    end  
      
    return mysql_pool
    
  • 配置文件
    同级目录下创建config_constant.lua,用于放置redis、mysql或者其他的公共配置文件
    将以下代码拷贝至该文件,具体配置数据请根据自己的mysql数据库的情况修改
    config = {}
    
    config.redisConfig = {
        redis_a = { -- your connection name 
    	        --ip
    	        host = '127.0.0.1',
    	        --端口
    	        port = 6379,
    	        --密码
    	        pass = '123456789',
    	        --超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200
    	        timeout = 120000,
    	        --redis的库
    	        database = 0,
    	    },
    --    redis_b = {
    --    --        host = '127.0.0.1',
    --    --        port = 6379,
    --    --       pass = '',
    --    --        timeout = 200,
    --    --        database = 0,
    --    --    },
        }
    
    config.db = {
    	prod = {
    		HOST = "127.0.0.1",
    		PORT = 3306,
    		USER = "test",
    		PASSWORD = "123456789",
    		DATABASE = "test",
    	}
    }
    return config
    

测试

  • 创建本地测试用户表,准备测试数据

  • 编写测试Lua脚本
    前端传递用户的ID,Lua查询出对应的用户信息返回
    在testcode文件下创建mysqltest.lua并拷贝一下至该文件

    --平台公共的配置文件常量
    local config = require "testcode.config_constant"
    
    --mysql连接池
    local mysqlUtil = require "mycode.mysql_factory"
    
    --用于接收前端数据的对象
    local args=nil
    --获取前端的请求方式 并获取传递的参数   
    local request_method = ngx.var.request_method
    --判断是get请求还是post请求并分别拿出相应的数据
    if"GET" == request_method then
            args = ngx.req.get_uri_args()
    elseif "POST" == request_method then
            ngx.req.read_body()
            args = ngx.req.get_post_args()
            --兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug
            if (args == nil or args.data == null) then
                    args = ngx.req.get_uri_args()
            end
    end
    
    --前端传递的id
    local id = args.id
    
    --组装sql语句
    local sql = "select * from test_table where id = "..id
    
    --执行sql语句
    local ret, res, sqlstate = mysqlUtil:query(sql, config.db);
    --判断查询结果
    if(ret and res ~=nil and #res>0) then
        --取出最新的值
        local user = res[1]
        --组装响应参数
        local reVa = "id:"..user.id..";</br>name:"..user.name..";</br>age:"..user.age
        --响应前端
        ngx.say(reVa)
    else
      ngx.say("未找到用户")
    end
    
  • 配置OpenResty下Nginx的Lua文件关联
    在nginx.con中的80配置下添加如下配置

    		location /mysql
    		{
    			default_type text/html;
    			#这里的lua文件的路径为绝对路径,请根据自己安装的实际路径填写
    			#记得斜杠是/这个,从window中拷贝出来的是\这样,这样是有问题的,务必注意
    			content_by_lua_file F:/DATA/software/other/openresty-1.13.6.2-win32/lualib/testcode/mysqltest.lua;
    		}
    

  • 重启OpenResty的Nginx
    nginx -s reload

  • 测试
    浏览器请求:http://127.0.0.1/mysql?id=1 出现以下结果,则正常测试成功



到此,Lua操作mysql完成!!!

猜你喜欢

转载自blog.csdn.net/lupengfei1009/article/details/86169560