模块越来越多,业务越来越复杂,RPC 就上场了,在 PHP 的世界里,鸟哥的作品一直备受广大网友的青睐。下面一起学习下鸟哥的 PRC 框架 Yar 。

揭开 Yar 神秘面纱

RPC 采用客户端/服务器模式。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
这和我们外网 api 的原理不都一个样么?那么我们一起看看高大上的 Yar 是怎么在玩。

Yar 功能演示

客户端代码,假设该服务设在局域网10.211.55.4

<?phpclass RpcClient {// RPC 服务地址映射表public static $rpcConfig = array("RewardScoreService"    => "http://10.211.55.4/yar/server/RewardScoreService.class.php",);public static function init($server){if (array_key_exists($server, self::$rpcConfig)) {$uri = self::$rpcConfig[$server];return new Yar_Client($uri);}}
}$RewardScoreService = RpcClient::init("RewardScoreService");
var_dump($RewardScoreService->support(1, 2));

服务器端代码

<?phpclass RewardScoreService {/*** $uid 给 $feedId 点赞* @param $feedId  interge* @param $uid  interge* @return void*/public function support($uid,$feedId){return "uid = ".$uid.", feedId = ".$feedId;}
}$yar_server = new Yar_server(new RewardScoreService());
$yar_server->handle();

访问结果如下

uid = 1, feedId = 2

Yar 远程调用的实现原理

实际呢,yar client 是通过__call这个魔术方法来实现远程调用的,在Yar_client类里面并没有任何方法,当我们在调用一个不存在的方式的时候,就会执行__call方法,这个在框架中非常常见。

Yar 协议分析

在 yar 中规定的传输协议如下图所示,请求体为82个字节的yar_header_t和8字节的打包名称和请求实体yar_request_t,在yar_header_t里面用body_len记录8字节的打包名称+请求实体的长度;返回体类似,只是实体内容的结构体稍微不同,在reval里面才是实际最后客户端需要的结果。

整个传输以二进制流的形式传送。

Yar 数据传输的整体流程分析

yar_transport.h中,定义了yar_transport_t结构体,先不考虑并行处理的接口,以socket传输协议为例子学习,代码简化一些如下:

typedef struct _yar_transport_interface {void *data;int  (*open)(struct _yar_transport_interface *self, char *address, uint len, long options, char **msg TSRMLS_DC);int  (*send)(struct _yar_transport_interface *self, struct _yar_request *request, char **msg TSRMLS_DC);struct _yar_response * (*exec)(struct _yar_transport_interface *self, struct _yar_request *request TSRMLS_DC);int  (*setopt)(struct _yar_transport_interface *self, long type, void *value, void *addition TSRMLS_DC);int  (*calldata)(struct _yar_transport_interface *self, yar_call_data_t *calldata TSRMLS_DC);void (*close)(struct _yar_transport_interface *self TSRMLS_DC);
} yar_transport_interface_t;typedef struct _yar_transport {const char *name;struct _yar_transport_interface * (*init)(TSRMLS_D);void (*destroy)(yar_transport_interface_t *self TSRMLS_DC);yar_transport_multi_t *multi;
} yar_transport_t;

然后在transports/socket.c中定义了yar_transport_socket

yar_transport_t yar_transport_socket = {"sock",php_yar_socket_init,php_yar_socket_destroy,
};

整理了整体的执行流程如下图

Yar 数据的打包和解包

鸟哥在yar_packager.c中首先定义了一个结构体,初始化的时候会把各个yar_packager_t注册到**packagers数组中。

struct _yar_packagers_list {unsigned int size;unsigned int num;yar_packager_t **packagers;
} yar_packagers_list;
typedef struct _yar_packager {const char *name;int  (*pack) (struct _yar_packager *self, zval *pzval, smart_str *buf, char **msg TSRMLS_DC);zval * (*unpack) (struct _yar_packager *self, char *content, size_t len, char **msg TSRMLS_DC);
} yar_packager_t;

然后通过传入的nameyar_packager_tname做比较,相同则返回该实例

PHP_YAR_API yar_packager_t * php_yar_packager_get(char *name, int nlen TSRMLS_DC) /* {{{ */ {int i = 0;for (;i<yar_packagers_list.num;i++) {if (strncasecmp(yar_packagers_list.packagers[i]->name, name, nlen) == 0) {return yar_packagers_list.packagers[i];}}return NULL;
} /* }}} */

亲密接触完毕。纸上得来终觉浅,绝知此事要躬行。这篇博客只能是辅助大家在看源码时一起分析,觉得不能抛开源码仅仅看这篇博客。

怎么样才能对这个内容真正的掌握呢,所以我有折腾了一个Java 版本的客户端,这样总算有所收获,这份代码也和我们平常写的业务逻辑还是有些区别,二进制的东西居多,整个过程下来对网络数据的传输有了更深刻的理解和学习哈。

Github 项目地址: https://github.com/zhoumengkang/yar-java-client

我与鸟哥 Yar 的亲密接触相关推荐

  1. 鸟哥:程序员应该不断提升自身的不可替代性

    这篇不是原创文章,是一篇来自开源中国的好文,很不错,对迷茫中的程序员有一定的启发作用,分享给大家! 如果把程序员这个行业当成是"体力导向型"行业,而你的优势在于"能加班& ...

  2. 鸟哥:技术人员如何保持进步

    在任何一个时代,一款优秀的产品背后必定有一只优秀的团队做支撑.有目共睹,链家在过去的一年里成绩斐然.我不禁好奇,这背后是怎样的一只技术团队?恰好去年"鸟哥"惠新宸离开微博加盟链家一 ...

  3. 鸟哥的Linux私房菜(基础篇)- 第十四章、Linux 账号管理与 ACL 权限配置

    第十四章.Linux账号管理与 ACL 权限配置 最近升级日期:2009/09/09 要登陆 Linux 系统一定要有账号与口令才行,否则怎么登陆,您说是吧?不过,不同的使用者应该要拥有不同的权限才行 ...

  4. PHP 鸟哥:我也曾经是“不适合”编程的人

    网名:雪候鸟,大家尊称鸟哥,惠新宸 @Laruence, 是国内最有影响力的 PHP 技术专家,PHP 开发组核心成员,PECL 开发者,Zend 公司外聘顾问.他曾供职于雅虎,百度,现在新浪微博任平 ...

  5. php 鸟哥链家,链家“鸟哥”告诉您技术人员应如何保持进步

    在任何一个时代,一款优秀的产品背后必定有一只优秀的团队做支撑.有目共睹,链家在过去的一年里成绩斐然.这背后是怎样的一只技术团队?恰好去年"鸟哥"惠新宸离开微博加盟链家一度为业界盛事 ...

  6. 鸟哥的Linux私房菜(服务器)- 第二十一章、文件服务器之三: FTP 服务器

    第二十一章.文件服务器之三: FTP 服务器 最近更新日期:2011/08/08 FTP (File Transfer Protocol) 可说是最古老的协议之一了,主要是用来进行档案的传输,尤其是大 ...

  7. 鸟哥的Linux私房菜(服务器)- 第十三章、文件服务器之一:NFS 服务器

    第十三章.文件服务器之一:NFS 服务器 最近更新日期:2011/07/27 NFS为 Network FileSystem 的简称,它的目的就是想让不同的机器.不同的操作系统可以彼此分享个别的档案啦 ...

  8. 鸟哥的Linux私房菜(服务器)- 第六章、 Linux 网络侦错

    第六章. Linux 网络侦错 最近更新日期:2011/07/19 虽然我们在第四章谈完了连上 Internet 的方法,也大略介绍了五个主要的网络检查步骤.不过,网络是很复杂的东西, 鸟哥也是接触了 ...

  9. 鸟哥的Linux私房菜(服务器)- 第五章、 Linux 常用网络指令

    第五章. Linux 常用网络指令 最近更新日期:2011/07/18 Linux 的网络功能相当的强悍,一时之间我们也无法完全的介绍所有的网络指令,这个章节主要的目的在介绍一些常见的网络指令而已. ...

  10. 鸟哥的Linux私房菜(基础篇)- 鸟哥的第一本书的主要内容,以 Mandrake 9.0 为例

    鸟哥的第一本书的主要内容,以 Mandrake 9.0为例 这个部分的内容主要是来自于鸟哥第一版基础篇的内容.不过,因为年代久远,事实上与第一版的内容有点出入-因为这是在第一版与第二版之间在经过编修后 ...

最新文章

  1. 华为再招 201 万年薪天才少年,任正非:养得起!
  2. 网购切莫小看1毛钱 暗藏信用卡诈骗玄机
  3. 二叉树的层序遍历和二叉树的线索化
  4. 配置token_Nginx常用的配置
  5. FPGA基础之逻辑单元(LE or LC)的基本结构
  6. javascript第一天
  7. Linux内核源码目录说明
  8. decorators 参数_Python Decorators(二):Decorator参数
  9. 关于数组表示的二叉结构中,下标乘除法对应关系的理解
  10. Android Studio(五):修改Android Studio项目包名
  11. mysql 防火墙 centos_CentOS 开启防火墙 firewall ,mysql 远程访问
  12. CorelDRAWX4的VBA插件开发(二十)创建进度条来显示程序运行进度
  13. ESP32 SIM800L:发送带有传感器读数的文本消息(SMS警报)
  14. Scala安装教程(windows和linux)
  15. Win7 64位操作系统连接HP 1010打印机完美解决方案
  16. python的环境问题相关
  17. TCP/IP网络编程:计算器服务器端/客户端
  18. 计算机底层:进程与线程。
  19. android版本内存卡,都8GB内存了 为何安卓手机还是这么卡?
  20. 高速电路PCB布局布线参考

热门文章

  1. 科比投篮预测——数据处理与分析
  2. “姓氏文化展”在国图开展 免费对读者开放
  3. 程序员防猝死指南——程序员养生攻略
  4. eclipse建web工程的dynamic web module version 具体是什么意思
  5. signature=d601b7b6eb512df6319aad970c9aaeab,Excise Tax Return Serial Number 97-17 971101 971115
  6. Codeforces 106C Buns - 多重背包 - 二进制拆分
  7. oracle 如何判断当前日期是星期几
  8. Python爬虫(1)
  9. 鸢尾花lris数据集的SVM线性分类
  10. ubuntu下配置smbd服务器,Windows访问Linux目录