- URL: https://www.laruence.com/en/2012/09/15/2779.html
- Please include attribution when republishing.
Yar (yet another RPC framework — the 教主 asked me why everything starts with "Ya", hehe, because it makes the names easier to come up with) is an RPC framework, built as a PHP extension, that I developed a little over three months ago to solve a real-world problem. Unlike the existing RPC frameworks (xml-rpc, soap), this is a lightweight framework that supports multiple packing protocols (msgpack, json, php), and — most importantly — it's capable of concurrent (parallel) calls.
Consider the following scenarios:
A traditional web application: one process, one request. That's the natural model. However, when handling a single request involves multiple data sources that have a certain degree of independence from each other...
Or, again a traditional web application: as a product grows fast and developers come and go, it slowly enters a vicious cycle — the codebase only ever grows, never shrinks. Because as the system becomes more complex, pulling one thread moves the whole thing, and a new maintainer doesn't have the time to fully master the existing architecture. And even if they did have that time, reconstructing the combined way of thinking of all the previous maintainers isn't easy either...
Left unchecked, the system becomes more and more unmaintainable... When a large application falls into this vicious cycle, all that's left for it is a rewrite.
So, can we decouple such a system?
We've already done a lot of decoupling — data, middleware, business, logic, and all kinds of layering. But when it comes to the web application layer, what else can we split? We've already done MVC...
Based on all this, Yar might just solve both of these problems for you.
Yar is a very lightweight RPC framework. In implementing Yar, I pursued ultimate lightweight design. It's extremely simple to use. Suppose you have a class called API that you need to expose as a service:
<?php
class API {
/**
* the doc info will be generated automatically into service info page.
* @params
* @return
*/
public function api($parameter, $option = "foo") {
}
protected function client_can_not_see() {
}
}
To bring in Yar, you only need:
<?php require "api.php"; $service = new Yar_Server(new API()); $service->handle(); ?>
Looks very similar to how you'd use Soap, right? Yes — and that's it. Your API class is now serving requests externally.
For developer convenience, Yar binds the documentation to the interface. For the example above, if you simply GET the service URL, you'll see the following info page:

That way, you can annotate the interface information in the comments, and keep the documentation together with the interface.
On the client side, a simple serial call is very easy:
<?php
$client = new Yar_Client("http://host/api/");
$result = $client->api("parameter");
?>
That way, if you have multiple services, you only need a single client.
So, what about the most exciting part — concurrent (parallel) calls?
<?php
function callback($retval, $callinfo) {
var_dump($retval);
}
Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback");
Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback");
Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback");
Yar_Concurrent_Client::call("http://host/api/", "api", array("parameters"), "callback");
Yar_Concurrent_Client::loop(); //send
?>
This way, all the requests are sent at once. As soon as any one of them completes, the "callback" function is called immediately.
There's also a subtle detail here: Yar squeezes in to not waste any time. After these requests are sent out, Yar will invoke the callback once. Unlike a normal response callback, the $callinfo parameter in this particular invocation is empty.
This way, we can send the requests first, then — in the first callback — keep doing the current process's local work, and only after all that local work is done hand things back to Yar to collect the concurrent RPC responses.
<?php
function callback($retval, $callinfo) {
if ($callinfo == NULL) {
//do the local logic
return TRUE;
}
//RPC response returned, the return value is in $retval
}
With all this in place, we can process multiple data sources in parallel within a web application, and thereby decouple those pieces of logic and deploy them separately.
A few links:
PECL package: Yar At PECL
Usage (Github Readme): Yar at Github
PS: to use Msgpack (an efficient binary packing protocol) as the packing protocol, you need to install the Msgpack extension separately (Msgpack).
Be First to Comment