PHP 教父鸟哥 Yar 的原理分析
模块越来越多,业务越来越复杂,RPC 就上场了,在 PHP 的世界里,鸟哥的作品一直备受广大网友的青睐。下面一起学习下鸟哥的 PRC 框架 Yar 。
揭开 Yar 神秘面纱
RPC 采用客户端/服务器模式。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。 这和我们外网 api 的原理不都一个样么?那么我们一起神马影院看看高大上的 Yar 是怎么在玩。
Yar 功能演示
客户端代码,假设该服务设在局域网10.211.55.4上
<?php
class 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));
服务器端代码
<?php
class 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, www.10rz.net/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;
然后通过传入的name和yar_packager_t的name做比较,相同则返回该实例
PHP_YAR_API yar_packager_t * php_yar_packager_get(char *name, int nlen TSRMLS_DC) /* {{{ */ {
int i = 0;www.10rz.net
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 版本的客户端,这样总算有所收获,这份代码也和我们平常写的业务逻辑还是有些区别,二进制的东西居多,整个过程下来对网络数据的传输有了更深刻的理解和学习哈。
PHP 教父鸟哥 Yar 的原理分析的更多相关文章
- PHP 鸟哥:我也曾经是“不适合”编程的人
网名:雪候鸟,大家尊称鸟哥,惠新宸 @Laruence, 是国内最有影响力的 PHP 技术专家,PHP 开发组核心成员,PECL 开发者,Zend 公司外聘顾问.他曾供职于雅虎,百度,现在新浪微博任平 ...
- 鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)
什么是 daemon 与服务 (service) Linux Daemon (守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些事件.它不需要用户输入就能运行 ...
- 跟着鸟哥学Linux系列笔记3-第11章BASH学习
跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 跟着鸟哥学Linux系列笔记1 跟着鸟哥学Linux系列笔记2-第10章VIM学习 认识与学习bash 1. ...
- 鸟哥的linux私房菜勘误表
博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://github.com/jiangxincode 知乎地址: https://ww ...
- (转)鸟哥SHELL入门材料
http://blog.chinaunix.net/space.php?uid=9809038&do=blog&cuid=62903 经典入门材料! 学习 Shell Scripts ...
- (整理)ubuntu 的 相关知识(来自 鸟哥的私房菜)
1. Linux 文件权限概念 $ ls 察看文件的指令 $ ls -al 出所有的文件详细的权限与属性 (包含隐藏档,就是文件名第一个字符为『 . 』的文件) 在你第一次以root身份登入Linux ...
- vsftp 详解鸟哥版
FTP (File Transfer Protocol) 可说是最古老的协议之一了,主要是用来进行档案的传输,尤其是大型档案的传输使用 FTP 更是方便!不过,值得注意的是,使用 FTP 来传输时,其 ...
- 鸟哥的 Linux 私房菜Shell Scripts篇(四)
12.4 条件判断式 只要讲到『程式』的话,那么条件判断式,亦即是『 if then 』这种判别式肯定一定要学习的!因为很多时候,我们都必须要依据某些资料来判断程式该如何进行.举例来说,我们在上头的a ...
- 鸟哥的 Linux 私房菜Shell Scripts篇(二)
参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...
随机推荐
- springboot 2.0 Redis command timed out的解决
环境:springboot 2.0.7 spring data redis springboot从1.x升级到2.x后,spring data redis使用的redis客户端驱动从1.x的jedis ...
- Android Doze模式源码分析
科技的仿生学无处不在,给予我们启发.为了延长电池是使用寿命,google从蛇的冬眠中得到体会,那就是在某种情况下也让手机进入类冬眠的情况,从而引入了今天的主题,Doze模式,Doze中文是打盹儿,打盹 ...
- TCP/IP协议分析含义与功能
TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即网络接口层.IP层.传输层和应用层.TCP/IP是一组专业化协议,包括IP.TCP.UDP.ARP.ICMP以及其它的一些被称为子协 ...
- 【extjs6学习笔记】1.4 初始:ajax请求django应用
使用sencha创建应用,默认如下: personnel数据使用的是本地数据 做以下修改,使用ajax 启动时会报404[此次调用是使用nginx部署] django应用app_jiake中,修改vi ...
- Linux下端口被占用如何解决???
有时候关闭软件后,后台进程死掉,导致端口被占用.下面以JBoss端口8083被占用为例,列出详细解决过程. 解决方法: 1.查找被占用的端口 netstat -tln netstat -tln | g ...
- 大会聚焦 | 开源技术盛会LinuxCon首次来到中国,大咖齐聚关注业界动态
2017年6月19-20日,开源技术盛会LinuxCon + ContainerCon + CloudOpen(LC3)首次在中国举行.两天议程满满,包括 17 个主旨演讲.8 个分会场的 88 场技 ...
- UVA 536 TreeRocvery 树重建 (递归)
根据先序历遍和中序历遍输出后序历遍,并不需要真的建树,直接递归解决 #include<cstdio> #include<cstring> ; char preOrder[N]; ...
- 多线程程序设计-Thread的一些方法
run():是程序中会和会和其他线程“同时”执行的部分. wait():使得当前线程进入等待状态,等待的线程不会主动进入到线程队列中排队等待cpu资源,必须由其他线程调用notify()方法通知它 ...
- 毛毛虫组【Beta】Scrum Meeting 1
第一天 日期:2019/6/23 前言 第一次会议: 时间:6月20日 地点:教9-C404机房 内容:此次会议主要确定组内成员具体分工,并对目标进行了初步的确定. 1.1 今日完成任务情况以及遇到的 ...
- java基础—对象转型
一.对象转型介绍 对象转型分为两种:一种叫向上转型(父类对象的引用或者叫基类对象的引用指向子类对象,这就是向上转型),另一种叫向下转型.转型的意思是:如把float类型转成int类型,把double类 ...