依赖的组件
hyperf/json-rpc
hyperf/rpc-client
hyperf/rpc-server
hyperf/service-governance
hyperf/consul
以 HTTP协议 为例
json-rpc 即为基于json的rpc调用,原理就是 A 和 B 拥有同一套 interface I 的定义,A 就像调用自己的方法一样调用B的方法F,当然F必须是 insterface I 中的方法。
保存镜像
docker commit -p hyperf raoxiaoya/hyperf:v1
一、服务端
1.1、启动服务提供者容器
docker run --name hyperf-db -p 9503:9503 --network host -v /data/www/hyperf-db:/hyperf-db -it --entrypoint /bin/sh raoxiaoya/hyperf:v1
cd /
composer create-project hyperf/hyperf-skeleton hyperf-db
安装的时候选择 JSON-RPC cd /hyperf-db
composer require hyperf/consul
服务治理组件,不然 publishTo 不会生效
composer require hyperf/service-governance 发布consul组件的配置到app
php bin/hyperf.php vendor:publish hyperf/consul
1.2、定义服务提供者
config/autoload/server.php
'servers' => [['name' => 'jsonrpc-http','type' => Server::SERVER_HTTP,'host' => '0.0.0.0','port' => 9503,'sock_type' => SWOOLE_SOCK_TCP,'callbacks' => [SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],],],
],
1.3、定义接口
app/JsonRpc/CalculatorServiceInterface.php
namespace App\JsonRpc;interface CalculatorServiceInterface
{public function add(int $a, int $b): int;
}
1.4、定义实现类
app/JsonRpc/CalculatorService.php
namespace App\JsonRpc;use Hyperf\RpcServer\Annotation\RpcService;
class CalculatorService implements CalculatorServiceInterface
{public function add(int $a, int $b): int{return $a + $b;}}
1.5、发布到服务中心
此地址为服务中心的地址,在启动服务时,Hyperf 会自动地将 @RpcService 定义了 publishTo 属性为 consul 的服务注册到服务中心去。
config/autoload/consul.php
return ['uri' => 'http://127.0.0.1:8500',
];
二、客户端
2.1、启动服务消费者容器
docker run --name hyperf-api -p 9502:9502 --network host -v /data/www/hyperf-api:/hyperf-api -it --entrypoint /bin/sh raoxiaoya/hyperf:v1cd /
composer create-project hyperf/hyperf-skeleton hyperf-api
安装的时候选择 JSON-RPC cd /hyperf-api
composer require hyperf/consul
2.2、定义服务消费者
config/autoload/server.php
'servers' => [['name' => 'http','type' => Server::SERVER_HTTP,'host' => '0.0.0.0','port' => 9502,'sock_type' => SWOOLE_SOCK_TCP,'callbacks' => [SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],],],
],
2.3、设置服务提供方地址,注册中心的地址
config/autoload/services.php
declare(strict_types=1);
return ['consumers' => [['name' => 'CalculatorService','service' => \App\JsonRpc\CalculatorServiceInterface::class,'id' => \App\JsonRpc\CalculatorServiceInterface::class,'protocol' => 'jsonrpc-http','load_balancer' => 'random','registry' => ['protocol' => 'consul','address' => 'http://127.0.0.1:8500',],'nodes' => [['host' => '127.0.0.1', 'port' => 9503],],'options' => ['connect_timeout' => 5.0,'recv_timeout' => 5.0,'settings' => ['open_eof_split' => true,'package_eof' => "\r\n",],'pool' => ['min_connections' => 1,'max_connections' => 32,'connect_timeout' => 10.0,'wait_timeout' => 3.0,'heartbeat' => -1,'max_idle_time' => 60.0,],],],],
];
2.4、定义接口,同服务端保持一致
app/JsonRpc/CalculatorServiceInterface.php
namespace App\JsonRpc;interface CalculatorServiceInterface
{public function add(int $a, int $b): int;
}指的注意的是,app/JsonRpc/CalculatorServiceInterface 接口应该发布到composer包,被多个服务所依赖。
2.5、定义路由
Router::addRoute(['GET'], '/testRpc', 'App\Controller\IndexController@testRpc');
2.7、控制器中调用
public function testRpc()
{$client = ApplicationContext::getContainer()->get(CalculatorServiceInterface::class);$res = $client->add(1, 2);return ['result' => $res,];
}
三、安装consul服务
然而文档中并没有说明如何安装 Consul 服务,以下对 Consul 做一个简单的安装。
docker pull consuldocker run --name=consul -p 8500:8500 -e CONSUL_BIND_INTERFACE=eth0 -d consul
访问页面
http://192.168.2.200:8500/
四、启动服务器
进入hyperf-db容器启动服务提供者
cd /hyperf-db
php bin/hyperf.php start
发现consul页面已经出来了一个services
进入hyperf-api容器启动服务消费者
cd /hyperf-api
php bin/hyperf.php start
访问接口
http://192.168.2.200:9502/testRpc
返回信息
{"result": 3
}
说明我们的服务已经搭建成功了。
优化的点
1、关于接口的管理
上面的示例中接口文件 app/JsonRpc/CalculatorServiceInterface.php 我是手动创建的,在实际应用中,或有很多个接口文件,且被不同的人管理,那么在这rpc架构中,这些接口又被多个服务所依赖,一旦接口被改动,都需要同步到其他依赖的服务,这是一件很抓狂的事情,所以我们应该将所有的接口整合到一个composer包,然后其他服务直接引入这个包,如果接口有改动,其他服务重新拉取即可。
创建composer包:https://blog.csdn.net/raoxiaoya/article/details/107759887
在 client 和 server 中都执行 composer require phprao/composer-test=v1.0.1 下载接口。然后删掉原先的接口文件
app/JsonRpc/CalculatorServiceInterface.php 然后把引用的 namespace 改一下就可以使用了。