PhpRpc 从 0 到 0.7
1.什么是RPC
RPC全称Remote Procedure Call,中文译为远程过程调用,简单理解就是 一种解决方案。
业务场景:
举一个大部分phper都接触过的商城开发,一般商城都有以下几个模块
- 商品模块
- 订单模块
- 会员模块
- XX模块
在常见架构中的体现是:
那么在RPC架构中每个模块就是一个服务提供者,架构体现:
在这套架构中业务机的职责就是把一个请求 ,拆分成N个小请求,分发到各个服务里面,再整合各个服务的结果,返回给用户。
例如在某次下单请求中,那么大概 发送的逻辑如下:
1. 业务机接受请求
2. 业务机提取用户参数,请求用户服务,获取用户余额等信息,等待结果
3. 业务机提取商品参数,请求商品服务,获取商品剩余库存和价格等信息,等待结果。
4. 业务机融合用户服务、商品服务的返回结果,进行下一步调用(假设满足购买条件)
5. 业务机调用用户服务进行扣款,调用商品服务进行库存扣减,调用订单服务进行下单(事务逻辑和撤回可以用请求id保证,或者自己实现其他逻辑调度)
6. 业务机根据处理响应用户
而在以上发生的行为,就称为远程过程调用。而调用过程实现的通讯协议可以有很多,比如常见的HTTP、TCP协议。
服务熔断
某个服务故障或者异常时直接熔断整个服务,而不是一直等到此服务超时
服务降级
当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回掉,返回一个缺省值 ,这样做,虽然服务水平下降,但好歹,比直接挂掉要强。 服务降级处理是在客户端实现完成的,与服务端没有关系
服务限流
例如某个服务器最多同时仅能处理100个请求, 或者是cpu负载达到百分之80的时候, 为了保护服务的稳定性,则不在希望继续收到 新的连接。那么此时就要求客户端不再对其发起请求,例如 你可以以任何的形式来监控你的服务,当触发某个条件时(CPU负载80%)下线此服务,业务机动态获取服务节点时就可以知道此服务已限流则响应用户[网络繁忙,请稍后再试] 或者此服务有多台机提供则其他机可继续提供服务,等被下线的机子恢复后又上线
2.Php Tcp通讯
源码
https://github.com/ar414-com/RpcDemo
开发环境要求
- 保证 PHP 版本大于等于 7.2
- 保证 Swoole 拓展版本大于等于 4.3.5
- 使用 Linux / FreeBSD / MacOS 这三类操作系统
作者开发环境
- PHP 7.2
- Swoole 4.3.5
- CentOS 7.2
创建一个最基本的TCP服务器
<?php //创建Server对象,监听 0.0.0.0:20001端口 $serv = new Swoole\Server("0.0.0.0", 20001); $serv->on('Start', function ($serv) { echo "服务已启动,主进程PID:{$serv->master_pid}\n"; }); //监听连接进入事件 $serv->on('Connect', function ($serv, $fd) { echo "Client: Connect.\n";}); //监听数据接收事件 $serv->on('Receive', function ($serv, $fd, $from_id, $data) { echo "接收客户端数据:{$data}\n"; $serv->send($fd, "Server: ".$data); }); //监听连接关闭事件 $serv->on('Close', function ($serv, $fd) { echo "Client: Close.\n";}); //启动服务器 $serv->start();
<?php //建立连接 $fp = stream_socket_client('tcp://127.0.0.1:20001'); //发送数据 fwrite($fp, 'Test'); //主动获取响应 $data = fread($fp, 65533); echo "服务端响应数据:{$data}\n"; //断开连接 fclose($fp);
客户端
服务端
3.客户端调用与服务端处理(提供思路)
客户端与服务器的数据传输约定
客户端请求Rpc服务(以下并非完整代码)
- 场景:例如在一个商场系统中,我们将商品库和用户库两个服务切分开到不同的服务器当中
- 当用户打开商场首页的时候, 我们希望App向某个网关发起请求,
- 该网关可以自动的帮我们请求商品列表和用户信息等数据
//商品列表 $data = [ 'service' => 'Goods', //服务名称 'action' => 'getList', //具体方法 'arg' => ['page' => 1] //请求参数 ]; //用户信息 $data = [ 'service' => 'User', //服务名称 'action' => 'getUserInfoForToken', //具体方法 'arg' => ['token' => '6aa62603ef82b70597a90d93af04b542'] //请求参数 ]; //打包数据 $dataStr = serialize($data); $dataStr = pack('N', strlen($str)).$str;
请求API网关 API网关自动根据Service参数查询出对应服务IP、PORT并进行调用返回
本示例为了方便将Rpc服务配置写入.env文件 例:
//.env RPC_GOODS_HOST=10.0.0.1 RPC_GOODS_PORT=8899 RPC_USER_HOST=10.0.0.2 RPC_USER_PORT=8899
服务端处理请求(完整代码)
//接受请求数据并解包 $data = substr($request,'4'); $data = unserialize($data); //TODO 检测必须参数 service action //检测服务是否存在 //$controllerNameSpace是你的控制器命名空间 $service = ucfirst($data['service']); $class = "{$controllerNameSpace}\\{$service}"; if(!class_exists($class)) { //TODO 服务不存在 //设置响应状态错误码(需自行封装) $response->setStatus(Response::STATUS_SERVICE_SERVICE_NOT_FOUND); //响应客户端(需自行封装) goto response;} //检测方法是否存在 $class = new \ReflectionClass($class); $action = $data['action']; if(!$class->hasMethod($action)) { //action不存在 //重新组装参数 //如果方法则调用魔术方法 比如调用一些PDO方法,如果无则调用时返回方法不存在 $request->proxyActionAssemblyArg(); $method = $class->getMethod('__call');} else { $method = $class->getMethod($action);} //调用 $instance = $class->newInstance($request,$response); $ret = $method->invokeArgs($instance,$request->getArg()); $response->setMessage($ret); //响应客户端(需自行封装) goto response; //作者的响应封装(仅供参考): response:{ if ($server->exist($fd)) { $message = $response->getMessage(); $responseData = [ 'status' => $response->getStatus(), 'data' => $message ]; $responseData = serialize($responseData); $responseData = Request::pack($responseData); $server->send($fd,$responseData); //判断客户端是否需要长连接 if(!$request->getIsKeep()) { $server->close($fd); } } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
码侬进阶Java架构师,需要掌握哪些技能?
架构师是什么?是一个既需要掌控整体又需要洞悉局部瓶颈并依据具体的业务场景给出解决方案的团队领导型人物。一个架构师得需要足够的想像力,能把各种目标需求进行不同维度的扩展,为目标客户提供更为全面的需求清单。所谓架构师,思考的是全局的东西,是如何组织你的系统,以达到业务要求,性能要求,具备可扩展性(scalability),可拓展性(extendability),前后兼容性等。可能涉及到的东西包括了从硬件到软件的方方面面。 架构师在软件开发的整个过程中起着很重要的作用。架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作。他必须对开发技术非常了解,并且需要有良好的组织管理能力。可以这样说,一个架构师工作的好坏决定了整个软件开发项目的成败。在成为Java架构师之前,应当先成为Java工程师。熟练使用各种框架,并知道它们实现的原理。jvm虚拟机原理、调优,懂得jvm能让你写出性能更好的代码;池技术,什么对象池,连接池,线程池……Java反射技术,写框架必备的技术,但是有严重的性能问题,替代方案java字节码技术;nio,没什么好说的,值得注意的是"直接内存"的特点,使用场...
- 下一篇
03月18日云栖号头条:达摩院AI火神山上线,已临床诊断26万病例
云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! 今日最新云头条快讯: 3月17日,记者获悉,达摩院医疗AI在武汉火神山医院上线。目前,达摩院医疗AI已在全国160多家医院上线,临床诊断26万病例;科技部生物中心主任张新民表示,法匹拉韦已完成临床研究,显示出很好的临床疗效。 一起来看最新的资讯: 达摩院AI火神山上线,已临床诊断26万病例 火神山医院目前仍有近千名患者,据官方数据,湖北出院患者平均住院20天,每3-4天需进行一次CT影像诊断,每位患者住院全程平均约有2000张以上CT影像,医生如果每次都依靠人工阅片并比对患者过往影像资料需要耗费极大精力。医疗AI解决了这一难题。公开资料显示,达摩院CT影像AI可在20秒内完成一次诊断(计算时间最短仅2秒),且准确率高达96%以上,大大节省医疗资源。 又双叒熔断了,美联储的7000亿美金,把美股打进“ICU” 美股史上仅有四次熔断,三次发生在一周内。美联储紧急投放7000亿美元救市,不但没能扭转颓势,反而引发了更大的恐慌。3月16日,美...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果