早上刷牙,处于半睡状态。突然想起昨天晚上看到的那个 go-lang 的 MVC 框架,若使用 go func() 方式异步获取数据,应当是不错的。窃喜……梦醒……
在地铁上被前前后后那些特种男女逼到车角,无奈。又想起早上那个白日梦,遂上网搜索了一番。得老赵的佳作一篇《F# 与ASP.NET(1):基于事件的异步模式与异步Action》。之前看过,由于对微软无爱,未能细品。今日一读,如醍醐灌顶,豁然开朗。
遂整理思路如下,以待后用。
在说异步模型之前,先说说最常见的同步模型吧。例如下面的 PHP 代码:
// 获取数据 $userInfo = getUserInfo(); $newsList = getNewsList(); $topRateNewsList = getNewsList('DESC `rate`'); // 创建模板,绑定变量 $tmp = CreateTemplate(); $tmp->bind('userInfo', $userInfo); $tmp->bind('newsList', $newsList); $tmp->bind('topRateNewsList', $topRateNewsList); // 渲染模板,输出 $tmp->render(); echo $tmp;
在这段代码中,所有调用都是顺序的。也就是说,如果 getUserInfo($userId) 没有返回用户信息的话,getNewsList(5) 永远都不会被调用。实际情况,可能是用户信息是从用户库取数据,新闻是从新闻库取数据。假设新闻库运行良好,而由于某种原因用户库宕机了,那么这次请求也就废掉了。故障也从一个库的宕机扩散到整个站点。
现在,我白日做梦的创建一种新语言 go-php,引入 go-lang 的关键字 go 到 php 中:
// 创建一个数据通道 $chan = CreateChan(); // 获取数据,并放到数据通道上去 go getUserInfo($chan); go getNewsList($chan); $params = array('DESC `rate`'); go getNewsList($chan, $params); // 创建模板 $tmp = CreateTemplate(); // 从通道上取数据 while($d = $chan->read()) { if ($d['error']) { // 数据有错误 ……处理一下吧 } else { $tmp->bind($d['key'], $d['data']); } } // 渲染模板,输出 $tmp->render(); echo $tmp;
好了,这其实不是什么新奇创造,这只是一个二段式异步调用(Begin/End)。这有点像大宗采购,采购商并不一件一件的商品进行采购,而是拿着清单说:“好了,兄弟,这是我要的货,你们帮我找齐,放到码头406号仓库去……”,然后他就在 406 号仓库等着点货了。这段代码还可以改进,就像采购清单一样,将这个清单推到数据层,数据层把数据返回到数据通道上去。恩,应该不少人在自己的应用中使用 MQ,Memcache 甚至 pipe 实现了这种异步了吧。
再来看另外一段 go-php 代码:
/** * 回调函数 * @param $tmp 模板 * @param $d 返回的数据 */ function callbackBind($tmp, $d) { if ($d['error']) { // 数据有错误 ……处理一下吧 } else { $tmp->bind($d['key'], $d['data']); } } // 创建模板 $tmp = CreateTemplate(); // 获取数据,并设置数据回调 go getUserInfo(callbackBind, $tmp); go getNewsList(callbackBind, $tmp); $params = array('DESC `rate`'); go getNewsList(callbackBind, $tmp, $params); // 如果不是所有数据都回调了,则阻塞 $tmp->wait(); // 渲染模板,输出 $tmp->render(); echo $tmp;
这就是老赵的事件回调的异步处理的 go-php 版本。这有点像渠道商订货(或者淘宝上的无货代理?):“我需要XXXX,你帮我送到XXXX去”。然后坐等,所有的内容都送到了,就收钱走人。
对于数据读取的错误,只要处理得当也不是致命的。最多在渲染页面的时候,少某块数据,用户只会奇怪:“这次怎么打开没有新闻那部分的内容了呢……刷新一下看看……”。而不会说:“烂网站,又打不开了……”用户体验直线上升啊!
好了,梦就做到这里。相信这两种方式其实已经有实际案例了。我比较孤陋寡闻一些,了解的不多。而且有的东西,未经许可也不好多说……大家私下打听吧。
总之呢,两种异步模型各自有各自的好处。并行的数据存取,提高 I/O 利用率是其本质。王道啊……
有疑问加站长微信联系(非本文作者)