作者:糖果

有时候我们写的服务可能会部署到很同种不同类型的服务器上,有一些数据,可能不便于存在本地,需要一个数据中心,保存这些数据。

我们要求是这样的:

1.客户端服务要周期性的去服务器上拉取数据。(存在SAE MySQL中)。

2.不使用长连接的方式通信,使用基于HTTP的协议。

3.客户端与数据库交互不依赖服务器端采用什么数据库,抽象出一层数据访问层。

基于以上三点:

服务器端:我们将服务器服务架设到SAE的云端,使用SAE支持的Python语言,WEB框架使用的Django,通过RPC协议,为客户端提供服务。服务端的数据存储在SAE的MySQL数据库中,为使服务器端可以对外开发RPC服务接口,使用开源的RPC服务端解决方案RPC4Django。

客户端:这里的客户端其是架设在另一台服务器的Openresty服务,使用Lua语言进行扩展,加入了定时拉取访问数据的流程演示模块,至于如何接定RPC接口,传输什么数据,看具体的实际业务,这里只是通过程序演示这个机制如何在SAE上完成变互的过程。

客户访问端使用持术是用Openresty做服务器,用Lua Lapis框架写成应用。在客户访问端需要做以下几件事情:

1.安装Openresty服务器,按装Lua Lapis框架。

2.使用Lua Lapis创建一个Openresty的项目。

3.配置Openresty,创建一个定时作任务。

这时我们先跳出Lua阶段,进行SAE端Python的RPC服务的,部署和编码,然后回来完成,客户端的剩下的两个动作。

4.用Lua RPC Client访问SAE上的RPC服务。

5.将取得的数据,存储到客户端的Openresty服务器的ShareDiction中,供本地其它业务使用些数据。

下面开始:

第1步:Openresty服务器安装和Lapis框架部署(此处只介绍Lapis的安装),更详细的信息请参考如下文章。

a). 安装luarocks。

sudo apt-get install luarocks

b). 通过luarocks安装lapis框架。

sudo luarocks install lapis

第2步:用Lapis 创建Openresty工程.

lapis new

命令执行后,会生成下面所示的目录结构。

3.在Openresty中创建一个定时任务。

定时器的实现思想如下:

让Openresty去加载一个lua脚本,脚本通过启动一个timer设定,调用一个函数,在被调用的函数内部,循环递归的进行time设定,调用这个被周函数本身,利用这种周期性的调用事件,我们定时递归的函数体中,执行一个函数过程CallRPC()去通过RPC协议访问SAE云上的数据。

RPC接口定义与实现,在下面接下来的Django部分会详细说明,下面就是提到的函数。此函数的主要的目的是6秒钟的时间间隔,通过RPC协议,拉取SAE上Mysql数据库里的数据,至于传输什么数据是和你的业务直接相关的,我们此处就使用一个简单的数据结构来说明问题。

local handler

function handler(premature, params)

     --CallRPC就是Lua通过JSON.RPC访问SAE的RPC服务器。

     CallRPC()

     --递归的timer,重复调用handler函数。

     local ok, err = ngx.timer.at(6, handler, "params-data")

     ngx.log(ngx.DEBUG, "ok:", ok, " err:", err)

end


--第一次设定timer,调用hander函数。

local ok, err = ngx.timer.at(6, handler,"params-data")

ngx.log(ngx.DEBUG, "ok:", ok," err:", err)

--判断第一次调用是否成功,如查不成功,把问题原因打印出来。

if not ok then

       ngx.log(ngx.ERR, "err:", err)

end

创建SAE上的RPC服务:

完成创建工作需要五步:

  1. 创建一个Django工程 。

  2. 安装RPC4Django。

  3. .创建立数据库表。

  4. 实现RPC服务接口。

  5. 启动RPC服务。

我们先暂停Openresty的部分,先介绍如何在SAE构建RPC服务器。

之前已经提过,构SAE上的RPC服务使用的是SAE的PYTHON服务,使用的也是SAE天然支持的Django框架。下面介绍的是创建一个Django工程,SAE天然支持 Django, Tornado, Flask框加。如果需要更多信息,请参考如下文章。

http://www.epubit.com.cn/article/143

服务器端

第一步:创建一个Django工程 。

a). 创建工程。

django-admin.pystartproject testrpc

b). 在工程内创建APP。

pythonmanage.py startapp myrpc

两格指令执行后,系统上建立如下的目录结构。

这表明Djago已经成功能完成创建工程和APP。

第二步:安装RPC4Django。

RPC服务主要靠的就是用RPC4Django来实现,rpc4django是一个开源项目,项目的地址如下:https://github.com/davidfischer/rpc4django

rpc4django也是一个Django的App,使用的话,只要在setting.py配置文件中引用即可。

修改testrpc文件夹中的setting.py文件,如下图:

把rpc4django加入到工程安装的APP的列表里,这样就可以像引用普APP一样使用rpc4django了。

第三步.创建立数据库表。

Django是MVC模式的Python框加,并且支持ORM,只要定一义一个Python的Model类,就可以同步生成数据库表。

我们在myrpc文件夹下的models.py里面加入表定义类,如下图:

创建完Model模块类后,需要同步一下DB,将Django根据类的定义生成对应的DB表格。

pythonmanage.py syncdb

如果之前安装了SAE的本地运行环境的话,可能使用cloudsql.py 直接访问远端的SAE数据库命令行。

执行后同步后,我们查看一下MyRPC数据库表的定义。

上图所示,表生成成功。

第四步.实现RPC服务接口。

因为使用rpc4django,生成一个RPC接口,就变的简单很多。

之前在新建的每一个Django App的时候,对应每个APP文件夹都有一个__init__.py文 ,我们在此文件中声明函数,并且使用rpcmethod装饰器,就会对应产生一个RPC服务接口,可以提供给客户端访问使用。这里我们就创建了一个叫做testrpc.MyRPC的RPC服务接口,返回的数据类型是一个数驵元素。这个数组的取得,就是通过Django的ORM模型,访问了我们之前所定义的MySQL数据表MyRPC。

第五步:启动RPC服务。

经过以上四步,一个最简单的SAE上的RPC服务就架设完了,让我们启到一个这个应用,然后RPC服务才可用。

Python manager.py runserver 127.0.0.1:8080

回到之前的Lua介绍,还剩下的步骤:

1.Lua调用 SAE上的RPC服务接口。

2.将返回的数据写入Openresty的ShareDiction中。

3.使用Lapis模板系统,将返回结果显示到网页上。

(此部分略,可参考此连接内容:http://www.epubit.com.cn/article/158)

第一步:如何使用Lua RPC客户端访问RPC。

Lua访问RPC使用的库是JSON库的RPC机能,原来还是通过HTTP向服务器发送一定格式的

JSON数据,并将服务器返回的数据,从JSON数据专成函数可以直接使用数据。

json=require"json"

require"json.rpc"

function CallRPC()

list, error =json.rpc.call("http://XXX.sinaapp.com/RPC","testrpc.MyRPC")
for _key, _val in pairs(list) do
    print  _val

    print "\n"
end

运行后会把SAE上数据库表里的数据返回,并打印出来,如下图:

第二步:将返回的数据写入Openresty的ShareDiction中。

我们已经通过Lua RPC客户端,访问RPC服务,将数据返回了,我们还需要将读取的数据存储到Openresty的ShareDiction里,提供给Openresty的Lua系统内部其它模块使用。

使用ShareDiction首先要修改.conf配置文件,需要在文件加入如下内容:

http {

  include mime.types;

  lua_shared_dict g_dict 10m;

  ...

创建了一个名字为g_dict的10m的共享字典,我们需要的就是将取后的数据,存入到共享字典中,封闭一个简单的函数来存储返回值。

function set_key(_key,_value)  

  if _key then

    local g_dict = ngx.shared.g_dict    

    g_dict:set(_key, _value)    

  end

end

第三步:使用Lapis模板系统,将返回结果显示到网页上。

(此部分略,可参考此连接内容:http://www.epubit.com.cn/article/158)

接下来,还会介绍,如何利用Django的用户验证系统,进行RPC的限制性访问。

(通过JS调用SAE上的RPC服务。)

如何在SAE上,使用BeautifulSoup在线分析指定网站内容的文章。

作者:糖果

PS:转载到其它平台请注明作者姓名及原文链接,请勿用于商业用途。