安装依赖
由于使用的是JSON-RPC服务,所以先要安装json-rpc
composer require hyperf/json-rpc
一个微服务极可能是服务端也可能是消费端,所以同时安装服务端和消费端
composer require hyperf/rpc-server
composer require hyperf/rpc-client
使用nacos作为服务的注册中心,所以还需要安装nacos的相关依赖
composer require hyperf/service-governance
composer require hyperf/service-governance-nacos
安装nacos服务,这个自行百度即可
相关配置
首先是config/autoload/server.php,在这里需要配置一个server,用于提供json-rpc服务,这个name属性必须是一个全局唯一的值
return [
'mode' => SWOOLE_PROCESS,
'servers' => [
[
'name' => 'jsonrpc-http',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9503,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
Event::ON_REQUEST => [Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
],
],
],
// 微服务配置
'enable' => [
'discovery' => true,
'register' => true,
],
'providers' => [],
'drivers' => [
'nacos' => [
'host' => '127.0.0.1',
'port' => 8848,
'username' => 'nacos',
'password' => 'nacos',
'guzzle' => [
'config' => null,
],
// 根据nacos客户端实际配置
'group_name' => '',
'namespace_id' => '',
'heartbeat' => 5,
],
],
];
接下来是config/autoload/services.php,这里主要是用于服务消费者端的配置
return [
// 微服务配置
'enable' => [
'discovery' => true,
'register' => true,
],
'consumers' => \Hyperf\Support\value(function () {
$consumers = [];
//这一段是很关键的,用于映射注册的服务名与消费端的接口层,后面在实际使用时将会通过注入接口来进行方法调用
$services = [
'TestService' => App\JsonRpc\Iface\TestServiceInterface::class,
];
foreach ($services as $name => $interface) {
$consumers[] = [
'name' => $name,
'service' => $interface,
'registry' => [
'protocol' => 'nacos',
'address' => 'http://127.0.0.1:8848',
]
];
}
return $consumers;
}),
'providers' => [],
'load_balancer' => 'random',
//若nacos没有开启鉴权,用户名和密码也可以不填
'drivers' => [
'nacos' => [
'host' => '127.0.0.1',
'port' => 8848,
'username' => 'nacos',
'password' => 'nacos',
'guzzle' => [
'config' => null,
],
// 根据nacos客户端实际配置
'group_name' => 'DEFAULT_GROUP',
'namespace_id' => 'public',
'heartbeat' => 5,
],
],
];
服务端
1、创建一个接口 TestServiceInterface.php
namespace App\JsonRpc\Iface;
interface TestServiceInterface
{
function add(int $a, int $b);
}
2、创建一个服务提供类 TestService.php,实现接口TestServiceInterface
namespace App\JsonRpc;
use App\JsonRpc\Iface\TestServiceInterface;
use Hyperf\RpcServer\Annotation\RpcService;
//name属性为定义该服务的名称,这里定义一个全局唯一的名字即可,Hyperf 会根据该属性生成对应的 ID 注册到服务中心去
//protocol属性为定义该服务暴露的协议
//server属性为绑定该服务类发布所要承载的 Server,默认值为 `jsonrpc-http`,该属性对应 `config/autoload/server.php` 文件内 `servers` 下所对应的 `name`,这里也就意味着我们需要定义一个对应的 `Server`,在‘相关配置’章节我们已经定义了
//publishTo属性为定义该服务所要发布的服务中心,目前仅支持 `consul`、`nacos` 或为空,为空时代表不发布该服务到服务中心去
#[RpcService(name: "TestService", protocol: "jsonrpc-http", server: "jsonrpc-http", publishTo: "nacos")]
class TestService implements TestServiceInterface
{
public function add(int $a, int $b): int
{
return $a + $b;
}
}
项目启动后就会发现已经成功在nacos中注册了服务
消费端
1、创建一个接口 TestServiceInterface.php,这里内容其实和服务端是一模一样的
namespace App\JsonRpc\Iface;
interface TestServiceInterface
{
function add(int $a, int $b);
}
2、调用服务,创建一个IndexController.php
namespace App\Controller;
use App\JsonRpc\Iface\TestServiceInterface;
Hyperf\Di\Annotation\Inject;
#[AutoController]
class IndexController extends AbstractController
{
#[Inject]
private TestServiceInterface $testService;
public function index(){
//下面这种直接从容器中获取的方式也可以
//$client = ApplicationContext::getContainer()->get(TestServiceInterface::class);
//$ret= $client->add(1,2);
$ret = $this->testService->add(1, 2);
var_dump($ret);
}
}
使用json-rpc的方式进行微服务间的接口调用,将跨服务的接口调用变得像直接调用本地方法一样简单。实际测试时发现,中途将nacos服务停止,消费者依然可以正常调用服务,这个应该和java使用nacos作为服务中心的原理一样,即消费端第一次连接nacos成功后会本地缓存nacos中的服务地址信息。