title: python远程过程调用记录

date: 2017-12-29 11:23:53

tags: [xmlrpc,jsonrpc,web2py]

需求

现有的两个web服务器之间需要打通传递数据,A应用采集数据发送给B应用处理,B处理后再存储到自己的数据库。

A服务器->B服务器: 刚刚采集到新鲜热乎的数据一份!

Note right of B服务器: 尝一口,扔冰箱里

B服务器-->A服务器: 不错!是挺新鲜的!

方案

方案一、A服务器采集数据后,按照B的需求进行加工处理,扔进B的数据库中。

方案二、A调用B的处理过程,B处理完后存入数据库。这就是远程过程调用(RPC)。

方案一将A、B之间的联动转化为A与B数据库的联动。此方案增加了系统间的耦合,降低了系统的稳定性,增加了维护成本,也带来了安全隐患。方案二A、B之间保持了独立性,减少了相互干扰,提升了稳定性。所以这里采用方案二来实现。

如何使用rpc调用,有两个方面问题:

一、B服务器作为服务提供方,以何种方式提供服务?

二、A服务器作为调用方,如何调用B所提供的服务?

web2py解决方案

一、服务器解决方案

B服务器采用python的web2py作为web服务器框架,在官网我们找到了RPC相关的文档说明,框架提供了多种RPC协议的支持。XMLRPC、JSONRPC、AMFRPC、SOAP等,权衡一下,选择了xmlrpc在调用时不需要再引入第三方库,使用会更方便。

web2py采用了典型的mvc框架,项目里controls目录下对应了所以页面请求的处理函数。修改对应的control文件并添加下面的代码。例:

default.py。
@service.xmlrpc
#RPC服务测试函数 ,注:每一个提供服务的函数需要加上@service.xmlrpc作为修饰符
def add(a, b):
return a + b
#开启RPC服务接口
def call():
session.forget()
return service()

主要工作分两步,1、添加call函数,开启RPC服务支持。2、为提供RPC服务的函数增加@service.xmlrpc修饰符。

就是这么简单,服务器端的配置就结束了,这里B服务器开启了add服务,将传入的两个参数相加并返回。

二、客户端解决方案

工作很简单,引入xmlrpclib包里的ServerProxy类,传入B服务器的url进行初始化,之后按照对象的方式进行调用。下面是客户端的测试代码。http://127.0.0.1:8000/app/default/call/xmlrpc是B服务器的网络链接地址。

>>> from xmlrpclib import ServerProxy
>>> server = ServerProxy(
'http://127.0.0.1:8000/app/default/call/xmlrpc')
>>> print server.add(3, 4)
7
>>> print server.add('hello','world')
'helloworld'

通用python网络服务解决方案

web2py作为web服务框架,对基于http协议实现的rpc服务具有天然的优势,服务器不需要再开启其他的网络服务。然而其他提供没有采用web2py框架的服务器该如何提供RPC服务呢。

最近的开发工作中,我们也遇到了这样的问题。此时的B服务器不是web服务器。

一、服务器解决方案

考虑到之前采用了xmlrpc实现远程过程调用,具有了一定的经验,功能上也满足了我们的需求,所以采用搭建xmlrpc服务的方式进行。

在B服务器中添加下面的代码,使用多进程的方式,开启xmlrpc服务器,并绑定到服务器的8088端口。

这里也是提供了add函数作为服务,并返回两个参数相加的接口。

def run_xmlrpcserver():
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SocketServer import ThreadingMixIn
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
pass
class MyObject:
def add(self,a,b):
return a+b
obj = MyObject()
server = ThreadXMLRPCServer(("localhost", 8088), allow_none=True)
server.register_instance(obj)
server.serve_forever()
# 开启服务器进程
Process(target=run_xmlrpcserver, args=tuple([ ])).start()

二、客户端解决方案

这里的代码与web2py解决方案中的一致,注意修改下服务的url即可,具体测试代码如下:

>>> server = xmlrpclib.ServerProxy("http://localhost:8088")
>>> words = server.add(1,2)
>>> words
3

总结

最近记性越来越差了,以后要多记录写才好。