11、Hyperf 3 微服务系列 - Nacos 集群

作者: 温新

分类: 【Hyperf 3 微服务系列】

阅读: 1723

时间: 2023-05-29 15:22:58

hi,我是温新,一名 PHPer

Hyperf 3 微服务代码已上传至 Github:https://github.com/ziruchu/hyperf3-microservice-code

上篇文章学习了 Nacos 的安装与访问,这篇文章将实现集群的部署。在部署集群之前先了解一上 Nacos 的相关知识。

Nacos 相关知识

命名空间

Nacos 有一个默认的命名空间 public,且不可删除。命名空间用于隔离不同的环境,同语言中的命名空间。

分组

一个命名空间中可以有 N 多个服务,服务多了不太好管理。可以根据不同的服务进行对应的分组。默认分组为 DEFAULT_GROUP

Nacos 集群部署

前情回顾

我们在部署 Consul 集群时的情况如下:

服务器 IP Consul 类型 Node 节点 服务类型
192.168.31.92 server server-01 服务者
192.168.31.93 server server-02 服务者
192.168.31.94 server server-03 服务者
192.168.31.90 client client-01 消费者

现在部署 Nacos 集群,我们同样使用这 4 台服务。92、93、94 这三台服务器上都部署者服务提供者,我们还老套路,复制项目进行改造。

Nacos 集群部署

集群概览

服务器 IP 应用名称 Node 节点 服务类型
192.168.31.92 note_provider_user_9605 server-01 服务者
192.168.31.93 note_provider_user_9606 server-02 服务者
192.168.31.94 note_provider_user_9607 server-03 服务者
192.168.31.90 client client-01 消费者

部署服务提供者

当前位置: 192.168.31.92 服务器下的 note_provider_user_9605 应用

第一步:复制项目
cp -r note_provider_user_9602 note_provider_user_9605

cd note_provider_user_9605
第二步:修改应用名称
// .env 文件
APP_NAME=node_provider_user_9605
第三步:修改服务端口
<?php
// config/autoload/server.php
'servers' => [
    [
        'name' => 'jsonrpc-http',
        'type' => Server::SERVER_HTTP,
        'host' => '0.0.0.0',
        // 修改服务端口为 9605
        'port' => 9605,
        'sock_type' => SWOOLE_SOCK_TCP,
        'callbacks' => [
            Event::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
        ],
    ],
],
第四步:安装 nacos 组件并修改配置

安装 nacos 组件

composer require hyperf/service-governance-nacos

修改 services 配置

<?php
// config/autoload/services.php
return [
    'enable' => [
        'discovery' => true,
        'register' => true,
    ],
    'consumers' => [],
    'providers' => [],
    'drivers' => [
        'nacos' => [
            // nacos server url like https://nacos.hyperf.io, Priority is higher than host:port
            // 'url' => '',
		   // 这个地方需要注意,可能会导致启动失败
            'host' => '192.168.31.90',
            'port' => 8848,
			// 登录 nacos 的账号
            'username' => 'nacos',
            'password' => 'nacos',
            'guzzle' => [
                'config' => null,
            ],
            // 分组
            'group_name' => 'DEFAULT_GROUP',
            // 命名空间 ID
            'namespace_id' => 'hyperf',
            'heartbeat' => 5,
        ],
    ],
];

host 默认值是 127.0.0.1,若是启动失败,修改成 nacos 服务器 IP 地址。

第五步:代码编写

1、UserServiceInterface.php 接口中新增两个用于测试的接口。

<?php
// app/JsonRpc/Interface/UserServiceInterface.php

public function getNacosServerInfo();
public function getServerInfo();

2、实现接口

<?php
// app/JsonRpc/Service/UserService.php
use Hyperf\ServiceGovernanceNacos\Client;
use Hyperf\Utils\Codec\Json;
    
#[RpcService(name: "UserService", protocol: "jsonrpc-http", server: "jsonrpc-http", publishTo: "nacos")]
class UserService implements UserServiceInterface
{
    // 获取 Nacos 注册的所有服务信息
    public function discovery()
    {
        $config      = ApplicationContext::getContainer()->get(ConfigInterface::class);
        $groupName   = $config->get('services.drivers.nacos.group_name');
        $namespaceId = $config->get('services.drivers.nacos.namespace_id');

        $client   = ApplicationContext::getContainer()->get(Client::class);
        $services = Json::decode((string)$client->service->list(1, 10, $groupName, $namespaceId)->getBody());
        $details  = [];
        if (!empty($services['doms'])) {
            $optional = [
                'groupName'   => $groupName,
                'namespaceId' => $namespaceId,
            ];
            foreach ($services['doms'] as $service) {
                $details[] = Json::decode((string)$client->instance->list($service, $optional)->getBody());
            }
        }

        return ResponseTool::success($details);
    }

    // 获取当前服务提供者的名称和端口
    public function getServerInfo()
    {
        $port    = 0;
        $config  = ApplicationContext::getContainer()->get(ConfigInterface::class);
        $servers = $config->get('server.servers');
        $appName = $config->get('app_name');
        foreach ($servers as $k => $server) {
            if ($server['name'] == 'jsonrpc-http') {
                $port = $server['port'];
                break;
            }
        }

        return ResponseTool::success([
            'appName' => $appName,
            'port'    => $port,
        ]);
    }    
}

注意:此时 publishTo 改为了 nacos。把服务发布到 nacos 上去。

此时单个 nacos 服务已经配置好了。

第六步:启动 hyperf

当前启动服务后,我们的服务会被注册的 nacos,打开 nacos web 管理界面,可以看到如下信息:

第七步:测试

我们使用 postman 进行测试。

POST请求 http://192.168.31.92:9605
请求参数
{
    "jsonrpc": "2.0",
    "method": "/user/getServerInfo",
    "params": {
    },
    "id": "",
    "context": []
}
返回结果
{
    "jsonrpc": "2.0",
    "id": "",
    "result": {
        "code": 200,
        "message": "success",
        "data": {
            "appName": "node_provider_user_9605",
            "port": 9605
        }
    },
    "context": []
}

POST请求 http://192.168.31.92:9605
请求参数
{
    "jsonrpc": "2.0",
    "method": "/user/getNacosServerInfo",
    "params": {
    },
    "id": "",
    "context": []
}
返回结果
{
    "jsonrpc": "2.0",
    "id": "",
    "result": {
        "code": 200,
        "message": "success",
        "data": [
            {
                "name": "DEFAULT_GROUP@@UserService",
                "groupName": "DEFAULT_GROUP",
                "clusters": "",
                "cacheMillis": 10000,
                "hosts": [
                    {
                        "instanceId": "192.168.31.92#9605#DEFAULT#DEFAULT_GROUP@@UserService",
                        "ip": "192.168.31.92",
                        "port": 9605,
                        "weight": 1,
                        "healthy": true,
                        "enabled": true,
                        "ephemeral": false,
                        "clusterName": "DEFAULT",
                        "serviceName": "DEFAULT_GROUP@@UserService",
                        "metadata": {
                            "server": "jsonrpc-http",
                            "protocol": "jsonrpc-http",
                            "className": "App\\JsonRpc\\Service\\UserService",
                            "publishTo": "nacos"
                        },
                        "instanceHeartBeatInterval": 5000,
                        "instanceHeartBeatTimeOut": 15000,
                        "ipDeleteTimeout": 30000
                    }
                ],
                "lastRefTime": 1679558634004,
                "checksum": "",
                "allIPs": false,
                "reachProtectionThreshold": false,
                "valid": true
            }
        ]
    },
    "context": []
}

通过测试发现,我们的服务已经跑通。

**集群部署:**我们如法炮制,对 93、94 这两台服务器进行操作,操作步骤从 1~7,这里就不在重复编写了。

集群部署完成后,nacos web 管理界面会看到相关信息,如下:

注意哈:某台服务断开后,健康实例数不会自动更新,刷新手动刷新页面。

消费者使用服务

当前所在位置:192.168.31.90 note_consumer_user_9502

第一步:复制项目
cp -R note_consumer_user_9501 note_consumer_user_9502
    
cd note_consumer_user_9502
第二步:修改应用名称
// .env 文件
APP_NAME=note_consumer_user_9502
第三步:修改服务端口
<?php
// config/autoload/server.php
    
'servers' => [
    [
        'name' => 'http',
        'type' => Server::SERVER_HTTP,
        'host' => '0.0.0.0',
        'port' => 9502,
        'sock_type' => SWOOLE_SOCK_TCP,
        'callbacks' => [
            Event::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
        ],
    ],
],
第四步:安装 nacos 组件并修改配置

安装 nacos 组件

composer require hyperf/service-governance-nacos

修改 services 配置

<?php
// config/autoload/services.php
    
// 服务定义
$services = [
    'UserService' => \App\JsonRpc\Interface\UserServiceInterface::class,
];
return [
    'enable' => [
        'discovery' => true,
        'register' => true,
    ],
    // 服务消费者配置
    'consumers' => value(function () use ($services) {
        $consumers = [];
        foreach ($services as $name => $interface) {
            $consumers[] = [
                'name' => $name,
                'service' => $interface,
                // 负载均衡算法,我们选择轮询
                'load_balancer' => 'round-robin',
                'registry' => [
                    'protocol' => 'nacos',
                    'address' => 'http://127.0.0.1:8848',
                ]
            ];
        }
        return $consumers;
    }),
    // 服务驱动,配置 nacos
    'drivers' => [
        'nacos' => [
            'host' => '127.0.0.1',
            'port' => 8848,
            // 登录 nacos 平台的账户密码
            'username' => 'nacos',
            'password' => 'nacos',
            'guzzle' => [
                'config' => null,
            ],
            // 分组名
            'group_name' => 'DEFAULT_GROUP',
            // 命名空间 id
            'namespace_id' => 'hyperf',
            'heartbeat' => 5,
        ],
    ],
];
第五步:代码编写

1、UserServiceInterface.php 接口中新增两个用于测试的接口。

<?php
// app/JsonRpc/Interface/UserServiceInterface.php
public function getServerInfo();

2、实现接口

<?php
// app/JsonRpc/Service/UserService.php

public function getServerInfo()
{
    return $this->__request(__FUNCTION__);
}

3、控制器调用

<?php
// app/Controller/UserController.php

#[GetMapping('/users/getServerInfo')]
public function getServerInfo()
{
    return ResponseTool::success($this->userService->getServerInfo());
}
第六步:测试

使用 postman 或浏览器进行测试

$ curl http://192.168.31.90:9502/users/getServerInfo
{"code":200,"message":"success","data":{"code":200,"message":"success","data":{"appName":"node_provider_user_9607","port":9605}}}

$ curl http://192.168.31.90:9502/users/getServerInfo
{"code":200,"message":"success","data":{"code":200,"message":"success","data":{"appName":"node_provider_user_9606","port":9605}}}

$ curl http://192.168.31.90:9502/users/getServerInfo
{"code":200,"message":"success","data":{"code":200,"message":"success","data":{"appName":"node_provider_user_9605","port":9605}}}

$ curl http://192.168.31.90:9502/users/getServerInfo
{"code":200,"message":"success","data":{"code":200,"message":"success","data":{"appName":"node_provider_user_9606","port":9605}}}

注意返回的 appName,表示了从哪个服务器返回的数据。

关于使用 Nacos 的服务注册与发现到这里就结束了。

我是温新。

请登录后再评论