官网地址 | 中文版协议规范 | GitHub

轻量级,高性能 JsonRPC 2.0 客户端和服务端的php扩展,基于 multi_curl + epoll的并行客户端。Jsonrpc_Client使用libcurl库的并行接口调取服务,使用IO多路复用的epoll去监听curl的IO事件,使用协程可以同步返回rpc的数据,但底层其实是异步的。Jsonrpc_Server支持php-fpm或swoole。遵守http://www.jsonrpc.org/协议规范。 English

特性

  • JSON-RPC 2.0协议规范
  • 并发curl与epoll结合的并行客户端
  • php-fpm中持久化epoll
  • php-fpm中持久化curl_multi队列
  • 默认使用YAJL解析JSON
  • 服务端支持请求与通知
  • Linux系统(需要支持epoll)

    PHP环境

  • PHP 5.3.*

  • PHP 5.4.*
  • PHP 5.5.*
  • PHP 5.6.*

    安装

    $/path/to/phpize $./configure —with-php-config=/path/to/php-config $make && make install

服务端

接口

  • Jsonrpc_Server::__construct(mixed payload,arraypayload,arraycallbacks, array $classes)
  • Jsonrpc_Server::register(string name,mixedname,mixedclosure)
  • Jsonrpc_Server::bind(string procedure,mixedprocedure,mixedclassname, string $method)
  • Jsonrpc_Server::jsonformat()
  • Jsonrpc_Server::rpcformat(mixed $payload)
  • Jsonrpc_Server::executeprocedure(string procedure,arrayprocedure,arrayparams)
  • Jsonrpc_Server::executecallback(object closure,arrayclosure,arrayparams)
  • Jsonrpc_Server::executemethod(string class,stringclass,stringmethod, array $params)
  • Jsonrpc_Server::execute(boolean $response_type)

注册函数

  1. <?php
  2. $server = new Jsonrpc_Server();
  3. // style one function variable
  4. $add1 = function($a, $b){
  5. return $a + $b;
  6. };
  7. $server->register('addition1', $add1);
  8. // style two function string
  9. function add2($a, $b){
  10. return $a + $b;
  11. }
  12. $server->register('addition2', 'add2');
  13. // style three function closure
  14. $server->register('addition3', function ($a, $b) {
  15. return $a + $b;
  16. });
  17. //style four class method string
  18. class Api
  19. {
  20. static public function add($a, $b)
  21. {
  22. return $a + $b;
  23. }
  24. }
  25. $server->register('addition4', 'Api::add');
  26. echo $server->execute();
  27. //output >>>
  28. //{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
  29. ?>

绑定方法

  1. <?php
  2. $server = new Jsonrpc_Server();
  3. class Api
  4. {
  5. static public function add($a, $b)
  6. {
  7. return $a + $b;
  8. }
  9. public function newadd($a,$b){
  10. return $a + $b;
  11. }
  12. }
  13. $server->bind('addition5', 'Api', 'add');
  14. $server->bind('addition6', $a=new Api, 'newadd');
  15. echo $server->execute();
  16. //output >>>
  17. //{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
  18. ?>

swoole jsonrpc server

  1. <?php
  2. $http = new swoole_http_server("127.0.0.1", 9501);
  3. function add($a, $b){
  4. return $a + $b;
  5. }
  6. $http->on('Request', function($request, $response){
  7. if ($request->server['request_uri'] == "/jsonrpc_server"){
  8. $payload = $request->rawContent();
  9. $jsr_server = new Jsonrpc_Server($payload);
  10. $jsr_server->register('addition', 'add');
  11. $res = $jsr_server->execute();
  12. $response->end($res);
  13. unset($payload);
  14. unset($jsr_server);
  15. unset($res);
  16. }else {
  17. $response->end("error");
  18. }
  19. });
  20. $http->start();
  21. ?>

客户端

接口

  • Jsonrpc_Client::__construct(boolean $persist)
  • Jsonrpc_Client::call(string url,stringurl,stringprocedure, array params,mixedparams,mixedid)
  • Jsonrpc_Client::connect(string $url)
  • Jsonrpc_Client::__call(string procedure,arrayprocedure,arrayparams)
  • Jsonrpc_Client::execute(boolean $response_type)
  • Jsonrpc_Client::authentication(string username,stringusername,stringpassword)
  • Jsonrpc_Client::__destruct()

持久化

Jsonrpc_client(1) 参数为1的时候,将epoll和curl_multi队列两个资源进行持久化,默认使用非持久化。

直接调用

  1. <?php
  2. $client = new Jsonrpc_Client(1);
  3. $client->connect('http://localhost/server.php');
  4. $client->addition1(3,5);
  5. $result = $client->execute();
  6. ?>

并行调用

  1. <?php
  2. $client = new Jsonrpc_Client(1);
  3. $client->call('http://localhost/server.php', 'addition1', array(3,5));
  4. $client->call('http://localhost/server.php', 'addition2', array(10,20));
  5. /* ... */
  6. $result = $client->execute();
  7. var_dump($result);
  8. //output >>>
  9. /*
  10. array(2) {
  11. [0]=>
  12. array(3) {
  13. ["jsonrpc"]=>
  14. string(3) "2.0"
  15. ["id"]=>
  16. int(110507766)
  17. ["result"]=>
  18. int(8)
  19. }
  20. [1]=>
  21. array(3) {
  22. ["jsonrpc"]=>
  23. string(3) "2.0"
  24. ["id"]=>
  25. int(1559316299)
  26. ["result"]=>
  27. int(30)
  28. }
  29. ...
  30. }
  31. */
  32. ?>

自定义 id

  1. <?php
  2. $client = new Jsonrpc_client(1);
  3. $client->call('http://localhost/server.php', 'addition', array(3,5),"custom_id_001");
  4. $result = $client->execute();
  5. var_dump($result);
  6. //output >>>
  7. /*
  8. array(1) {
  9. [0]=>
  10. array(3) {
  11. ["jsonrpc"]=>
  12. string(3) "2.0"
  13. ["id"]=>
  14. string(13) "custom_id_001"
  15. ["result"]=>
  16. int(8)
  17. }
  18. }
  19. */
  20. ?>

YAJL 生成/解析

Interface

  • Jsonrpc_Yajl::generate(array $array)
  • Jsonrpc_Yajl::parse(string $json)

生成

  1. <?php
  2. $arr = array(
  3. 1,
  4. "string",
  5. array("key"=>"value")
  6. );
  7. var_dump(Jsonrpc_Yajl::generate($arr));
  8. /* ==>output
  9. string(28) "[1,"string",{"key":"value"}]";
  10. */
  11. ?>

解析

  1. <?php
  2. $str = '[1,"string",{"key":"value"}]';
  3. var_dump(Jsonrpc_Yajl::parse($str));
  4. /* ==>output
  5. array(3) {
  6. [0]=>
  7. int(1)
  8. [1]=>
  9. string(6) "string"
  10. [2]=>
  11. array(1) {
  12. ["key"]=>
  13. string(5) "value"
  14. }
  15. }
  16. */
  17. ?>

常见错误信息

jsonrpc 2.0 错误信息

  1. // 语法解析错误
  2. {"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
  3. // 无效请求
  4. {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid Request"}}
  5. // 找不到方法
  6. {"jsonrpc":"2.0","id":null,"error":{"code":-32601,"message":"Method not found"}}
  7. // 无效的参数
  8. {"jsonrpc":"2.0","id":null,"error":{"code":-32602,"message":"Invalid params"}}
  9. //

HTTP协议错误信息

  1. // 400
  2. {"jsonrpc":"2.0","id":null,"error":{"code":-32400,"message":"Bad Request"}}
  3. // 401
  4. {"jsonrpc":"2.0","id":null,"error":{"code":-32401,"message":"Unauthorized"}}
  5. // 403
  6. {"jsonrpc":"2.0","id":null,"error":{"code":-32403,"message":"Forbidden"}}
  7. // 404
  8. {"jsonrpc":"2.0","id":null,"error":{"code":-32404,"message":"Not Found"}}
  9. // 500
  10. {"jsonrpc":"2.0","id":null,"error":{"code":-32500,"message":"Internal Server Error"}}
  11. // 502
  12. {"jsonrpc":"2.0","id":null,"error":{"code":-32502,"message":"Bad Gateway"}}
  13. ...
  14. // unknow
  15. {"jsonrpc":"2.0","id":null,"error":{"code":-32599,"message":"HTTP Unknow"}}

curl错误信息

  1. // 1 CURLE_UNSUPPORTED_PROTOCOL
  2. {"jsonrpc":"2.0","id":null,"error":{"code":-32001,"message":"Curl Unsupported Protocol"}}
  3. // 2 CURLE_FAILED_INIT
  4. {"jsonrpc":"2.0","id":null,"error":{"code":-32002,"message":"Curl Failed Init"}}
  5. // 3 CURLE_URL_MALFORMAT
  6. {"jsonrpc":"2.0","id":null,"error":{"code":-32003,"message":"Curl Url Malformat"}}
  7. // 4
  8. {"jsonrpc":"2.0","id":null,"error":{"code":-32004,"message":"Curl Not Built In"}}
  9. // 5 CURLE_COULDNT_RESOLVE_PROXY
  10. {"jsonrpc":"2.0","id":null,"error":{"code":-32005,"message":"Curl Couldnt Resolve Proxy"}}
  11. // 6 CURLE_COULDNT_RESOLVE_HOST
  12. {"jsonrpc":"2.0","id":null,"error":{"code":-32006,"message":"Curl Couldnt Resolve Host"}}
  13. // 7 CURLE_COULDNT_CONNECT
  14. {"jsonrpc":"2.0","id":null,"error":{"code":-32007,"message":"Curl Couldnt Connect"}}
  15. ...
  16. // CURL ERROR UNKNOW
  17. {"jsonrpc":"2.0","id":null,"error":{"code":-32099,"message":"Curl Error Unknow"}}