hyperf中结合nacos实现微服务的调用

57 阅读1分钟

安装依赖

由于使用的是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中注册了服务 image.png

消费端

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中的服务地址信息。