JSON RPC:基于JSON格式的跨语言远程过程调用协议
Hyperf:基于Swoole的PHP协程框架,适合配合Docker搭建大型集群项目处理高并发场景
1、使用Hyperf搭建适配TCP协议的JSON RPC服务composer create-project hyperf/hyperf-skeleton Server/Client
What time zone do you want to setup ?
[n] Default time zone for php.ini
Make your selection or type a time zone name, like Asia/Shanghai (n): n
Which RPC protocol do you want to use ?
[1] JSON-RPC with Service Governance
[2] JSON-RPC
[3] gRPC
[n] None of the above
Make your selection or type a composer package name and version (n): 2
Which config center do you want to use ?
[1] Apollo
[2] Aliyun ACM
[n] None of the above
Make your selection or type a composer package name and version (n): 1
Do you want to use hyperf/constants component ?
[1] yes
[n] None of the above
Make your selection (n): 1
Do you want to use hyperf/async-queue component ? (A simple redis queue component)
[1] yes
[n] None of the above
Make your selection or type a composer package name and version (n): 1
Do you want to use hyperf/amqp component ?
[1] yes
[n] None of the above
Make your selection or type a composer package name and version (n): 1
Do you want to use hyperf/model-cache component ?
[1] yes
[n] None of the above
Make your selection or type a composer package name and version (n): 1
Do you want to use hyperf/elasticsearch component ?
[1] yes
[n] None of the above
Make your selection or type a composer package name and version (n): n
Do you want to use hyperf/tracer component ? (A open tracing protocol component, adapte with Zipkin etc.)
[1] yes
[n] None of the above
Make your selection or type a composer package name and version (n): 1
2、服务提供者(Server)的开发与配置
app目录结构:.
├── Constants
├── Controller
├── Exception
├── JsonRpc
│ ├── UserService.php
│ └── UserServiceInterface.php
├── Listener
├── Model
└── Process
server/app/JsonRpc/UserServiceInterface.php<?php
declare(strict_types=1);
namespace App\JsonRpc;
interface UserServiceInterface
{
/**
* 通过Id获取Token
* @param int $id ID
* @return string
*/
public function getTokenById(int $id): string;
}
server/app/JsonRpc/UserService.php<?php
declare(strict_types=1);
namespace App\JsonRpc;
use Hyperf\RpcServer\Annotation\RpcService;
/**
* Class UserService
* @RpcService(name="UserService", protocol="jsonrpc", server="jsonrpc")
*/
class UserService implements UserServiceInterface
{
public function getTokenById(int $id): string
{
return md5($id);
}
}
server/config/autoload/server.php<?php
declare(strict_types=1);
use Hyperf\Server\Server;
use Hyperf\Server\SwooleEvent;
return [
'mode' => SWOOLE_PROCESS,
'servers' => [
[
'name' => 'http',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9501,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
],
],
[
'name' => 'jsonrpc',
'type' => Server::SERVER_BASE,
'host' => '0.0.0.0',
'port' => 9505,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\TcpServer::class, 'onRequest'],
]
],
],
'settings' => [
'enable_coroutine' => true,
'worker_num' => swoole_cpu_num(),
'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
'open_tcp_nodelay' => true,
'max_coroutine' => 100000,
'open_http2_protocol' => true,
'max_request' => 100000,
'socket_buffer_size' => 2 * 1024 * 1024,
],
'callbacks' => [
SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
],
];
3、服务消费者(Client)的开发与配置
app目录结构:.
├── Constants
├── Controller
│ └── IndexController.php
├── Exception
├── JsonRpc
│ └── UserServiceInterface.php
├── Listener
├── Model
└── Process
client/app/JsonRpc/UserServiceInterface.php<?php
declare(strict_types=1);
namespace App\JsonRpc;
interface UserServiceInterface
{
/**
* 通过Id获取Token
* @param int $id ID
* @return string
*/
public function getTokenById(int $id): string;
}
client/app/Controller/IndexController.php<?php
namespace App\Controller;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\Utils\ApplicationContext;
use App\JsonRpc\CalculatorServiceInterface;
/**
* @AutoController()
*/
class IndexController extends AbstractController
{
public function index()
{
$user = $this->request->input('user', 'Hyperf');
$method = $this->request->getMethod();
return [
'method' => $method,
'message' => "Hello {$user}.",
];
}
public function get_token()
{
$server = ApplicationContext::getContainer()->get(UserServiceInterface::class);
var_dump($server->getTokenById(12345));
}
clientconfigautoloadserver.php<?php
declare(strict_types=1);
use Hyperf\Server\Server;
use Hyperf\Server\SwooleEvent;
return [
'mode' => SWOOLE_PROCESS,
'servers' => [
[
'name' => 'http',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9510,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
],
],
],
'settings' => [
'enable_coroutine' => true,
'worker_num' => swoole_cpu_num(),
'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
'open_tcp_nodelay' => true,
'max_coroutine' => 100000,
'open_http2_protocol' => true,
'max_request' => 100000,
'socket_buffer_size' => 2 * 1024 * 1024,
],
'callbacks' => [
SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
],
];
clientconfigautoloadservices.php<?php
declare(strict_types=1);
return [
'consumers' => value(function(){
$consumers = [];
$services = [
'UserService' => App\JsonRpc\UserServiceInterface::class
];
foreach ($services as $name => $interface) {
$consumers[] = [
'name' => $name,
'service' => $interface,
'protocol' => 'jsonrpc',
'load_balancer' => 'random',
'nodes' => [
['host' => '127.0.0.1', 'port' => 9505]
],
'options' => [
'pool' => [
'min_connections' => 1,
'max_connections' => 32,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
'max_idle_time' => 60.0,
]
]
];
}
return $consumers;
}),
];
4、服务启动与演示
启动:[Dark-Enchanter:/usr/local/var/www/jsonrpc/server » php ./bin/hyperf.php start
[Dark-Enchanter:/usr/local/var/www/jsonrpc/client » php ./bin/hyperf.php start
演示:[Dark-Enchanter:/usr/local/var/www/jsonrpc » curl http://127.0.0.1:9510/get_token
827ccb0eea8a706c4c34a16891f84e7b
典型RPC架构图: