rpc框架yar之源码解析-入门和原理介绍
关于rpc的文章,网上的内容很多,但我还是准备写一下,主要是自己的理解吧。算是公众号的第一篇技术类文章吧。
成都创新互联公司是一家专注于成都网站制作、做网站与策划设计,汪清网站建设哪家好?成都创新互联公司做网站,专注于网站建设十年,网设计领域的专业建站公司;建站业务涵盖:汪清等地区。汪清做网站价格咨询:13518219792
上周给团队小伙伴分享了也是下面基础入门的内容,本文主要结合一个简单框架yar的原理和源码来说明详细情况。
RPC的定义
RPC,即 Remote Procedure Call(远程过程调用),调用远程计算机上的服务,就像调用本地服务一样。
RPC可以很好的解耦系统,如WebService就是一种基于Http协议的RPC。
RPC的框架
各种架构都是在一定环境背景下产生的,有跨语言的,java语言的,有php的,有基于http的,有基于http2的。如下:
Thrift, gRPC, rpcx, motan, dubbox
Phprpc, yar, swoole, Hprose
RPC调用
这里以dubbo的架构图为例,dubbo主要分成4个角色:消费者(Consumer),生产者(Provider),监控中心(Monitor),注册中心(Registry)。
Provider: 暴露服务的服务提供方,生产者。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次数和调用时间的监控中心。
调用方法如下:
0. 服务容器启动,加载,运行服务提供者(server端)。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,根据指定的负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
以上是从网上其他帖子上找的调用内容。基本上涵盖了rpc框架的基本思路,monitor和registry不是必须的,如果有其他方式替代, 也可省略或者换成其他可以实现功能的方式,如集中处理日志。下面是我们在实际使用中用到的内容。
业务背景:在DAU过亿的某博,基础数据独立成平台,这样返回的PC,手机,H5其实是基础数据,要想被手机端所用,实际上需要加工然后传到端上展示。而为了统一化管理,网页版和手机app版尽量使用同一套解析。业务需求产生,在一定的历史背景下,产生了rpc的调用模式。条条大路通罗马,问题不止一个解决方案,我们只是采用了一种,即结合http,nginx ,php-fpm等使用yar这个php扩展模块实现这个业务。
严格意义上讲yar不能独立使用的,没有dubbo,motan等那种自己独立成框架体系。有些部分交给使用者自己实现,如日志记录,我们的日志记录实际与yar关系不大。框架数据传输方式还是借助http,结合nginx,php-fpm等内容,基础还是个http的请求。(curl和sockert两种方式,sockert目前我们没有使用)。没有注册发现服务的具体使用,这个完全由lvs给我们解决,服务的可用完全交给了运维。
了解了各个角色,我们来看下核心内容,Yar实现了rpc的基础部分,即数据的译码/解码和传输,我感觉这两部分是这个框架的核心。下面是流程图:
请求过程:
Client需要远程调用的时候,先初始化数据,数据主要包括三个部分header, packager_name,request_body,然后根据配置中的方式从pack_list选择合适的序列化方式(msgpack,json,php)
对request_body进行序列化。 然后进行传输,传输方式 同样是采用工厂方法,从已有的方式中选择Curl/sockert方式进行传输数据,传输数据的过程实际就是发送一个http请求(我们以curl为例)。
服务器端监听端口,底层网络实现都利用现有的nginx, php-fpm。在PHP代码中,实现的地方实例化一个类,然后根据request的内容,解析body,然后去初始化header, 获得packager_name,根据packer_name解析yar_body的内容。
以下是每次request和response的数据情况。以request为例传输的body数据包含三个部分,82byte的头部,packager_name,和经过packager_name序列化的string。当这段数据传到server端,按照固定的结构解析出来即可。
PACK过程是对数据作如下处理的过程。以msgpack为例,对中间部分的数据进行序列化。生成最右边的内容(序列化后的字符串有最右有差别,这里只是拿json举例)。
传输
yar目前有两种传输方式,这个在之前提到过curl和socket方式。因为socket实际没有用过所以这里主要介绍curl。
curl的模块主要以来底层的CURL模块,主要封装了如下方法。其中multi系列主要是解决并行请求的方案。
php_yar_curl_open
这个方法主要是用CURL创建一个连接对象。这里有个复用的机制,当options &
YAR_PROTOCOL_PERSISTENT(0x1) 为true的时候,会去已经使用的连接中找一下,如果存在并且没有在用则复用。
php_yar_curl_send
这个函数主要是把request需要的数据,转成字符串,然后放在请求的postfield里面。
php_yar_curl_exec
将postfield内容,通过http请求发送出去。获得返回的内容。然后按照上述内容解析出结果。
本来还想分享grpc的protobuf和htt2,鉴于粗浅学习阶段,网上的其他博客文章更详细,这里就不写了,等我实际有自己的理解再说啦。
凡事都没有完美,也碰到过yar的不足之处,比如server的handle方法,解析post数据,执行对应的方法返回都在这里了。没有将请求的实际方法暴露,这样在server端统计起来比较困难。曾试图在源码中加个getCallMethod方法去标记这个内容,不过只是自己玩玩,没有实际应用...
有同学问我为啥我们当时要用yar,也许别的框架也能满足我们的需求,一定的历史背景决定一定的技术架构。技术的选型更多倾向于开发者的水平----即选择自己驾驭的技术,站在巨人的肩膀上展望远处。
文章题目:rpc框架yar之源码解析-入门和原理介绍
文章位置:http://azwzsj.com/article/piseho.html