Python用rpc实现分布式系统调用的原理及实例

rpc概念?

rpc 一般俗称,远程过程调用,把本地的函数,放到远端去调用。

通常我们调用一个方法,譬如: sumadd(10, 20),sumadd方法的具体实现要么是用户自己定义,要么存在于该语言的库函数中,也就说在sumadd方法的代码实现在本地,它是一个本地调用!

“远程调用”意思就是:被调用方法的具体实现不在程序运行本地,而是在别的某个地方(分布到各个服务器),但是用起来像是在本地。

rpc远程调用原理 :

比如 A调用B提供的remoteAdd方法:

首先A与B之间建立一个TCP连接;

然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;

B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;

A接受远程调用结果,然后do()。

RPC框架也就是把上线说的具体的细节封装起来,给用户好用的API使用(提示:有些远程调用选择比较底层的socket协议,有些远程调用选择比较上层的HTTP协议);

一般rpc配合http协议的多点,也就是走http的多。 当然还是看应用,我曾经一共的rpc框架是基于zeromq的zerorpc。速度是挺快,server和client都有python的gevent支持,速度没道理慢。(有兴趣的,可以看看有关zerorpc的文章 http://rfyiamcool.blog.51cto.com/1030776/1254000 )最少要比python本身的xml-rpc要快。 rpc over http(基于http的rpc)有两种协议,一种是xml-rpc ,还有一个是 json-rpc。

XML-RPC:XML Remote Procedure Call,即XML远程方法调用,利用http+xml封装进行RPC调用。基于http协议传输、XML作为信息编码格式。一个xml-rpc消息就是一个请求体为xml的http-post请求,服务端执行后也以xml格式编码返回。这个标准面前已经演变为下面的SOAP协议。可以理解SOAP是XML-RPC的高级版本。

JSON-RPC:JSON Remote Procedure Call,即JSON远程方法调用 。类似于XML-RPC,不同之处是使用JSON作为信息交换格式

下面是一个例子,很简单。我们是用python的rpc库SimpleXMLRPCServer 做的测试,创建rpc server,然后注册一些函数,供应别的客户端去调用。

 代码如下 复制代码
from SimpleXMLRPCServer import SimpleXMLRPCServer

原文:xiaorui.cc

def add(x,y):
    return x+y
 
def subtract(x, y):
    return x-y
 
def multiply(x, y):
    return x*y
 
def divide(x, y):
    return x/y
 
# A simple server with simple arithmetic functions
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_multicall_functions()
server.register_function(add, 'add')
server.register_function(subtract, 'subtract')
server.register_function(multiply, 'multiply')
server.register_function(divide, 'divide')
server.serve_forever()

 

 代码如下 复制代码
import xmlrpclib
 
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
multicall = xmlrpclib.MultiCall(proxy)
multicall.add(7,3)
multicall.subtract(7,3)
multicall.multiply(7,3)
multicall.divide(7,3)
result = multicall()
 
print "7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)

rpc本来是单任务的,如果任务相对频繁,可以设置成多线程的默认,你不用在调用threading模块什么的,直接引用 。

 代码如下 复制代码
class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass

然后rpc初始化的方法换成。

 代码如下 复制代码
server = AsyncXMLRPCServer(('', 1111), SimpleXMLRPCRequestHandler)

这里再说下,和xmlrpc相似的jsonrpc,貌似现在用xmlrpc的,要比jsonrpc的多点。  有时候到国外的it论坛看帖子,xmlrpc用的交多点。其实现在较大的公司,一般干脆直接自己实现了rpc框架,像淘宝Dubbo(朋友有搞过,搞了半天,没有对接成接口,说是有难度,不明觉厉!),百度的xxx(忘名字了)。

 代码如下 复制代码
import jsonrpc
server = jsonrpc.Server(jsonrpc.JsonRpc20(), jsonrpc.TransportTcpIp(addr=("127.0.0.1", 31415), logfunc=jsonrpc.log_file("myrpc.log")))
#原文:xiaorui.cc
# 注册一个函数方法
def echo(s):
    return s
 
def search(number=None, last_name=None, first_name=None):
    sql_where = []
    sql_vars  = []
    if number is not None:
        sql_where.append("number=%s")
        sql_vars.append(number)
    if last_name is not None:
        sql_where.append("last_name=%s")
        sql_vars.append(last_name)
    if first_name is not None:
        sql_where.append("first_name=%s")
        sql_vars.append(first_name)
    sql_query = "SELECT id, last_name, first_name, number FROM mytable"
    if sql_where:
        sql_query += " WHERE" + " AND ".join(sql_where)
    cursor = ...
    cursor.execute(sql_query, *sql_vars)
    return cursor.fetchall()
 
server.register_function( echo )
server.register_function( search )
 
# start server
server.serve()

# 创建jsonrpc客户端
import jsonrpc
server = jsonrpc.ServerProxy(jsonrpc.JsonRpc20(), jsonrpc.TransportTcpIp(addr=("127.0.0.1", 31415)))
 
#调用远端的一个函数
result = server.echo("hello world")
 
found = server.search(last_name='Python')

我做过一些个压力的测试,XMLRPCSERVER的开了async之后,每个连接特意堵塞5秒,他的并发在40个左右 。也就是每秒成功40个左右,剩下的还是在堵塞等待中。 其实他的瓶颈不是在于rpc的本身,是承载rpc的那个basehttpserver,太弱爆了。

接收请求,调用方法 !

 现在开源社区这么发达,有不少人都根据rpc的协议,重写了承载rpc的web服务。  比如用flask,tornado,配合uwsgi,你猜咋招了。。。。如果不堵塞连接,那还可以,如果堵塞连接,uwsgi的废材特色就显出来了,以前有文章说过,uwsgi是prework,他会预先启动进程,官方都推荐要根据你的cpu核数或者超线程来开启进程,如果开的太多,你会发现,uwsgi他是驾驭不了那么多进程的。还是看我大tornado,用了@gen.engine之后。轻易飙到500的并发连接。

(以上是我的吃饱又蛋疼测试,没听过谁会重复调用那么多的堵塞方法,自评 sx行为)

不多说了,看flask实现xmlrpc服务端的代码,看了下flask xmlrpc的源码,实现的不难。

 代码如下 复制代码
from flask import Flask
from flaskext.xmlrpc import XMLRPCHandler, Fault
 
app = Flask(__name__)
 
handler = XMLRPCHandler('api')
handler.connect(app, '/api')
 
@handler.register
def woca(name="world"):
    if not name:
        raise Fault("fuck...fuck", "fuck shencan!")
    return "Hello, %s!" % name
原文:xiaorui.cc
app.run()

对于每个连接的超时,有多种的方法,如果你用的是flask,tornado做web server,那就写个装饰器single起来,只是性能不好。 或者是前面挂一个nginx,然后做个client_header_timeout,client_body_timeout,proxy_connect_timeout(你懂的。),如果用的python自带的xml-rpc的话,需要引入socket。

 代码如下 复制代码
import socket
socket.setdefaulttimeout()

再说下rpc安全的问题。

至于安全方面,有兴趣就开个ssl,或者是在程序里面判断下client ip,反正配置都是统一下发的,你重载daemon的时候,也就知道该判断什么ip了。

我个人对于rpc的应用,更加的倾向于基本资源的获取和调用,毕竟单纯的用socket或者是mq,你在程序里面还要做一个解析过来的数据,然后根据过来的数据在做调用。 (alert: 我想触发 add() ,如果是rpc的话,我不用管,只是传过去就行了,到那时mq和socket就需要eval调用函数了),一些复杂的应用还是喜欢用面向资源的rest,也推荐大家用这个,靠谱的。 

时间: 2024-12-25 04:54:27

Python用rpc实现分布式系统调用的原理及实例的相关文章

分布式系统调用链监控

分布式系统调用链监控 应用架构由集中式向分布式演进后,整个调用关系变得复杂. 分布式架构由复杂且较大规模集群构成,各个应用之间相当独立,可能由不同团队.不同语言实现. 系统一个完整的调用过程可能横跨多个服务及数据中心. 复杂的调用导致系统出问题后难以定位问题. 无法准确知道整体系统性能及运行情况. 全链路性能监控 一个请求完整的调用链可能如下图,经过多个系统服务,调用关系复杂. 期间我们会关注各个调用的各项性能指标,比如吞吐量(TPS).响应时间及错误记录等. 吞吐量,根据拓扑可相应计算组件.平

在Python程序中实现分布式进程的教程

  这篇文章主要介绍了在Python程序中实现分布式进程的教程,在多进程编程中十分有用,示例代码基于Python2.x版本,需要的朋友可以参考下 在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上. Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上.一个服务进程可以作为调度者,将任务分布到其他多个进

python爬虫抓取图片的疑问和原理

问题描述 python爬虫抓取图片的疑问和原理 我想问一下 最简单的抓取图片保存下来的原理 如下面这段代码 response=urllib.request.urlopen("http://ww3.sinaimg.cn/mw600/006h1GB2jw1f1hbjv1eiwj30zk0qo44l.jpg") html=response.read() with open("ddd.JPG","wb") as f f.write(html) 这里htm

Linux VFS中write系统调用实现原理【转】

转自:http://blog.chinaunix.net/uid-28362602-id-3425881.html 目录 用户空间的write函数在内核里面的服务例程为sys_write Vfs_write函数实现原理   WORD里面的目录复制过来似乎不能直接用..还是放在这里当主线看吧..   用户空间的write函数在内核里面的服务例程为sys_write root@syslab ~]# grep write /usr/include/asm/unistd_64.h #define __N

Python中的对象,方法,类,实例,函数用法分析_python

本文实例分析了Python中的对象,方法,类,实例,函数用法.分享给大家供大家参考.具体分析如下: Python是一个完全面向对象的语言.不仅实例是对象,类,函数,方法也都是对象. 复制代码 代码如下: class Foo(object):     static_attr = True     def method(self):         pass foo = Foo() 这段代码实际上创造了两个对象,Foo和foo.而Foo同时又是一个类,foo是这个类的实例. 在C++里类型定义是在编

Python实现冒泡,插入,选择排序简单实例_python

本文所述的Python实现冒泡,插入,选择排序简单实例比较适合Python初学者从基础开始学习数据结构和算法,示例简单易懂,具体代码如下: # -*- coding: cp936 -*- #python插入排序 def insertSort(a): for i in range(len(a)-1): #print a,i for j in range(i+1,len(a)): if a[i]>a[j]: temp = a[i] a[i] = a[j] a[j] = temp return a #

python 打印出所有的对象/模块的属性(实例代码)_python

实例如下: import sys def print_all(module_): modulelist = dir(module_) length = len(modulelist) for i in range(0,length,1): print getattr(module_,modulelist[i]) print_all(sys) 以上这篇python 打印出所有的对象/模块的属性(实例代码)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持. 以上是小编为您精心

python操作memcached以及分布式的例子

memcached 是以 LiveJournal 旗下 Danga Interactive 公司的 Brad Fitzpatric 为首开发的一款软件.现在已成为 mixi.Facebook.LiveJournal 等众多服务中提高 Web 应用扩展性的重要因素. 许多 Web 应用都将数据保存到 RDBMS 中,应用服务器从中读取数据并在浏览器中显示.但随着数据量的增大.访问的集中,就会出现 RDBMS 的负担加重.数据库响应恶化.网站显示延迟等重大影响.这时就该 memcached 大显身手

Memcached 分布式缓存实现原理简介_Linux

摘要 在高并发环境下,大量的读.写请求涌向数据库,此时磁盘IO将成为瓶颈,从而导致过高的响应延迟,因此缓存应运而生.无论是单机缓存还是分布式缓存都有其适应场景和优缺点,当今存在的缓存产品也是数不胜数,最常见的有redis和memcached等,既然是分布式,那么他们是怎么实现分布式的呢?本文主要介绍分布式缓存服务mencached的分布式实现原理. 缓存本质 计算机体系缓存 什么是缓存,我们先看看计算机体系结构中的存储体系,根据冯·诺依曼计算机体系结构模型,计算机分为五大部分:运算器.控制器.存