增加 Cluster 支持类。画饼。

This commit is contained in:
iVampireSP.com 2023-01-04 20:18:22 +08:00
parent 8d0c1c2dea
commit 9bd0f11e16
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
6 changed files with 179 additions and 28 deletions

View File

@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands\Cluster;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class Log extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cluster:log';
/**
* The console command description.
*
* @var string
*/
protected $description = '监听集群消息。';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
return CommandAlias::SUCCESS;
}
}

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands\Cluster;
use App\Support\Cluster;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Console\Command\Command as CommandAlias;
use ZipArchive;
@ -45,13 +45,13 @@ public function handle(): int
}
}
$cache_key = "cluster:master_config";
$config = Cache::get($cache_key);
$cache_key = "master_config";
$config = Cluster::get($cache_key);
if ($config) {
$this->info('检查下载目录的 MD5 值。');
$config_md5_key = "cluster:master_config_md5";
$config_md5 = Cache::get($config_md5_key, '');
$config_md5_key = "master_config_md5";
$config_md5 = Cluster::get($config_md5_key, '');
$md5 = md5($config);
if ($md5 !== $config_md5) {
@ -86,11 +86,11 @@ public function handle(): int
if ($node_type === 'slave') {
// 下载 .env 文件
$this->info('正在下载 .env 文件。');
$env_cache_key = "cluster:${node_type}_env";
$env_md5_key = "cluster:${node_type}_env_md5";
$env_cache_key = "${node_type}_env";
$env_md5_key = "${node_type}_env_md5";
$env = Cache::get($env_cache_key);
$env_md5 = Cache::get($env_md5_key);
$env = Cluster::get($env_cache_key);
$env_md5 = Cluster::get($env_md5_key);
$this->info('检查 .env 文件的 MD5 值。');
if (md5($env) !== $env_md5) {

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands\Cluster;
use App\Support\Cluster;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\Console\Command\Command as CommandAlias;
use ZipArchive;
@ -112,26 +112,26 @@ public function upload($node_type)
$this->info('正在上传 config 目录。');
$cache_key = "cluster:${node_type}_config";
Cache::forever($cache_key, file_get_contents($cacheZip));
$cache_key = "${node_type}_config";
Cluster::forever($cache_key, file_get_contents($cacheZip));
// md5
$this->info('正在报告 cache 目录的 MD5 值。');
$cache_md5_key = "cluster:${node_type}_config_md5";
Cache::forever($cache_md5_key, md5_file($cacheZip));
$cache_md5_key = "${node_type}_config_md5";
Cluster::forever($cache_md5_key, md5_file($cacheZip));
unlink($cacheZip);
}
// 上传 .env 文件
$this->info('正在上传 .env 文件。');
$env_key = "cluster:${node_type}_env";
Cache::forever($env_key, file_get_contents(base_path('.env')));
$env_key = "${node_type}_env";
Cluster::forever($env_key, file_get_contents(base_path('.env')));
// 上传 .env 文件的 MD5
$this->info('正在报告 .env 文件的 MD5 值。');
$env_md5_key = "cluster:${node_type}_env_md5";
Cache::forever($env_md5_key, md5_file(base_path('.env')));
$env_md5_key = "${node_type}_env_md5";
Cluster::forever($env_md5_key, md5_file(base_path('.env')));
$this->info('完成。');
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands\Cluster;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class Work extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cluster:work';
/**
* The console command description.
*
* @var string
*/
protected $description = '开始集群协调任务。';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
return CommandAlias::SUCCESS;
}
}

View File

@ -2,8 +2,10 @@
namespace App\Console\Commands;
use App\Support\Cluster;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Str;
use Symfony\Component\Console\Command\Command as CommandAlias;
@ -30,6 +32,11 @@ class Init extends Command
*/
public function handle(): int
{
if (!config('settings.node.ip')) {
$this->error('请先配置节点 IP。');
return CommandAlias::FAILURE;
}
// 重写 .env 文件中的 NODE_ID
$this->info('正在重写 .env 文件中的 NODE_ID。');
@ -45,22 +52,16 @@ public function handle(): int
file_put_contents(base_path('.env'), $env);
if (!config('settings.node.ip')) {
$this->error('请先配置节点 IP。');
return CommandAlias::FAILURE;
}
// 刷新配置缓存
$this->info('正在刷新配置缓存。');
Artisan::call('config:cache');
// redis 创建一个 hash
$this->info('正在创建 Redis hash。');
$redis = app('redis')->connection();
$redis->hset('nodes', $node_id, [
'type' => config('settings.node.type'),
'id' => $node_id,
]);
$this->info('正在注册节点。');
Cluster::registerThisNode();
$this->info('初始化完成。');
return CommandAlias::SUCCESS;
}

84
app/Support/Cluster.php Normal file
View File

@ -0,0 +1,84 @@
<?php
namespace App\Support;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class Cluster
{
public static string $prefix = 'cluster:';
public static function isMaster(): bool
{
return config('settings.node.type') === 'master';
}
public static function isSlave(): bool
{
return config('settings.node.type') === 'slave';
}
public static function isCluster(): bool
{
return self::isMaster() || self::isSlave();
}
public static function publish($event, $data = []): void
{
Redis::publish('cluster_ready', json_encode([
'node' => [
'type' => config('settings.node.type'),
'id' => config('settings.node.id'),
'ip' => config('settings.node.ip'),
],
'data' => $data,
]));
}
public static function hset($key, $value, $data = []): void
{
Redis::hset($key, $value, json_encode($data));
}
public static function get($key, $default = null): string|array|null
{
return Cache::get(self::$prefix . $key, $default);
}
public static function set($key, $value, $ttl = null): void
{
Cache::put(self::$prefix . $key, $value, $ttl);
}
public static function forget($key): void
{
Cache::forget(self::$prefix . $key);
}
// forever
public static function forever($key, $value): void
{
Cache::forever(self::$prefix . $key, $value);
}
public static function hget($key, $value, $default = null): string|array|null
{
return Redis::hget($key, $value, $default);
}
public static function registerThisNode(): void
{
$node_id = config('settings.node.id');
Cluster::hset('nodes', $node_id, [
'type' => config('settings.node.type'),
'id' => $node_id,
'ip' => config('settings.node.ip'),
]);
Cluster::publish('node_init');
}
}