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的高级版本。

注释下,原文地址,blog.xiaorui.cc

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

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

 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
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
 
 
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()

这个是连接的Client,python下的xmlrpclib 本身就提供了server和client类,当然咱们也可以自己写,看源码就知道他只是把func,args做了xml格式化而已。

 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
 
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模块什么的,直接引用 。

 
 
 
 
 

Python

 
1
2
 
class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass
 

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

 
 
 
 
 

Python

 
1
2
 
server = AsyncXMLRPCServer(('', 1111), SimpleXMLRPCRequestHandler)

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

 
 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
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()
 
 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
 
# 创建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,太弱爆了。

 
 
 
 
 
 

Python

 
1
2
 
注释下,原文地址,<a href="http://blog.xiaorui.cc/" target="_blank">blog.xiaorui.cc</a><span style="line-height:1.5;font-family:微软雅黑, 'Microsoft YaHei';font-size:20px;"></span>

接收请求,调用方法 !

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

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

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

 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
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。

 
 
 
 
 

Python

 
1
2
3
 
import socket
socket.setdefaulttimeout()

再说下rpc安全的问题。

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

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

python调用rpc实现分布式系统的更多相关文章

  1. python调用RPC接口

    要调用RPC接口,python提供了一个框架grpc,这是google开源的 rpc相关文档: https://grpc.io/docs/tutorials/basic/python.html 需要安 ...

  2. 《精通并发与Netty》学习笔记(07 - 基于Thrift实现Java与Python的RPC调用)

    上节我们介绍了基于Thrift实现java与java的RPC调用,本节我们基于Thrift实现Java与Python的RPC调用 首先,修改data.thirft文件,将命名空间由java改为py n ...

  3. python调用zabbix接口实现Action配置

    要写这篇博客其实我的内心是纠结的,老实说,我对zabbix的了解实在不多.但新公司的需求不容置疑,当我顶着有两个头大的脑袋懵懵转入运维领域时,面前摆着两百多组.上千台机器等着写入zabbix监控的需求 ...

  4. 【初学python】使用python调用monkey测试

    目前公司主要开发安卓平台的APP,平时测试经常需要使用monkey测试,所以尝试了下用python调用monkey,代码如下: import os apk = {'j': 'com.***.test1 ...

  5. python调用py中rar的路径问题。

    1.python调用py,在py中的os.getcwd()获取的不是py的路径,可以通过os.path.split(os.path.realpath(__file__))[0]来获取py的路径. 2. ...

  6. python调用其他程序或脚本方法(转)

    python运行(调用)其他程序或脚本 在Python中可以方便地使用os模块运行其他的脚本或者程序,这样就可以在脚本中直接使用其他脚本,或者程序提供的功能,而不必再次编写实现该功能的代码.为了更好地 ...

  7. python调用c\c++

    前言 python 这门语言,凭借着其极高的易学易用易读性和丰富的扩展带来的学习友好性和项目友好性,近年来迅速成为了越来越多的人们的首选.然而一旦拿python与传统的编程语言(C/C++)如来比较的 ...

  8. Python调用C++

    /***gcc -o libpycall.so -shared -fPIC pycall.c*/ #include <stdio.h> #include <stdlib.h> ...

  9. 使用Python调用Flickr API抓取图片数据

    Flickr是雅虎旗下的图片分享网站,上面有全世界网友分享的大量精彩图片,被认为是专业的图片网站.其API也很友好,可以实现多种功能.这里我使用了Python调用其API获得了大量的照片数据.需要注意 ...

随机推荐

  1. spring mvc:练习:表单验证(javaConfig配置和注解)

    使用Spring表单标签, 表单验证使用 JSR303 的验证注解,hibernate-validators,提供了使用MessageSource和访问静态资源(如CSS,JavaScript,图片) ...

  2. spring mvc:视图解析器

    ModelAndView对象中的view对象,可以使用字符串来让Spring框架进行解析获得适合的视图.而解析View的就是ViewResolver技术. ViewResolver的定义如下: pub ...

  3. Python实现H5页面

    from selenium import webdriver mobile_emulation = {'deviceName':'iPhone X'} options = webdriver.Chro ...

  4. C语言实现顺序表

    C语言实现顺序表代码 文件SeqList.cpp #pragma warning(disable: 4715) #include"SeqList.h" void ShowSeqLi ...

  5. 严重:Error configuring application listener of class org.springframework.web.util.IntrospectorCleanupListener

    mave项目换了一个新的工作空间时出现的问题 原因: 其实是你的jar文件没有同步发布到自己项目的lib目录中(如果你是用Maven进行构建的话) 可以试试 下面的办法 解决方案: 项目点击右键 点击 ...

  6. LeetCode OJ:Reorder List(重序链表)

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do thi ...

  7. week13《java程序设计》第13次作业总结

    week13<java程序设计>第13次作业总结 1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 答: 1.IP与端口:ip和域名相对应,可找 ...

  8. 201621123006 《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 多态.重载.继承.覆盖.super.抽象类 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. ...

  9. input 取消自动填充

    增加属性:  name="clear" 

  10. 源码编译tmux

    (1)clone 源代码仓库: $ git clone https://github.com/tmux/tmux.git (2) 编译之前先安装libevent,去官网下载tar包: http://l ...