Light, concurrent RPC framework for PHP & C
Light, concurrent RPC framework for PHP (see also: Yar C framework, Yar Java framework, Lua Yar framework)
Yar is an RPC framework which provides a simple and easy way to do communication between PHP applications. It also offers the ability to make multiple calls to remote services concurrently.
Yar is a native PHP extension — not a userland library. It uses a compact binary protocol (yar_header_t + packager payload) over HTTP or TCP, with no external runtime dependencies beyond curl. This means no Composer packages, no framework bootstrap, no separate proxy process. It's designed for the "just works" experience: install the extension, write a few lines of PHP, and you have RPC.
Yar is a PECL extension, simply install it by:
$ pecl install yar
$ /path/to/phpize
$ ./configure --with-php-config=/path/to/php-config/
$ make && make install
Available configure options:
--with-curl=DIR
--enable-msgpack / --disable-msgpack
--enable-epoll / --disable-epoll (requires Yar 2.1.2)
--enable-epoll replaces the default select()-based I/O multiplexing with Linux epoll. This can improve performance for Yar_Concurrent_Client under high concurrency. It only affects Linux; on other platforms it has no effect.
$ pecl install msgpack
Or for Ubuntu:
$ apt-get install msgpack-php
Or, get the source from GitHub: https://github.com/msgpack/msgpack-php
$ /path/to/phpize
$ ./configure --with-php-config=/path/to/php-config/ --enable-msgpack
$ make && make install
| INI Setting | Default | Description |
|---|---|---|
yar.timeout |
5000 |
Timeout in milliseconds |
yar.connect_timeout |
1000 |
Connection timeout in milliseconds |
yar.packager |
"php" (or "msgpack" if built with --enable-msgpack) |
One of "php", "json", "msgpack" |
yar.debug |
Off |
Enable debug mode. When enabled, Yar emits E_WARNING messages with detailed protocol-level information for every request and response, prefixed with [Debug Yar_Server] or [Debug Yar_Client] and including timestamps. |
yar.expose_info |
On |
Whether to output the API info page for GET requests |
yar.content_type |
"application/octet-stream" |
Content-Type sent in responses |
yar.ssl_verify |
Off |
Whether to verify the TLS certificate of HTTPS servers. When enabled, the curl transport sets CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST, and requests against servers with invalid certificates will fail. Disabled by default for backward compatibility. Available since 2.4.0. |
Note:
yar.connect_timeoutis in milliseconds. Prior to 1.2.1 it was measured in seconds.
YAR_OPT_PACKAGER
YAR_OPT_PERSISTENT
YAR_OPT_TIMEOUT
YAR_OPT_CONNECT_TIMEOUT
YAR_OPT_HEADER // Since 2.0.4
YAR_OPT_PROXY // Since 2.2.0
YAR_OPT_RESOLVE // Since 2.1.0
YAR_OPT_PROVIDER // Since 2.3.0
YAR_OPT_TOKEN // Since 2.3.0
YAR_VERSION
YAR_HAS_MSGPACK // 1 if compiled with --enable-msgpack, 0 otherwise
Used by Yar_Server_Exception::getType() and Yar_Client_Exception::getType() to indicate the nature of the error:
YAR_ERR_OKEY = 0x00 // No error
YAR_ERR_PACKAGER = 0x01 // Packager error
YAR_ERR_PROTOCOL = 0x02 // Protocol error
YAR_ERR_REQUEST = 0x04 // Request error
YAR_ERR_OUTPUT = 0x08 // Output error
YAR_ERR_TRANSPORT = 0x10 // Transport error
YAR_ERR_FORBIDDEN = 0x20 // Forbidden (auth failed or info page disabled)
YAR_ERR_EXCEPTION = 0x40 // General exception
Yar defines a structured exception hierarchy for both server and client errors:
Exception / RuntimeException
├── Yar_Server_Exception
│ ├── Yar_Server_Request_Exception
│ ├── Yar_Server_Protocol_Exception
│ ├── Yar_Server_Packager_Exception
│ └── Yar_Server_Output_Exception
└── Yar_Client_Exception
├── Yar_Client_Transport_Exception
├── Yar_Client_Protocol_Exception
└── Yar_Client_Packager_Exception
Both Yar_Server_Exception and Yar_Client_Exception extend Exception (or RuntimeException if SPL is available).
Yar_Server_Exception::getType() returns the error type constant (e.g. YAR_ERR_TRANSPORT).
Yar_Client_Exception::getType() returns the string "Yar_Exception_Client" — this is the exception class name, not an error type constant. If you need the actual error type on the client side, catch the specific sub-exception classes instead (e.g. Yar_Client_Transport_Exception, Yar_Client_Protocol_Exception, Yar_Client_Packager_Exception).
Note:
Yar_Serveris afinalclass and cannot be extended.
It's very easy to set up a Yar HTTP RPC Server:
<?php
class API
{
/**
* The doc info will be generated automatically into the service info page.
* @params
* @return
*/
public function some_method($parameter, $option = "foo")
{
}
protected function client_can_not_see()
{
}
}
$service = new Yar_Server(new API());
$service->handle();
Usual RPC calls are issued as HTTP POST requests.
If an HTTP GET request is issued to the URI (access the API address directly via a browser), the service info page (generated from the doc comments above) will be returned:
Yar_Server::__construct(object $executor)
Creates a new Yar server wrapping the given $executor object. All public methods of $executor are exposed as RPC endpoints.
Yar_Server::handle(): bool
Starts processing the incoming RPC request. Returns true on success.
Yar's PHP extension only provides an HTTP server. For TCP-based RPC servers, use the standalone Yar C framework. It supports TCP and Unix socket protocols and is fully compatible with Yar PHP clients. The C framework is also the recommended backend for production deployments with high throughput requirements.
Since 2.3.0, you can customise the output of the service info page by defining a __info magic method:
<?php
class API
{
protected function __info($markup)
{
return "Hello world";
}
}
Then if an HTTP GET request is issued, "Hello world" will be returned instead.
Since 2.3.0, Yar allows the server to authenticate client requests via Provider / Token fields in the header. To enable this, define a protected magic method named __auth on the server side:
<?php
class API
{
protected function __auth($provider, $token)
{
return verify($provider, $token);
}
}
Note:
__authmust always be defined asprotected.
If __auth is defined, it will be called at the very beginning of every request:
__auth returns true (or any truthy value — 1, a non-empty string, a non-empty array, etc.), the request proceeds.__auth returns false (exactly false), the request is terminated with an "authentication failed" error (YAR_ERR_FORBIDDEN).On the client side, specify the provider and token via:
<?php
$client->setOpt(YAR_OPT_PROVIDER, "provider");
$client->setOpt(YAR_OPT_TOKEN, "token");
$client->call();
Note:
Yar_Clientis afinalclass and cannot be extended.
Yar_Client::__construct(string $uri[, array $options = null])
Creates a new Yar client. The $uri is the server address (e.g. "http://host/api/" or "tcp://host:port").
$options is an optional array of initial options, e.g.:
$client = new Yar_Client("http://host/api/", [
YAR_OPT_CONNECT_TIMEOUT => 1000,
YAR_OPT_PERSISTENT => 1,
]);
Yar_Client::setOpt(int $type, mixed $value): Yar_Client|bool
Set a client option. Returns $this on success (for chaining), false on failure.
See Option Constants for available $type values.
Yar_Client::getOpt(int $type): mixed
Get the current value of a client option.
Yar_Client::call(string $method, array $arguments): mixed
Call a remote method by name. Returns the result on success.
Yar_Client supports PHP's __call, so these are equivalent:
$client->call("some_method", [$arg1, $arg2]);
$client->some_method($arg1, $arg2);
<?php
$client = new Yar_Client("http://host/api/");
/* the following setOpt calls are optional */
$client->setOpt(YAR_OPT_CONNECT_TIMEOUT, 1000);
$client->setOpt(YAR_OPT_HEADER, ["hd1: val", "hd2: val"]); // Custom headers, Since 2.0.4
/* call remote service */
$result = $client->some_method("parameter");
Yar supports sending multiple calls concurrently and collecting the results via a callback loop.
Note:
Yar_Concurrent_Clientonly supports HTTP/HTTPS protocol. TCP and Unix socket concurrent calls are not available — use individualYar_Clientinstances for those.Note: A maximum of 128 concurrent calls can be registered in a single
loop(). Exceeding this limit triggers a warning.
Each callback receives two arguments:
$retval — the return value of the remote method$callinfo — an array with call metadataEach error_callback receives three arguments:
$type — the error type constant$error — the error message$callinfo — an array with call metadata…
Yar_Concurrent_Client::call(
string $uri,
string $method,
?array $arguments = null,
?callable $callback = null,
?callable $error_callback = null,
?array $options = null
): null|int|bool
Registers a concurrent call. Returns null on error, or an opaque int ID on success.
Yar_Concurrent_Client::loop(
?callable $callback = null,
?callable $error_callback = null,
?array $options = null
): ?bool
Sends all registered concurrent calls and waits for responses. Returns true on success, null on failure.
Yar_Concurrent_Client::reset(): bool
Clears all registered concurrent calls without sending them. Returns true on success.
Since 2.1.0, if YAR_OPT_PERSISTENT is set to true, Yar will use HTTP keep-alive to speed
No open issues yet, or sync has not completed.