11、Hyperf 3 微服务系列 - Nacos 集群
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 的服务注册与发现到这里就结束了。
我是温新。