直接调用跟通过spring cloud rpc调用用,哪个执行效率高?

51CTO旗下网站
聊聊Python用rpc实现分布式系统调用的那些事
对于rpc的应用,更加的倾向于基本资源的获取和调用,毕竟单纯的用socket或者是mq,你在程序里面还要做一个解析过来的数据,然后根据过来的数据在做调用。
作者:rfyiamcool来源:51CTO| 10:42
通俗的讲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/4000 )最少要比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 &&& &&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&)))& &&&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&)& &&& &&server.serve()&
&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,也推荐大家用这个,靠谱的。
博文地址:
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条头条热点头条
24H热文一周话题本月最赞
讲师:305226人学习过
讲师:153419人学习过
讲师:14893人学习过
精选博文论坛热帖下载排行
《精通ASP+XML+CSS网络开发混合编程》介绍当前网络开发的主流平台与技术之一的ASP+CSS+XML的知识与应用,全书各知识点均配以实例,按照基础...
订阅51CTO邮刊你的分布式应用真的需要那么多同步调用么?
在5月17日举办的2016云栖大会·武汉峰会上阿里中间件产品专家马雷(阿仁)就阿里中间件MQ做了精彩的演讲,告诉大家:阿里中间件团队的目标是让消息“传”无边界。本文也就为什么使用消息中间件,消息中间件的核心场景进行了分享。相信阿仁的分享会让大家对分布式应用的异步调用有更加深刻的了解。精彩不要错过!
对整个分布式应用系统而言,一共分为两种调用,一种是同步调用,一种是异步调用。同步调用就是基于RPC,基于链路监控等等的一套东西,而今天分享的主题是则基于异步调用的。
大家仔细思考一下,我们所做的整个分布式系统中有多少链路是同步调用的,又有多少链路又应该是异步调用的呢?比如在一个下单流程中,有多少核心链路是使用同步调用的,有多少需要异步调用?
消息中间件的使命是让消息传递无边界,传递无边界有两个概念,第一个就是你可以把包括应用之间的通信等各种字节流这样的消息传到各个端,包括手机端,物联网,智能电灯,汽车以及云上应用服务等。第二个就是消息可以传递任何东西,从最小的几个字节到最大的几百兆的文件。
一、为什么使用消息中间件
1.云是地基
先问一个问题:为什么要使用消息中间件?现在开发分布式应用系统,很少有人从头开始写代码,因为现在已经不是一个人憋在酒店里写一个软件就可以成功的年代了,现在往往需要团队作战,而且还有可能从更大的角度来讲,是一个生态在作战,并且你所在的生态有可能和其他的生态存在竞争的关系。那什么是中间件呢?
用现实生活类比来讲,现在房价卖的很高,以前卖房子该怎么去卖?开发商需要先买块地基,然后在地基上搭建个框架,最终将其装修完了以后卖给客户。现在卖房子怎么卖呢?可以直接用现成的框架,无论最终客户想要装修成写字间也好,别墅也好,公寓也好,都可以快速地卖给客户,快速实现资金回笼。所以这里有一个理念是:云实际上就是一个地基,用户不需要去搞自己的IDC。
2、中间件是框架
而中间件相当于框架,有了云的地基,有了中间件的框架,就可以在上面快速地搭建业务,实现将业务的快速变现,这才是业务的基石。中间件是应用快速落地的加速器,它可以让团队拥有快速试错的技术能力。
二、消息场景核心问题-解耦
在整个的分布式应用中,需要将应用拆分成很多个WAR包,那么有多少链路需要同步调用,多少能使用异步调用?以经验来说约70%~80%的链路都可以使用异步调用。阿里消息中间件的延迟是在1ms~5ms之间的这样的一个粒度,实际上类似于准实时的概念,甚至在秒杀的某类场景当中减库存也可以是异步的,通知以及实时监控这些链路全部都可以异步实现。设想如果全部都使用同步调用进行设计,现在淘宝的一个下单流程需要几百个调用,如果全是同步的话,实现这样的下单需要大概几十s量级的时间,那么淘宝为什么能做到下单之后立即就能成交,其实是因为其后面全部链路都使用的是异步调用,并且只有在核心链路中某些最核心的交易环节中的几个环节才会使用同步调用。
在这里分享一个可能给大家一些启示的泰国电影,这个电影一共有三个主人公,父亲,女儿和女儿的男朋友,当时女儿不顾家族和父亲的反对一定要和男朋友交往,父亲实在是拗不过女儿就同意了,但是这个父亲却采取了一个非常残酷的措施,把女儿和她的男朋友用手铐拴在一起,于是每天无论吃饭还是睡觉,每天任何行动女儿和男朋友都在一起。最后的结果相信大家都猜到了,开始非常快乐,最后女孩的男朋友疯了,在疯之前将女孩杀死了,而父亲也因为这个事情从此一蹶不振。这是一个真正的悲剧,人生是这样,如果两个事物太过于耦合在一起的话就将是个悲剧。
设计程序架构也类似,如果你将所有程序都紧耦合的设计在一起,对于这样高度耦合的架构,相信在不久的未来随着业务的发展,你所设计的系统也会成为一个悲剧。真正的场景是在分布式应用中,比如说应用中A和B两个功能模块,既希望他们解耦开,但是又希望他们互联达到目标状态。我们不希望B不可用时候,A也不可用,这是目标。那么为了这个目标能采取什么策略呢?
第一步,需要增加很多A和B的实例,但是这样带来的问题是链路也会增加,调用也会增加。因为A的配置或者B的配置要更改,那么第二步就需要在A和B中间加一个负载均衡器,这是最传统的做法,你增加多少,我就增加多少,大家互不关心对方的配置。
第三点,当有一天做大促销的时候,或者当你的客户大量增多的时候,大量的流量到来,A的流量需要直接传导到B。所以阿里在整个消息领域引出了一个非常重要的概念,叫做Topic或者Queue(队列)。Topic其实也是基于队列的,这个东西的作用是:第一负载均衡,第二点它可以充当一个大的缓冲,这样可以把所有的流量缓存到Topic里面。
举个例子说明Topic的概念:这张图有三部分,生产者,Topic和消费者。生产者生产的消息放到对应的Topic里面,谁取了这个消息或者谁订阅了这个消息就把消息拿走。实际上Topic的概念就像是变压器,变压器是220V的出来的也是这个流量,接入其他的也是这个流量。这给最终设计系统带来一个好处就是首先对于后面的这些应用而言,它们不会因为前面像洪水一样的流量而被压垮。第二个更为重要的就是在设计整个系统的时候就不会有更多的成本浪费在这些旁枝末节的服务上。
再举个例子,做秒杀业务时下单应用非常重要,对这个应用扩展了100台机器,下面的通知比如发邮件的应用,需不需要也扩展100台机器呢?其实是不需要的,虽然还是需要发邮件,但是可以保证邮件以平稳的流量发送,只需要扩展5台或者10台来满足基本需求就可以。这是两个最大的好处,中间的这个Topic,也就是消息中间件就像一个万能的变压器一样,即便大洪流来了经过它也变成比较顺畅的流量。
接下来举几个现实中的例子探讨一下到底哪些链路需要异步。流程推进:就是做工作流或者审批流,再有就是订单的流转,下订单,减库存,使用优惠券结算,最终通知用户或者订单超时等等。这是第一点,流程推进是之前用的最多的。定时消息:消息中间件MQ支持一个定时或者延时的消息,在电商里面主要有两种应用场景,一个是客户下单30分钟之后,订单可能会判定为超时,所以在客户下单之后需要异步发一条消息;并且在30分钟之后,如果订单还没有支付,就被判定为超时并将其关掉。另外一个就是支付提醒,用户下单之后10分钟还没有支付,那么会对其发送一个支付的提醒。这样带来的最大好处就是也可以自己写轮询条件或定时程序,首先对订单或这张表或者其他的多个表进行轮询,但是这些东西其实不需要去做,只需要发一个定时的消息就可以了,触发条件就会发送那个消息。日志监控:如果系统足够大并且对实时性要求比较高,日志全部要异步地放到实时计算的引擎里面。社交互动:现在Facebook用MQTT协议做社交,对于其他类似微信的社交以及现在比较火的视频直播聊天室,点赞送花买礼物等这种对于消息来说的巨大挑战:首先要求实时性,比如在聊天室直播的过程中送花的等待时间不能过长;其次是并发,芒果TV在超女100强比赛的时候也是用了视频直播,包括熊猫TV在选熊猫女郎的时候也是,当聊天室里突然冲进去几百万人的时候,订阅的关系就变得非常复杂,就是说我和你是好友,我发的东西,你应该能看见,但是我跟她不是好友,没有订阅关系,我又和某一个兴趣组有订阅关系,这样就形成了多级的订阅关系,这时候再发消息谁可见谁不可见就取决于订阅关系是什么样的。如果我发的消息之后,一百万人要同时都能接受到这个消息,这是对消息领域一个非常大的挑战。
三、什么是阿里云MQ
阿里云是如何解决这个问题的MQ这个产品已经有7年的历史,并且MQ是经过双十一几千亿条消息流量检验的。第二个就是这个产品在开源社区进行了部分的开源,因为第二阶段需要扩展影响力,所以就将产品一部分进行开源,而开源版本的MQ也有很多电商在用。这就是MQ产品的历史。
从商用的结果来看,阿里的消息队列MQ应该是全球性价比最高的,因为它的计费很简单,就只有API和Topic调用这两块费用。客户建一个Topic就有一个资源占用费,而且计费是阶梯的,其他的消息产品包括亚马逊,微软以,由于收的消息有多种造成很难计算费用,比如要通过调用次数收费,网络流量也需要收费,出口的费用,存储的费用甚至积压的费用都会收取,而阿里云的MQ只收取API的调用费用和Topic的资源占用费用,所以很清楚。
下图是MQ的入口,整个产品都是在这个叫做阿里云互联网中间件里面。互联网中间件包括了企业级分布式应用服务EDAS,消息队列MQ和分布式关系型数据库服务DRDS。我们的团队是服务于整个阿里巴巴集团的,阿里系中大多数应用 都在用我们的中间件。
再一张图是主要控制台界面,在这里可以进行Topic管理,发布管理以及订阅管理。查询方面可以进行Topic查询,Message Key查询和按照Message ID查询,并且还有后面的报表,从这里能获得比如10分钟内TPS是多少,生产了多少消息,失败了多少这样的数据。还有监控报警,整个消息领域内有两个数据最为关键,一个是RT的时间,也就是发送消息的延迟,我们能将其控制在1ms~5ms,这个数据是非常准实时的;第二个是堆积,当大流量到来时会堆积很多消息,堆积对很多消息是很重要的,有的消息中间件堆积了一亿条消息,再将其重新拉取的时候将会使性能下降非常多。如果订单的业务堆积了1000条就需要报警了,需要看看应用是不是已经报错了,所以监控是一个非常重要的功能。
阿里云消息中间件的特点:
双11验证:MQ是经过了双十一验证的,MQ不是阿里看到了未来云计算领域消息是很重要的部分而去开发的,这个完全是阿里的业务需求加上七八年的技术沉淀下来的结果。
体系完善:阿里云MQ的体系比较完善,首先我们在内部产品名叫做MetaQ和Notify,同时有一部分是开源的,叫做RocketMQ,企业今天可以去IOE,未来真的强大到可以专门研究中间件,可以转移到开源的产品上去,这里没有技术绑定的风险。
高可靠和高性能:MQ对消息是多份存储的,可靠性非常高。并且是高性能的,对于单机TPS,在此领域很多人说Kafka性能很高,但是实际上阿里云MQ比Kafka的性能还要高,现在单机性能已经达到10万TPS以上,也就是一秒钟发十万条以上信息,并且这仅是对于单机不是集群。
多协议:MQ还支持多协议,不仅支持TCP还支持HTTP以及MQTT,另外MQ还可以像以前的传统软件一样独立部署,如果想不在云上使用,而在自己的IDC环境中使用MQ也可行。
TCP VS HTTP VS MQTT:专业 VS 简单 VS 物联
在整个消息领域里面,大概有这三个协议,对于支持TCP协议的消息,TCP的协议定义长连接是最稳定的,玩法也是最多的。在TCP上可以做到“推拉结合”的方式,在消息里面也有两种基本传递的方式,一种是“拉”一种是“推”,淘宝之前使用“推”的方式,这样比较快,但是大家后来发现这种方式就像是喂金鱼,如果下游消费能力不好很容易被撑宕机,所以后来改为了“拉”的方式,并且将其做成类似“推”的方式,这时候“拉”的方式已经和“推”的方式效率上差不多了。“拉”的方式最大优点就是下游消费端可以按照自己消费能力控制消费进度,即使下游处理能力没有那么强,消息依然会按部就班处理,但是绝不会崩溃。“推”的方式则是全部推给下游,很容易造成崩溃。
在物联网和移动端就完全不一样了,因为终端不同,它的消息很小,所以采用真正“推”的方式,其次这样的消息不会存很长时间,很多消息会被丢弃,很多场景应用“推”的方式。
HTTP相比TCP要慢很多,但是HTTP有好处,很多小众语言包括GOLang,Python和PHP等都支持,大家对HTTP的接受程度很高,所以也会提供HTTP接入。
另外在整个消息领域有很多商业的也有很多开源的,有很多成熟的也有很多不成熟的,甚至几个人用数月时间也能写出一个消息中间件,但是这个就像学日语一样,入门很简单但是要想真正把消息中间件做到透没那么简单,需要研究CPU,磁盘等等很深的东西。
MQ VS Kafka VS ActiveMQ
对比一下,MQ与之前提到的 Kafka,Kafka 基于日志的场景,但是如果需要传输订单的消息,比如金融报文,甚至对汽车遥控的消息,如要使用 Kafka 有效性就会低一些。另外一个就是ActiveMQ,如果用ActiveMQ就会很简单,但流量出现洪峰的时候,性能就会下降非常多。另外MQ在支持事务方面是其他消息中间件所不具备的。MQ提供事务消息,应用与应用之间有服务的分布式事务,数据库之间也有多个分布式事务,比如同时查50个库,这种叫分布式数据库的事务。在消息领域也有分布式消息,也叫作事务消息。就是在做本地事务和提交消息之间,把这两阶段联动成一个事务,之前如果自己写的话,需要判断它的提交状态,所有事物的回滚都需要自己做。MQ使用事务消息能保证操作的原子性,要么全成功,要么全失败。
Kafka存储局限性 :
MQ和Kafka 18项差异对比 :
另外在阿里云上面有两个消息服务,MQ消息队列和MNS消息服务,MQ是阿里云专业的消息中间件,是阿里双11使用的消息中间件,支持TCP、HTTP、MQTT三种协议。产品首页:
应用场景解析:物联网通用消息协议MQTT
消息队列Message Queue可应用在多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。
而基于物联网的应用是天然的基于消息的分布式应用。消息是构建物联网应用的基础,每个传感器将成为系统中的节点,节点之间依靠消息异步通信。
物联网消息解决方案=MQ+MQTT
物联网消息解决方案的大致过程是这样的,物联网消息从终端上传到云上来,首先经过云盾安全监测和SLB负载均衡,再到MQTT的网关进而进入核心服务,最终短信以及E-mail网关将这些数据发出去。
其中最重要的一点就是链路监控的功能。MQ消息中间件使用了鹰眼监控,可以监控消息从哪一台机器发出来,其RT时间为多少秒,发到哪个Topic,之后被那个订阅组消费了,之后订阅组下面有挂载了多少台机器,哪一台机器接入成功了,哪一台接入失败了,实现真正地监控消息轨迹,而不是让用户去查看日志。
最后想说一点关于创业方面的,创业公司最重要的是试错的能力和商业模式的验证,使用中间件,使用异步解耦的消息可以让创业团队,拥有快速试错、快速创新的技术能力,可以让技术团队专注业务应用开发,从而实现整个团队的业务快速发展。文章作者:马雷 (花名:阿仁)
编辑:贾子甲 (漫步~云端) 、 Sheeta
版权声明:本文内容由互联网用户自发贡献,版权归作者所有,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
用云栖社区APP,舒服~
【云栖快讯】中办国办印发《推进互联网协议第六版(IPv6)规模部署行动计划》加快推进基于 IPv6 的下一代互联网规模部署,计划指出2025年末中国 IPv6 规模要达到世界第一,阿里云也第一时间宣布了将全面提供IPv6服务,那么在全面部署 IPV6 前,你需要了解都在这儿&&
有个问题:异步化之后怎么确保操作成功?如果失败了如何处理?例如我有一条指令消息(给用户发邮件)推送到MQ中,结果不知道为啥消息不见了还是消费失败了之类的,没有成功给用户发到邮件,这类问题一般怎么处理?
@戈风 消息到处流转,而且可能一份变多份,排查起来的确不方便,所以MQ有类似消息轨迹功能。一条消息可以从发送到TOPIC到订阅组到最终消费机器的整个链路进行查看。里面描述具体发邮件的CASE,如果消息已经发到邮件应用程序中,那么需要再具体排查邮件处理程序。
要拆分为异步,最大的阻碍,要有一堆持久进程来实时消费各种消息。这对很多小公司来说,是一个最大的问题。可能MQ不是为小公司准备的,大公司也存在自己的问题,使用MQ需要重构整个业务架构。所以,还需要时间。
充分利用阿里云现有资源管理和服务体系,引入中间件成熟的整套分布式计算框架,以应用为中心,帮助企业级客户轻松构建并...
基于云安全大数据能力实现,通过防御SQL注入、XSS跨站脚本、常见Web服务器插件漏洞、木马上传、非授权核心资源...
一种稳定、可靠、容量和服务能力可弹性伸缩的分布式关系型数据库服务。
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
订阅广场全新上线
Loading...REST RPC:简单、易用、高性能的开源RPC框架
Motivation
目前传统的C++ RPC框架一般都是基于protobuf或者是thrift,都需要用专门的代码生成器来生成代码,这种方式存在以下这些问题:
使用麻烦。使用时需要先写一个DSL描述文件,然后用代码生成器来生成代码,如果model类很多的时候,工作就很繁琐,工作量也比较大。维护性差。当某些model类需要修改时,必须重新定义和编译,做一些繁琐而重复的工作。学习成本高。使用它们之前先要学习代码生成器如何使用,还要学习复杂的DSL语法定义规则,而这些语法规则并不是通用的,一段时间不用之后又要重新去学习。不能快速响应增加新API的需求。当多语言的客户端较多时,服务端增加新接口时,客户端升级比较繁琐。
面对这些问题,rest_rpc就应运而生了,她就是来解决这些问题的,rest_rpc的主要特性:
简单、好用、灵活让用户只关注于业务,业务之外的事由框架负责不需要学习和编写DSL不需要使用代码生成器能快速响应API升级的需求彻底消除了繁琐重复的model定义工作modern(C++14)跨平台
Getting started
从GitHub上下载rest_rpc
git clone https://github.com/topcpporg/rest_rpc.git
下载依赖的库Kapok和spdlog
git submodule update –init
下载boost库,需要boost1.55以上版本编译
需要支持C++14的编译器,gcc4.9以上,vs2015以上
linux下直接使用cmake编译CMakelists.txt
win下直接使用vs2015打开restrpc.vcxproj
服务端代码
rpc server提供两个服务,一个是add服务,实现一个简单的加法;一个是translate服务,实现将字符串从小写转换为大写。
#include &string& #include "server.hpp" int add(int a, int b) { return a + } struct messager { std::string translate(const std::string& orignal) { std::string temp = for (auto & c : temp) c = toupper(c); } }; int main() { server s(9000, std::thread::hardware_concurrency()); s.register_handler("add", &add); s.register_handler("translate", &messager::translate, &m); s.run(); return 0; }
rpc server需要做的事情很简单,它只需要定义rpc服务接口即可,这也是rest rpc的设计理念,让用户只专注于业务。业务接口几乎不受限制,可以是普通函数,也可以是函数对象或者成员函数,函数的参数可以是基本类型也可以是结构体,灵活好用。需要注意的是函数参数不能是指针类型。
客户端代码
rpc client连接到服务器之后,直接调用通用接口既可以完成rpc调用,调用方式接近本地调用。
#include "client_proxy.hpp" int main() { try { boost::asio::io_service io_ client_proxy client(io_service); client.connect("127.0.0.1", "9000"); std::string result = client.call("translate", "test"); //{"code":0,"result":"TEST"} io_service.run(); } catch (const std::exception& e) { std::cerr && "Exception: " && e.what() && std:: } return 0; }
client调用同步接口返回的字符串是标准的json格式,对应的结构体是一个泛型结构体。
template&typename T& struct response_msg { T //json格式字符串,基本类型或者是结构体. };
你可以将标准的json字符串反序列化为对应的对象。比如这个例子中我们调用translate RPC服务,返回的结果是一个字符串,我们可以通过Kapok很方便地反序列化。
DeS dr.Parse(result); response_msg&std::string& response = {}; dr.Deserialize(response); std::cout&&respnse.result&&std:: //will output upper word.
客户端的通用接口call还提供了异步接口,同步还是异步由用户自己选择,更多的示例可以参考GitHub上的代码。
rest rpc目前定义了2种异常类型,参数异常和业务逻辑异常,下面是rpc调用的结果码。
enum result_code { OK = 0, FAIL = 1, EXCEPTION = 2, ARGUMENT_EXCEPTION = 3 };
服务端的异常处理
服务端如果在调用RPC过程中发生了异常,服务器会将异常信息包装为response_msg,序列化为json字符串回发到客户端。
客户端的异常处理
客户端收到RCP调用返回的字符串结果后需要根据结果码判断本次调用是否是正常的,或者是有异常的。下面的例子展示了如何处理可能产生的异常。
template&typename T& void handle_result(const char* result) { DeS dr.Parse(result); Document& doc = dr.GetDocument(); if (doc[CODE].GetInt() == result_code::OK) { response_msg&T& response = {}; dr.Deserialize(response); std::cout && response.result && std:: } else { //maybe exception, output the exception message. std::cout && doc[RESULT].GetString() && std:: } }
使用rest rpc需要注意的一些问题:
服务端的rpc服务函数参数中不要出现指针,其他的任意参数都可以服务端的rpc服务函数参数如果有结构体,结构体必须定义一个META宏,像这样:
template&typename T& struct response_msg { T META(code, result); };
这个宏是序列化需要用到的,具体用法可以参考Kapok
如果需要传送二进制数据的话,需要先做一个转换,将二进制流转换为或者16进制,框架已经提供了这两种方式的codec.
目前单次传送buf的最大长度为8192,如果超出这个长度,服务器会认为长度非法。如果你希望单次传送的缓冲区更大,自行修改常量即可。最重要的问题是记住: 就像调用本地函数一样调用RPC接口,除了业务逻辑之外你真的不需要关注其他!
Dependencies
网络通信依赖了boost.asiojson序列化/反序列化依赖了Kapok日志依赖了spdlog依赖了C++14
为什么已经有这么多RPC库了,还要重新开发一个RPC库?
是的,C++的RPC库确实是有不少了,几乎都是基于thrift或是protobuf开发的,这些库都存在一个问题,我需要学习DSL和IDL工具的使用,重复而繁琐。我希望有一个非常简单易用的RPC,除了业务逻辑,其他的都不让我操心,这就是我重新开发一个RPC库的动机。希望大家用用rest rpc,感受一下她的魅力,如果觉得好用的话请不要吝惜给star。
这个RPC库的性能如何?
rest rpc底层是用的asio,性能比较好,所以rest rpc的性能也是出色的,4核8线程32G内存的工作站上测试,在cpu占用42%时,qps达到14w+。
rest rpc的学习成本高吗?
学习成本很低,因为我们是以用户使用的便利性作为首要的设计理念,让用户仅仅需要关注业务逻辑。
即使是库本身的核心代码也是非常之少,不过一千多行,非常轻量级。
rest rpc已经用于生产环境了吗?
目前还没有,还处于预览版阶段,欢迎大家试用,如果发现问题了请及时向我们的C++社区(purecpp.org)反馈, 或者在github上提issue.我们会很快在生产环境中使用rest rpc了,使用稳定之后会发布正式版,请大家持续关注。也欢迎喜欢rest rpc的开发者能加入进来贡献有深度的代码,逐渐完善rest rpc的功能。
rest rpc支持分布式吗?
目前还不支持分布式,不过这已经在我们的计划中了,很快就可以实现分布式了。
Contributer
江南(qicosmos),网事如风(avdbg),IndignantAngel,shines77
本文为《深入应用C++11》作者、C++开源社区purecpp.org创始人祁宇的投稿。
审校/责任编辑:唐小引,欢迎技术投稿、约稿、给文章纠错,请发送邮件至。
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点}

我要回帖

更多关于 spring cloud rpc调用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信