- 本文地址: https://www.laruence.com/2020/03/16/5578.html
- 转载请注明出处
Yar(Yet Another RPC framework)是一个轻量级支持并行调用的PHP RPC框架,是我还在微博的时候为了优化微博的性能而开发的一个工具,Yar的并行调用在微博被大量应用以降低用户请求耗时。
最近还是因为疫情,我把Yaf,Yaconf都优化了一轮,今天也完成了Yar的优化(事实上,Yar之前写的就还不错,没啥可优化的,哈哈),也新增了俩个能力。我来简单介绍下:
链接持久化
也就是YAR_OPT_PERSISTENT, 这个配置之前一直有,只不过之前是设计为跨请求的持久化,这次做了优化,变成了基于PHP请求生命期的链接保持。
也就是说,当你对一个Yar_Client设置了YAR_OPT_PERSISTEN为true的话,在一次RPC调用结束后,Yar不会销毁这个链接,从而加速后续的针对同样这个Client的RPC调用,我们来看个例子:
<?php function bench($client) { $start = microtime(true); $client->header("connection"); echo microtime(true) - $start, "s\n"; } $client = new Yar_Client("http://remote_host/index.php"); $client->setOpt(YAR_OPT_PERSISTENT, 1); bench($client); bench($client); bench($client);
输出:
0.090613842010498s 0.045492887496948s 0.045512914657593s
可见,第二次调用的时候,耗时降低了一半,这是因为节省了TCP链接建立的耗时。
最后,链接会在PHP请求结束以后,整体释放,也就是PHP请求生命期的存活,不会垮请求,也不用担心内存泄漏。
不过很遗憾,这个并不能用于加速并行调用:
function callback($retval, $callinfo) { global $start; if ($callinfo) { echo "Num ", $callinfo["sequence"] , " costs: ", microtime(true) - $start, "s\n"; } } Yar_Concurrent_Client::call("http://remote_host/index.php", "header", array("connection"), NULL, NULL, array(YAR_OPT_PERSISTENT=>1)); $start = microtime(true); Yar_Concurrent_Client::loop("callback", function($error) { var_dump($error); }); $start = microtime(true); Yar_Concurrent_Client::loop("callback", function($error) { var_dump($error); });
我们会发现俩次调用没有加速的效果:
Num 1 costs: 0.091023921966553s Num 1 costs: 0.090677976608276s
这跟Yar底层使用的libcurl有关系,从libcurl的官方文档关于curl_multi_add_handle:
When an easy interface is added to a multi handle, it will use a shared connection cache owned by the multi handle. Removing and adding new easy handles will not affect the pool of connections or the ability to do connection re-use.
也就是说,只要我把一个我们打开的libcurl cp通过curl_multi_add_handle加入到并行队列,这个cp就会使用libcurl multi自己管理的共享连接池,不会受Yar自己管理的persistent与否影响了。而这个共享是指在整个一次libcurl multi的请求过程中的共享,但事实上因为我们一次会发出所有请求,不会存在一个请求完成下一个请求开始的情况,那么也就不会存在复用了。
不过,我后来观察到在某些版本之上的libcurl,比如我测试的7.58.0下,可以看到加速的效果(这个是本机测试,所以看起来速度快很多):
Num 1 costs: 0.0017080307006836s Num 1 costs: 0.0010600090026855s
后续有时间需要慢慢研究下,从libcurl哪个版本开始的变化。
自定义DNS
这个是来自HuangeChaodian网友的PR,基本上是有的时候,我们需要自定义某个Host的DNS解析结果,比如在测试的时候,把一个Hostname指向本地。
诚然,我们可以使用编辑hosts来达到这个效果, 但如果能在代码中切换,还是会方便不少,看例子:
<?php $client = new Yar_Client("http://remote_host/index.php"); $client->setOpt(YAR_OPT_RESOLVE, "remote_host:80:127.0.0.1");
这样,Yar就会把remote_host解析为127.0.0.1了, 可以方便我们做一些本地调试。
性能优化
我现在发现,我写的代码随着时间的变化性能提升还是很明显的, 因为Yar写的比较晚, 相对来说可优化的点不多, 于是就简单点做了一些小修补,就不提了,:)
最后,2.1.0 已经发布Yar-2.1.0.
Enjoy!
Thanks for this virsion bird brother
大佬,这个框架无法执行后续方法吗?
比如:
class A{
function __constract(){
$server = new \Yar_Server($this);
$server->handle();
}
function a(){
echo ‘aa’;
}
function __destruct(){
echo ‘该方法不被执行’;
}
}
$a = new A();
$a->a();
这里的注销函数不执行吗?
truthbet Online service providers That answers all needs Excellent 24 hours a day.
so much great information on here, : D.
dna24bet
Great! It sounds good. Thanks for sharing..
chudjenbet
Thank you very much for this great post
thailotto
YAR 能否支持TCP直接传递数据。。。
老是识别不了我的方法,驼峰命名,蛇形命名都试过,10次要出现4,5次
这里:spprintf(msg, 0, “%s”, “need specifical request method”);
可以总结一个重现方法,包括你使用的php的版本,操作系统等信息,贴在github上提个issue
请求10次有4-5次报这个错误 need specifical request method ,应该怎么办?
你的php版本是多少?
[…] Yar-2.1 新功能介绍 […]
支持鸟哥,个人微服务使用了鸟哥的yar rpc框架,但是最近升级php8.0后发现yar框架编译失败了,希望鸟哥帮忙抽空升级下兼容下php8.0. github上也提了一个issue。😃
正在使用中,赞赞赞
鸟哥,用了yar很久了, 但是目前就一直有一个困扰的问题像请求解决方法。
使用yar请求远程服务器,如果响应http code是 200 则正常,如果是其他 比如301,302, 307 之类的,就不能正常跳转,直接抛出异常了。
那肯定不能跳转啊, 这个是RPC啊, 你自我克服下。
升级到2.1.2版本 ,报错:curl exec failed ‘Timeout was reached’ 对libcurl版本有要求吗
你适当增大yar.timeout看看,单位是毫秒, 默认5000
我也遇到了这个问题。。
支持鸟哥
现在项目中就有在用
占鸟哥的坑