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

揭开 Yar 神秘面纱

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

Yar 功能演示

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

 
  1. <?php
  2. class RpcClient {
  3. // RPC 服务地址映射表
  4. public static $rpcConfig = array(
  5. "RewardScoreService" => "http://10.211.55.4/yar/server/RewardScoreService.class.php",
  6. );
  7. public static function init($server){
  8. if (array_key_exists($server, self::$rpcConfig)) {
  9. $uri = self::$rpcConfig[$server];
  10. return new Yar_Client($uri);
  11. }
  12. }
  13. }
  14. $RewardScoreService = RpcClient::init("RewardScoreService");
  15. var_dump($RewardScoreService->support(1, 2));

服务器端代码

 
  1. <?php
  2. class RewardScoreService {
  3. /**
  4. * $uid 给 $feedId 点赞
  5. * @param $feedId interge
  6. * @param $uid interge
  7. * @return void
  8. */
  9. public function support($uid,$feedId){
  10. return "uid = ".$uid.", feedId = ".$feedId;
  11. }
  12. }
  13. $yar_server = new Yar_server(new RewardScoreService());
  14. $yar_server->handle();

访问结果如下

 
  1. 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传输协议为例子学习,代码简化一些如下:

 
  1. typedef struct _yar_transport_interface {
  2. void *data;
  3. int (*open)(struct _yar_transport_interface *self, char *address, uint len, long options, www.10rz.net/char **msg TSRMLS_DC);
  4. int (*send)(struct _yar_transport_interface *self, struct _yar_request *request, char **msg TSRMLS_DC);
  5. struct _yar_response * (*exec)(struct _yar_transport_interface *self, struct _yar_request *request TSRMLS_DC);
  6. int (*setopt)(struct _yar_transport_interface *self, long type, void *value, void *addition TSRMLS_DC);
  7. int (*calldata)(struct _yar_transport_interface *self, yar_call_data_t *calldata TSRMLS_DC);
  8. void (*close)(struct _yar_transport_interface *self TSRMLS_DC);
  9. } yar_transport_interface_t;
  10. typedef struct _yar_transport {
  11. const char *name;
  12. struct _yar_transport_interface * (*init)(TSRMLS_D);
  13. void (*destroy)(yar_transport_interface_t *self TSRMLS_DC);
  14. yar_transport_multi_t *multi;
  15. } yar_transport_t;

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

 
  1. yar_transport_t yar_transport_socket = {
  2. "sock",
  3. php_yar_socket_init,
  4. php_yar_socket_destroy,
  5. };

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

Yar 数据的打包和解包

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

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

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

 
  1. PHP_YAR_API yar_packager_t * php_yar_packager_get(char *name, int nlen TSRMLS_DC) /* {{{ */ {
  2. int i = 0;www.10rz.net
  3. for (;i<yar_packagers_list.num;i++) {
  4. if (strncasecmp(yar_packagers_list.packagers[i]->name, name, nlen) == 0) {
  5. return yar_packagers_list.packagers[i];
  6. }
  7. }
  8. return NULL;
  9. } /* }}} */

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

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

PHP 教父鸟哥 Yar 的原理分析的更多相关文章

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

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

  2. 鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)

    什么是 daemon 与服务 (service) Linux Daemon (守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些事件.它不需要用户输入就能运行 ...

  3. 跟着鸟哥学Linux系列笔记3-第11章BASH学习

    跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 跟着鸟哥学Linux系列笔记1 跟着鸟哥学Linux系列笔记2-第10章VIM学习 认识与学习bash 1. ...

  4. 鸟哥的linux私房菜勘误表

    博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://github.com/jiangxincode 知乎地址: https://ww ...

  5. (转)鸟哥SHELL入门材料

    http://blog.chinaunix.net/space.php?uid=9809038&do=blog&cuid=62903 经典入门材料! 学习 Shell Scripts ...

  6. (整理)ubuntu 的 相关知识(来自 鸟哥的私房菜)

    1. Linux 文件权限概念 $ ls 察看文件的指令 $ ls -al 出所有的文件详细的权限与属性 (包含隐藏档,就是文件名第一个字符为『 . 』的文件) 在你第一次以root身份登入Linux ...

  7. vsftp 详解鸟哥版

    FTP (File Transfer Protocol) 可说是最古老的协议之一了,主要是用来进行档案的传输,尤其是大型档案的传输使用 FTP 更是方便!不过,值得注意的是,使用 FTP 来传输时,其 ...

  8. 鸟哥的 Linux 私房菜Shell Scripts篇(四)

    12.4 条件判断式 只要讲到『程式』的话,那么条件判断式,亦即是『 if then 』这种判别式肯定一定要学习的!因为很多时候,我们都必须要依据某些资料来判断程式该如何进行.举例来说,我们在上头的a ...

  9. 鸟哥的 Linux 私房菜Shell Scripts篇(二)

    参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...

随机推荐

  1. jQuery中slim版本与普通版本的区别

    在jQuery3中,推出了一个slim版本.slim,百度翻译:细长的; 苗条的,纤细的; 微小的; 无价值的. 区别概述: slim即简化版,比普通版本缺少Ajax和特效模块模块. 官方发布地址:h ...

  2. [Oracle 视图] ALL_OBJECTS

    ALL_OBJECTS ALL_OBJECTS describes all objects accessible to the current user. ALL_OBJECTS描述当前用户的可访问的 ...

  3. 由Cocos2d-x工程入口窥见代理模式

    关于设计模式(Design Pattern),自从“四人帮”第一次在<Design Patterns: Elements of Reusable Object-Oriented Software ...

  4. gd调试命令,gdb调试core文件

    使用 gcc -g test.c -o test.out 编译程序,只有加-g参数才支持gdb调试: 然后 gdb ./test.out 运行可执行文件,进入gdb调试模式(gdb),在括号后面的输入 ...

  5. jacvaSe-LinkedList

    package com.java.chap08.sec02; import java.util.LinkedList; public class TestLinkedList { private st ...

  6. HDU 5500 Reorder the Books (水题)

    题意: 有n本书,编号为1~n,现在书的顺序乱了,要求恢复成有序的样子,每次只能抽出其中一本并插到最前面,问最少需要多少抽几次? 思路: 如果pos[i]放的不是书i的话,则书i的右边所有的书都必须抽 ...

  7. 有一个无效 SelectedValue,因为它不在项目列表中

    “Drp_XX”有一个无效 SelectedValue,因为它不在项目列表中 出现以上异常的原因肯定是将DrowDownList控件的SelectedValue属性赋值为一个列表中不存在的值.那么我们 ...

  8. UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)

    摘要:中途相遇.对比map,快排+二分查找,Hash效率. n是4000的级别,直接O(n^4)肯定超,所以中途相遇法,O(n^2)的时间枚举其中两个的和,O(n^2)的时间枚举其他两个的和的相反数, ...

  9. 01_2_模拟spring装载bean

    01_2_模拟spring装载bean 1. xml配置文件内容 beans.xml <beans> <bean id="u" class="com.w ...

  10. c++作业:求N的阶乘。

    N的阶乘就是n.(n-1)! 5的阶乘是什么?5*4*3*2*1 #include <iostream> using namespace std; int jiecheng(int num ...