mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-11-30 02:37:58 +08:00
commit
339ecd9e2e
@ -1,5 +1,15 @@
|
||||
# v2.0.9 - TBD
|
||||
|
||||
## Added
|
||||
|
||||
- [#2331](https://github.com/hyperf/hyperf/pull/2331) Added auth api for nacos.
|
||||
- [#2331](https://github.com/hyperf/hyperf/pull/2331) Added config nacos.enable to control the nacos component.
|
||||
- [#2331](https://github.com/hyperf/hyperf/pull/2331) Added array merge mode for nacos.
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#2331](https://github.com/hyperf/hyperf/pull/2331) Fixed exception thrown when the service or config was not found for nacos.
|
||||
|
||||
# v2.0.8 - 2020-08-24
|
||||
|
||||
## Added
|
||||
|
@ -9,10 +9,17 @@ declare(strict_types=1);
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Nacos\Constants;
|
||||
|
||||
return [
|
||||
'enable' => true,
|
||||
// The nacos host info
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 8848,
|
||||
// The nacos account info
|
||||
'username' => null,
|
||||
'password' => null,
|
||||
'config_merge_mode' => Constants::CONFIG_MERGE_OVERWRITE,
|
||||
// The service info.
|
||||
'service' => [
|
||||
'service_name' => 'hyperf',
|
||||
|
@ -15,10 +15,12 @@ use GuzzleHttp\Client;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
use Hyperf\Guzzle\ClientFactory;
|
||||
use Hyperf\Guzzle\CoroutineHandler;
|
||||
|
||||
abstract class AbstractNacos
|
||||
{
|
||||
use AccessToken;
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
@ -29,14 +31,22 @@ abstract class AbstractNacos
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $container->get(ConfigInterface::class);
|
||||
$this->handler = new CoroutineHandler();
|
||||
}
|
||||
|
||||
public function request($method, $uri, array $options = [])
|
||||
{
|
||||
$token = $this->getAccessToken();
|
||||
$token && $options[RequestOptions::QUERY]['accessToken'] = $token;
|
||||
return $this->client()->request($method, $uri, $options);
|
||||
}
|
||||
|
||||
@ -51,10 +61,10 @@ abstract class AbstractNacos
|
||||
|
||||
public function client(): Client
|
||||
{
|
||||
$factory = $this->container->get(ClientFactory::class);
|
||||
$headers['charset'] = $headers['charset'] ?? 'UTF-8';
|
||||
return $factory->create([
|
||||
return new Client([
|
||||
'base_uri' => $this->getServerUri(),
|
||||
'handler' => $this->handler,
|
||||
RequestOptions::HEADERS => [
|
||||
'charset' => 'UTF-8',
|
||||
],
|
||||
|
48
src/nacos/src/Api/AccessToken.php
Normal file
48
src/nacos/src/Api/AccessToken.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Nacos\Api;
|
||||
|
||||
trait AccessToken
|
||||
{
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $accessToken;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $expireTime = 0;
|
||||
|
||||
public function getAccessToken(): ?string
|
||||
{
|
||||
$username = $this->config->get('nacos.username');
|
||||
$password = $this->config->get('nacos.password');
|
||||
|
||||
if ($username === null || $password === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->accessToken) && $this->expireTime > time() + 60) {
|
||||
return $this->accessToken;
|
||||
}
|
||||
|
||||
$api = $this->container->get(NacosAuth::class);
|
||||
|
||||
$result = $api->login($username, $password);
|
||||
|
||||
$this->accessToken = $result['accessToken'];
|
||||
$this->expireTime = $result['tokenTtl'] + time();
|
||||
|
||||
return $this->accessToken;
|
||||
}
|
||||
}
|
36
src/nacos/src/Api/NacosAuth.php
Normal file
36
src/nacos/src/Api/NacosAuth.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Nacos\Api;
|
||||
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Hyperf\Nacos\Exception\RequestException;
|
||||
use Hyperf\Utils\Codec\Json;
|
||||
|
||||
class NacosAuth extends AbstractNacos
|
||||
{
|
||||
public function login(string $username, string $password): array
|
||||
{
|
||||
$response = $this->client()->request('POST', '/nacos/v1/auth/users/login', [
|
||||
RequestOptions::QUERY => [
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
],
|
||||
]);
|
||||
|
||||
$statusCode = $response->getStatusCode();
|
||||
$contents = $response->getBody()->getContents();
|
||||
if ($statusCode !== 200) {
|
||||
throw new RequestException($contents, $statusCode);
|
||||
}
|
||||
return Json::decode($contents);
|
||||
}
|
||||
}
|
@ -23,7 +23,13 @@ class NacosConfig extends AbstractNacos
|
||||
RequestOptions::QUERY => $configModel->toArray(),
|
||||
]);
|
||||
|
||||
return $configModel->parse($response->getBody()->getContents());
|
||||
$statusCode = $response->getStatusCode();
|
||||
$contents = $response->getBody()->getContents();
|
||||
if ($statusCode !== 200) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $configModel->parse($contents);
|
||||
}
|
||||
|
||||
public function set(ConfigModel $configModel): array
|
||||
|
@ -77,7 +77,7 @@ class NacosInstance extends AbstractNacos
|
||||
return false;
|
||||
}
|
||||
$enabled = array_filter($instance, function ($item) {
|
||||
return $item['enabled'];
|
||||
return $item['enabled'] && $item['healthy'];
|
||||
});
|
||||
|
||||
$tactics = strtolower($this->config->get('nacos.load_balancer', 'random'));
|
||||
|
@ -12,8 +12,10 @@ declare(strict_types=1);
|
||||
namespace Hyperf\Nacos\Api;
|
||||
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Hyperf\Nacos\Exception\RequestException;
|
||||
use Hyperf\Nacos\Model\ServiceModel;
|
||||
use Hyperf\Utils\Codec\Json;
|
||||
use Hyperf\Utils\Str;
|
||||
|
||||
class NacosService extends AbstractNacos
|
||||
{
|
||||
@ -44,13 +46,23 @@ class NacosService extends AbstractNacos
|
||||
return $response->getBody()->getContents() === 'ok';
|
||||
}
|
||||
|
||||
public function detail(ServiceModel $serviceModel): array
|
||||
public function detail(ServiceModel $serviceModel): ?array
|
||||
{
|
||||
$response = $this->request('GET', '/nacos/v1/ns/service', [
|
||||
RequestOptions::QUERY => $serviceModel->toArray(),
|
||||
]);
|
||||
|
||||
return Json::decode($response->getBody()->getContents());
|
||||
$statusCode = $response->getStatusCode();
|
||||
$contents = $response->getBody()->getContents();
|
||||
if ($statusCode !== 200) {
|
||||
if (Str::contains($contents, 'is not found')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new RequestException($contents, $statusCode);
|
||||
}
|
||||
|
||||
return Json::decode($contents);
|
||||
}
|
||||
|
||||
public function list(int $pageNo, int $pageSize = 10, ?string $groupName = null, ?string $namespaceId = null): array
|
||||
|
@ -84,6 +84,8 @@ class FetchConfigProcess extends AbstractProcess
|
||||
public function isEnable($server): bool
|
||||
{
|
||||
$config = $this->container->get(ConfigInterface::class);
|
||||
return $server instanceof Server && (bool) $config->get('nacos.config_reload_interval', false);
|
||||
return $server instanceof Server
|
||||
&& $config->get('nacos.enable', true)
|
||||
&& (bool) $config->get('nacos.config_reload_interval', false);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ namespace Hyperf\Nacos\Config;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Framework\Event\OnPipeMessage;
|
||||
use Hyperf\Nacos\Constants;
|
||||
use Hyperf\Process\Event\PipeMessage as UserProcessPipMessage;
|
||||
use Hyperf\Utils\Arr;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class OnPipeMessageListener implements ListenerInterface
|
||||
@ -49,7 +51,11 @@ class OnPipeMessageListener implements ListenerInterface
|
||||
if (property_exists($event, 'data') && $event->data instanceof PipeMessage) {
|
||||
$root = $this->config->get('nacos.config_append_node');
|
||||
foreach ($event->data->configurations ?? [] as $key => $conf) {
|
||||
$this->config->set($root ? $root . '.' . $key : $key, $conf);
|
||||
$configKey = $root ? $root . '.' . $key : $key;
|
||||
if (is_array($conf) && $this->config->get('nacos.config_merge_mode') == Constants::CONFIG_MERGE_APPEND) {
|
||||
$conf = Arr::merge($this->config->get($configKey, []), $conf);
|
||||
}
|
||||
$this->config->set($configKey, $conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
src/nacos/src/Constants.php
Normal file
19
src/nacos/src/Constants.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Nacos;
|
||||
|
||||
class Constants
|
||||
{
|
||||
const CONFIG_MERGE_OVERWRITE = 1;
|
||||
|
||||
const CONFIG_MERGE_APPEND = 2;
|
||||
}
|
16
src/nacos/src/Exception/RequestException.php
Normal file
16
src/nacos/src/Exception/RequestException.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Nacos\Exception;
|
||||
|
||||
class RequestException extends RuntimeException
|
||||
{
|
||||
}
|
@ -18,9 +18,11 @@ use Hyperf\Framework\Event\MainWorkerStart;
|
||||
use Hyperf\Nacos\Api\NacosInstance;
|
||||
use Hyperf\Nacos\Api\NacosService;
|
||||
use Hyperf\Nacos\Client;
|
||||
use Hyperf\Nacos\Constants;
|
||||
use Hyperf\Nacos\Exception\RuntimeException;
|
||||
use Hyperf\Nacos\Instance;
|
||||
use Hyperf\Nacos\Service;
|
||||
use Hyperf\Utils\Arr;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class MainWorkerStartListener implements ListenerInterface
|
||||
@ -55,27 +57,39 @@ class MainWorkerStartListener implements ListenerInterface
|
||||
if (! $config->get('nacos')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nacosService = $this->container->get(NacosService::class);
|
||||
$service = $this->container->get(Service::class);
|
||||
$exist = $nacosService->detail($service);
|
||||
if (! $exist && ! $nacosService->create($service)) {
|
||||
throw new RuntimeException(sprintf('nacos register service fail: %s', $service));
|
||||
if (! $config->get('nacos.enable', true)) {
|
||||
return;
|
||||
}
|
||||
$this->logger->info('nacos register service success.', compact('service'));
|
||||
|
||||
$instance = $this->container->get(Instance::class);
|
||||
$nacosInstance = $this->container->get(NacosInstance::class);
|
||||
if (! $nacosInstance->register($instance)) {
|
||||
throw new RuntimeException(sprintf('nacos register instance fail: %s', $instance));
|
||||
}
|
||||
$this->logger->info('nacos register instance success.', compact('instance'));
|
||||
try {
|
||||
$nacosService = $this->container->get(NacosService::class);
|
||||
$service = $this->container->get(Service::class);
|
||||
$exist = $nacosService->detail($service);
|
||||
if (! $exist && ! $nacosService->create($service)) {
|
||||
throw new RuntimeException(sprintf('nacos register service fail: %s', $service));
|
||||
}
|
||||
$this->logger->info('nacos register service success.', compact('service'));
|
||||
|
||||
$client = $this->container->get(Client::class);
|
||||
$config = $this->container->get(ConfigInterface::class);
|
||||
$appendNode = $config->get('nacos.config_append_node');
|
||||
foreach ($client->pull() as $key => $conf) {
|
||||
$config->set($appendNode ? $appendNode . '.' . $key : $key, $conf);
|
||||
$instance = $this->container->get(Instance::class);
|
||||
$nacosInstance = $this->container->get(NacosInstance::class);
|
||||
if (! $nacosInstance->register($instance)) {
|
||||
throw new RuntimeException(sprintf('nacos register instance fail: %s', $instance));
|
||||
}
|
||||
$this->logger->info('nacos register instance success.', compact('instance'));
|
||||
|
||||
$client = $this->container->get(Client::class);
|
||||
$config = $this->container->get(ConfigInterface::class);
|
||||
$appendNode = $config->get('nacos.config_append_node');
|
||||
|
||||
foreach ($client->pull() as $key => $conf) {
|
||||
$configKey = $appendNode ? $appendNode . '.' . $key : $key;
|
||||
if (is_array($conf) && $config->get('nacos.config_merge_mode') == Constants::CONFIG_MERGE_APPEND) {
|
||||
$conf = Arr::merge($config->get($configKey, []), $conf);
|
||||
}
|
||||
$config->set($configKey, $conf);
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logger->critical((string) $exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ class OnShutdownListener implements ListenerInterface
|
||||
public function process(object $event)
|
||||
{
|
||||
$config = $this->container->get(ConfigInterface::class);
|
||||
if (! $config->get('nacos.enable', true)) {
|
||||
return;
|
||||
}
|
||||
if (! $config->get('nacos.remove_node_when_server_shutdown', false)) {
|
||||
return;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class InstanceBeatProcess extends AbstractProcess
|
||||
sleep($config->get('nacos.client.beat_interval', 5));
|
||||
$send = $nacosInstance->beat($service, $instance);
|
||||
if ($send) {
|
||||
$logger && $logger->info('nacos send beat success!', compact('instance'));
|
||||
$logger && $logger->debug('nacos send beat success!', compact('instance'));
|
||||
} else {
|
||||
$logger && $logger->error('nacos send beat fail!', compact('instance'));
|
||||
}
|
||||
@ -47,6 +47,6 @@ class InstanceBeatProcess extends AbstractProcess
|
||||
public function isEnable($server): bool
|
||||
{
|
||||
$config = $this->container->get(ConfigInterface::class);
|
||||
return $config->get('nacos.client.beat_enable', false);
|
||||
return $config->get('nacos.enable', true) && $config->get('nacos.client.beat_enable', false);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user