在为mysql-proxy编写lua脚步的时候,需要知道一下几个入口函数,通过这几个入口函数我们可以控制mysql-proxy的一些行为。

  • connect_server()          当代理服务器接受到客户端连接请求时(tcp中的握手)会调用该函数
  • read_handshake()        当mysql服务器返回握手相应时会被调用
  • read_auth()             当客户端发送认证信息(username,password,port,database)时会被调用
  • read_auth_result(aut)  当mysql返回认证结果时会被调用
  • read_query(packet)      当客户端提交一个sql语句时会被调用
  • read_query_result(inj) 当mysql返回查询结果时会被调用

1.connect_server使用


function read_handshake( )
local con = proxy.connection print("<-- let's send him some information about us")
print(" server-addr : " .. con.server.dst.name)
print(" client-addr : " .. con.client.src.name)

-- lets deny clients from !127.0.0.1
   if con.client.src.address ~= "127.0.0.1" then
      proxy.response.type = proxy.MYSQLD_PACKET_ERR
      proxy.response.errmsg = "only local connects are allowed"

     print("we don't like this client");

    return proxy.PROXY_SEND_RESULT
   end

end

获取代理的链接对象,这个对象是全局的,可以在函数中直接拿来使用。从连接对象中我们可以拿到客户端名称和服务器名称,通过也能获得客户端的ip地址,上面的代码就是禁止非本机ip登录mysql。

2、read_auth使用


读取用户的认证信息包括用户名、密码、所要连接的数据库。其中的proxy.MYSQLD_PACKET_ERR是mysql-proxy中自带的常量。

function read_auth( )
local con = proxy.connection print("--> there, look, the client is responding to the server auth packet")
print(" username : " .. con.client.username)
print(" password : " .. string.format("%q", con.client.scrambled_password))
print(" default_db : " .. con.client.default_db) if con.client.username == "evil" then
proxy.response.type = proxy.MYSQLD_PACKET_ERR
proxy.response.errmsg = "evil logins are not allowed" return proxy.PROXY_SEND_RESULT
end
end

3.read_auth_result使用


通过该方法我们可以获得mysql数据库的认证结果,认证结果由auth对象持有,我们可以访问其packet属性(字符串类型),可以查看返回结果。字符串的第一个字符是对结果的标识。

function read_auth_result( auth )
local state = auth.packet:byte() //获取第一个字符并将其转为整型 if state == proxy.MYSQLD_PACKET_OK then
print("<-- auth ok");
elseif state == proxy.MYSQLD_PACKET_ERR then
print("<-- auth failed");
else
print("<-- auth ... don't know: " .. string.format("%q", auth.packet));
end
end

4.read_query的使用


packet中就存放着客户请求的SQL语句,类型为字符串类型。起始第一个字符同上,为标识符。这里判断是不是一个查询语句,是的话就从第二个字符开始输出查询语句。

function read_query( packet )
print("--> someone sent us a query")
if packet:byte() == proxy.COM_QUERY then
print(" query: " .. packet:sub()) if packet:sub() == "SELECT 1" then
proxy.queries:append(, packet)
end
end end

5、read_query_result使用


其实我们该函数和read_query函数时是希望对SQL语句进行处理,但是由于时间有限,不能对mysql-proxy提供的sql处理继续研究,这里先就先贴出来。

function read_query_result( inj )
print("<-- ... ok, this only gets called when read_query() told us") proxy.response = {
type = proxy.MYSQLD_PACKET_RAW,
packets = {
"\255" ..
"\255\004" .. -- errno
"#" ..
"12S23" ..
"raw, raw, raw"
}
} return proxy.PROXY_SEND_RESULT
end
--[[ $%BEGINLICENSE%$
Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; version 2 of the
License. This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA $%ENDLICENSE%$ --]] local proto = require("mysql.proto") local prep_stmts = { } function read_query( packet )
local cmd_type = packet:byte()
if cmd_type == proxy.COM_STMT_PREPARE then
proxy.queries:append(, packet, { resultset_is_needed = true } )
return proxy.PROXY_SEND_QUERY
elseif cmd_type == proxy.COM_STMT_EXECUTE then
proxy.queries:append(, packet, { resultset_is_needed = true } )
return proxy.PROXY_SEND_QUERY
elseif cmd_type == proxy.COM_STMT_CLOSE then
proxy.queries:append(, packet, { resultset_is_needed = true } )
return proxy.PROXY_SEND_QUERY
end
end function read_query_result(inj)
if inj.id == then
-- print the query we sent
local stmt_prepare = assert(proto.from_stmt_prepare_packet(inj.query))
print(("> PREPARE: %s"):format(stmt_prepare.stmt_text)) -- and the stmt-id we got for it
if inj.resultset.raw:byte() == then
local stmt_prepare_ok = assert(proto.from_stmt_prepare_ok_packet(inj.resultset.raw))
print(("< PREPARE: stmt-id = %d (resultset-cols = %d, params = %d)"):format(
stmt_prepare_ok.stmt_id,
stmt_prepare_ok.num_columns,
stmt_prepare_ok.num_params)) prep_stmts[stmt_prepare_ok.stmt_id] = {
num_columns = stmt_prepare_ok.num_columns,
num_params = stmt_prepare_ok.num_params,
}
end
elseif inj.id == then
local stmt_id = assert(proto.stmt_id_from_stmt_execute_packet(inj.query))
local stmt_execute = assert(proto.from_stmt_execute_packet(inj.query, prep_stmts[stmt_id].num_params))
print(("> EXECUTE: stmt-id = %d"):format(stmt_execute.stmt_id))
if stmt_execute.new_params_bound then
for ndx, v in ipairs(stmt_execute.params) do
print((" [%d] %s (type = %d)"):format(ndx, tostring(v.value), v.type))
end
end
elseif inj.id == then
local stmt_close = assert(proto.from_stmt_close_packet(inj.query))
print(("> CLOSE: stmt-id = %d"):format(stmt_close.stmt_id)) prep_stmts[stmt_close.stmt_id] = nil -- cleanup
end
end

这里使用了MySQL新的接口stmt,对其不了解可以查看下面的连接。

戳我

Mysql-proxy中的lua脚本编程(一)的更多相关文章

  1. C++中嵌入Lua脚本环境搭建

    第一步(环境准备工作): 工具: ●LuaForWindows_v5.1.4-46.exe傻瓜式安装. 作用:此工具可以在windows环境下编译运行Lua脚本程序.安装完成后会有两个图标:Lua和S ...

  2. 在redis中使用lua脚本

    在实际工作过程中,可以使用lua脚本来解决一些需要保证原子性的问题,而且lua脚本可以缓存在redis服务器上,势必会增加性能. 不过lua也会有很多限制,在使用的时候要注意. 在Redis中执行Lu ...

  3. redis中使用lua脚本

    lua脚本 Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能 使用脚本的好处 1.减少网络开销,在Lua脚 ...

  4. 新姿势!Redis中调用Lua脚本以实现原子性操作

    背景:有一服务提供者Leader,有多个消息订阅者Workers.Leader是一个排队程序,维护了一个用户队列,当某个资源空闲下来并被分配至队列中的用户时,Leader会向订阅者推送消息(消息带有唯 ...

  5. 【COCOS2DX-LUA 脚本开发之一】在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途!

    [COCOS2DX-LUA 脚本开发之一]在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途! 分类: [Cocos2dx Lua 脚本开发 ] 2012-04-1 ...

  6. 怎样在Cocos2d-x中使用Lua脚本

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013321328/article/details/25699545 笔者使用的是Cocos2d-x ...

  7. 服务降级 托底预案 Nginx中使用Lua脚本检测CPU使用率,当达到阀值时开启限流,让用户排队

    https://mp.weixin.qq.com/s/FZAcQQAKomGEe95kln1HCQ 在京东我们是如何做服务降级的 https://mp.weixin.qq.com/s/FZAcQQAK ...

  8. Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性

    Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...

  9. 在redis一致性hash(shard)中使用lua脚本的坑

    redis 2.8之前的版本,为了实现支持巨量数据缓存或者持久化,一般需要通过redis sharding模式来实现redis集群,普遍大家使用的是twitter开源的Twemproxy. twemp ...

随机推荐

  1. zabbix安装排错过程

    在讲安装过程之前需要先把zabbix的工作流程简单的讲一遍:zabbix是个开源监控软件,通过web才能更直观的监控我们想要监控的主机,同时,zabbix从被监控主机获取到的信息需要存放在数据库中,因 ...

  2. MSBI BigData demo—sqoop import

    --sp_readerrorlog 读取错误的信息记录 exec sys.sp_readerrorlog 0, 1, 'listening'查看端口号 首先hadoop环境要配置完毕,并检验可以正常启 ...

  3. pig 介绍与pig版 hello world

    前两天使用pig做ETL,粗浅的看了一下,没有系统地学习,感觉pig还是值得学习的,故又重新看programming pig. 以下是看的第一章的笔记: What is pig? Pig provid ...

  4. VMware + OpenStack: 从 Plugin 到 VIO (VMware Integrated OpenStack)的演进

    VMware 做为实际上的企业虚拟化领导者,对 OpenStack 的态度一直在变化.一开始,VMware 表达出与 OpenStack 的竞争态度.随着 OpenStack 的逐步壮大并且一步一步进 ...

  5. POJ 1990 MooFest --树状数组

    题意:牛的听力为v,两头牛i,j之间交流,需要max(v[i],v[j])*dist(i,j)的音量.求所有两两头牛交谈时音量总和∑(max(v[i],v[j])*abs(x[j]-x[i])) ,x ...

  6. GitHub Top 100的Android开源库

    摘要: 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择「Best M... 本项目主要对目前 GitH ...

  7. Android Studio系列教程三--快捷键

    Android Studio系列教程三--快捷键 2014 年 12 月 09 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang.com/ ...

  8. Gitblit-Git版本服务器环境部署

    Gitblit介绍 Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库.相当于 Git 的 Java 管理工具,支持linux系统. Git是分布式版本控制系统,它强调速度.数 ...

  9. Jython概要

    1.安装jython 1.1 进入http://www.jython.org/downloads.html ,网页上会显示当前最稳定的版本(The most current stable releas ...

  10. Bitbucket免费的私有仓库

    1.官网 https://bitbucket.org/ 2.介绍 知乎:http://www.zhihu.com/question/20053312 建议同时用Bitbucket和Github,理由如 ...