🎯 一、架构设计
1.1 配置分层策略
Nacos配置中心
├── 公共配置 (shared)
│ ├── database.properties (数据库配置)
│ ├── redis.properties (Redis配置)
│ ├── aliyun.properties (阿里云服务)
│ └── tencent.properties (腾讯云服务)
├── 环境配置
│ ├── develop (开发环境)
│ ├── test (测试环境)
│ └── production (生产环境)
└── 应用私有配置└── dbb_live_api.properties
1.2 命名空间设计
develop
- 开发环境test
- 测试环境production
- 生产环境
1.3 配置组设计
DEFAULT_GROUP
- 应用基础配置DATABASE_GROUP
- 数据库相关CACHE_GROUP
- 缓存相关THIRD_PARTY_GROUP
- 第三方服务
🔧 二、技术实现方案
2.1 安装Nacos PHP SDK
composer.json添加依赖:
{"require": {"nacos-group/nacos-sdk-php": "^0.2"}
}
2.2 创建Nacos配置文件
创建 config/nacos.php
:
<?phpreturn [// Nacos服务器地址'host' => env('NACOS_HOST', '127.0.0.1'),'port' => env('NACOS_PORT', 8848),// Nacos认证'username' => env('NACOS_USERNAME', 'nacos'),'password' => env('NACOS_PASSWORD', 'nacos'),// 命名空间(环境隔离)'namespace_id' => env('NACOS_NAMESPACE_ID', ''),// 配置组'group' => env('NACOS_GROUP', 'DEFAULT_GROUP'),// 数据ID(配置文件名)'data_ids' => ['app' => env('NACOS_DATA_ID_APP', 'dbb_live_api'),'database' => env('NACOS_DATA_ID_DATABASE', 'database'),'redis' => env('NACOS_DATA_ID_REDIS', 'redis'),'third_party' => env('NACOS_DATA_ID_THIRD_PARTY', 'third_party'),],// 配置格式'format' => env('NACOS_FORMAT', 'properties'), // properties, json, yaml// 是否启用配置监听(热更新)'enable_listener' => env('NACOS_ENABLE_LISTENER', false),// 配置缓存路径'cache_dir' => storage_path('framework/nacos'),// 配置缓存时间(秒)'cache_ttl' => env('NACOS_CACHE_TTL', 300),
];
2.3 创建Nacos服务提供者
创建 app/Providers/NacosServiceProvider.php
:
<?phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;
use Nacos\NacosClient;
use Illuminate\Support\Facades\Cache;class NacosServiceProvider extends ServiceProvider
{/*** Register services.*/public function register(){$this->app->singleton('nacos', function ($app) {return new NacosClient(config('nacos.host'),config('nacos.port'),config('nacos.username'),config('nacos.password'));});}/*** Bootstrap services.*/public function boot(){// 只在非测试环境加载Nacos配置if (!$this->app->runningUnitTests() && env('NACOS_ENABLED', false)) {$this->loadNacosConfig();}}/*** 从Nacos加载配置*/protected function loadNacosConfig(){try {$nacos = $this->app->make('nacos');$dataIds = config('nacos.data_ids');$group = config('nacos.group');$namespaceId = config('nacos.namespace_id');foreach ($dataIds as $key => $dataId) {$cacheKey = "nacos_config_{$key}_{$namespaceId}_{$group}_{$dataId}";// 尝试从缓存获取配置$config = Cache::remember($cacheKey, config('nacos.cache_ttl'), function () use ($nacos, $dataId, $group, $namespaceId) {try {$response = $nacos->getConfig($dataId, $group, $namespaceId);return $this->parseConfig($response);} catch (\Exception $e) {\Log::error("Failed to fetch Nacos config: {$dataId}", ['error' => $e->getMessage()]);return [];}});// 将配置合并到运行时环境$this->mergeConfig($config);}} catch (\Exception $e) {\Log::error('Nacos config loading failed', ['error' => $e->getMessage(),'trace' => $e->getTraceAsString()]);}}/*** 解析配置内容*/protected function parseConfig($content){$format = config('nacos.format');switch ($format) {case 'json':return json_decode($content, true) ?? [];case 'yaml':return yaml_parse($content) ?? [];case 'properties':default:return $this->parseProperties($content);}}/*** 解析properties格式配置*/protected function parseProperties($content){$config = [];$lines = explode("\n", $content);foreach ($lines as $line) {$line = trim($line);if (empty($line) || strpos($line, '#') === 0) {continue;}if (strpos($line, '=') !== false) {list($key, $value) = explode('=', $line, 2);$config[trim($key)] = trim($value);}}return $config;}/*** 合并配置到环境变量*/protected function mergeConfig(array $config){foreach ($config as $key => $value) {// 设置到环境变量putenv("{$key}={$value}");$_ENV[$key] = $value;$_SERVER[$key] = $value;}}
}
2.4 创建Nacos配置管理命令
创建 app/Console/Commands/NacosConfigCommand.php
:
<?phpnamespace App\Console\Commands;use Illuminate\Console\Command;
use Nacos\NacosClient;class NacosConfigCommand extends Command
{protected $signature = 'nacos:config {action} {--data-id=} {--group=} {--content=}';protected $description = 'Nacos配置管理命令';public function handle(){$action = $this->argument('action');switch ($action) {case 'publish':$this->publishConfig();break;case 'get':$this->getConfig();break;case 'delete':$this->deleteConfig();break;case 'sync':$this->syncFromEnv();break;default:$this->error("Unknown action: {$action}");}}/*** 发布配置到Nacos*/protected function publishConfig(){$dataId = $this->option('data-id');$group = $this->option('group') ?? config('nacos.group');$content = $this->option('content');if (!$dataId || !$content) {$this->error('data-id and content are required');return;}try {$nacos = app('nacos');$result = $nacos->publishConfig($dataId,$group,$content,config('nacos.namespace_id'));if ($result) {$this->info("Config published successfully: {$dataId}");} else {$this->error("Failed to publish config: {$dataId}");}} catch (\Exception $e) {$this->error("Error: " . $e->getMessage());}}/*** 获取配置*/protected function getConfig(){$dataId = $this->option('data-id');$group = $this->option('group') ?? config('nacos.group');if (!$dataId) {$this->error('data-id is required');return;}try {$nacos = app('nacos');$config = $nacos->getConfig($dataId,$group,config('nacos.namespace_id'));$this->info("Config content:");$this->line($config);} catch (\Exception $e) {$this->error("Error: " . $e->getMessage());}}/*** 从.env文件同步配置到Nacos*/protected function syncFromEnv(){$envFile = base_path('.env');if (!file_exists($envFile)) {$this->error('.env file not found');return;}$content = file_get_contents($envFile);$this->info('Syncing .env to Nacos...');try {$nacos = app('nacos');$dataId = config('nacos.data_ids.app');$group = config('nacos.group');$result = $nacos->publishConfig($dataId,$group,$content,config('nacos.namespace_id'));if ($result) {$this->info('Sync completed successfully');} else {$this->error('Sync failed');}} catch (\Exception $e) {$this->error("Error: " . $e->getMessage());}}
}
2.5 创建Nacos配置热更新监听器
创建 app/Services/NacosConfigListener.php
:
<?phpnamespace App\Services;use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;class NacosConfigListener
{protected $nacos;protected $listeners = [];public function __construct(){$this->nacos = app('nacos');}/*** 添加配置监听*/public function addListener($dataId, $group, $callback){$this->listeners[] = ['dataId' => $dataId,'group' => $group,'callback' => $callback,'md5' => '',];}/*** 启动配置监听*/public function listen(){while (true) {foreach ($this->listeners as &$listener) {try {$config = $this->nacos->getConfig($listener['dataId'],$listener['group'],config('nacos.namespace_id'));$currentMd5 = md5($config);if ($listener['md5'] !== $currentMd5) {Log::info("Config changed: {$listener['dataId']}");// 调用回调函数call_user_func($listener['callback'], $config);// 更新MD5$listener['md5'] = $currentMd5;// 清除缓存$cacheKey = "nacos_config_{$listener['dataId']}";Cache::forget($cacheKey);}} catch (\Exception $e) {Log::error("Config listener error: {$listener['dataId']}", ['error' => $e->getMessage()]);}}sleep(5); // 5秒轮询一次}}
}
📝 三、配置迁移方案
3.1 配置文件拆分建议
基础应用配置 (dbb_live_api.properties):
# 应用基础配置
APP_NAME=Laravel
APP_ENV=production
APP_DEBUG=false
APP_URL=https://api.example.com
LOG_CHANNEL=daily
LOG_LEVEL=info
TIMEZONE=Asia/Shanghai# JWT配置
JWT_SECRET=your_jwt_secret_here
JWT_ALGO=HS256
JWT_TTL=60
JWT_REFRESH_TTL=20160# 是否上报异常
REPORT_EXCEPTION=true# WebSocket地址
WS_SERVER=ws://127.0.0.1:9502# 是否开启Telescope
TELESCOPE_ENABLED=false# 维护模式
APP_MAINTENANCE=false
APP_MAINTENANCE_PHONE=# 当前服务器标识
CURRENT_SERVER=production-001
数据库配置 (database.properties):
# 主数据库配置
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dbb_live
DB_USERNAME=root
DB_PASSWORD=password
DB_PREFIX=tbl_# 旧数据库配置
DB_CONNECTION_OLD=mysql
DB_HOST_OLD=127.0.0.1
DB_PORT_OLD=3306
DB_DATABASE_OLD=dbb_old
DB_USERNAME_OLD=root
DB_PASSWORD_OLD=password
DB_PREFIX_OLD=tbl_# 用户关注分表配置
USER_FOLLOWER_DB_COUNT=1
USER_FOLLOWER_TABLE_COUNT=200
USER_FOLLOWER_DB_HOST_0=127.0.0.1
USER_FOLLOWER_DB_DATABASE=dbb_shop
USER_FOLLOWER_DB_PORT=3306
USER_FOLLOWER_DB_USERNAME=root
USER_FOLLOWER_DB_PASSWORD=password
USER_FOLLOWER_DB_PREFIX=tbl_
Redis配置 (redis.properties):
# 默认Redis配置
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
CACHE_DRIVER=redis# 直播相关Redis配置
REDIS_LIVE_HOST=127.0.0.1
REDIS_LIVE_USERNAME=null
REDIS_LIVE_PASSWORD=null
REDIS_LIVE_PORT=6379
REDIS_LIVE_CACHE_DB=0# 队列配置
QUEUE_CONNECTION=redis
第三方服务配置 (third_party.properties):
# 阿里云OSS
ALI_ACCESS_KEY_ID=
ALI_ACCESS_SECRET=
ALI_REGION_ID=
OSS_ROLE_ARN=
ALIYUN_OSS_ACCESS_ID=
ALIYUN_OSS_ACCESS_SECRET=
ALIYUN_OSS_ENDPOINT=
ALIYUN_OSS_ACCESS_BUCKET=
ALIYUN_OSS_DOMAIN=# 腾讯云配置
COS_ACCESS_APP_ID=
COS_ACCESS_SECRET_ID=
COS_SECRET_SECRET_KEY=
COS_DEFAULT_REGION=
COS_BUCKET=
COS_URL=# 腾讯IM
IM_SDK_APP_ID=
IM_SECRET_KEY=
IM_IDENTIFIER=
IM_REGION=
IM_CALLBACK_TOKEN=# 腾讯云点播
VOD_SUBAPPID=
VOD_SECRETID=
VOD_SECRETKEY=
VOD_REGION=
VOD_URL=
VOD_DEFINITION=# 腾讯云直播
TENCENTCLOUD_LIVE_SECRETID=
TENCENTCLOUD_LIVE_SECRETKEY=
TENCENTCLOUD_LIVE_APPID=
TENCENTCLOUD_LIVE_BIZID=
TENCENTCLOUD_LIVE_KEY=
TENCENTCLOUD_LIVE_PUSH=
TENCENTCLOUD_LIVE_PULL=
TENCENTCLOUD_LIVE_PUSH_TTL_DAY=7
TENCENTCLOUD_LIVE_TEMPLATE=appauto# 支付相关
PAY_DOMAIN=
PAY_CENTER_KEY=doudie
NOTIFY_COIN_RECHARGE=
PAYMENT_REGISTER_URL=
PAYMENT_DISABLE_URL=
APPLE_URL=https://buy.itunes.apple.com/verifyReceipt
APPLE_PASSWORD=# 短信服务
SMS_ALIYUN_ACCESS_KEY_ID=
SMS_ALIYUN_ACCESS_KEY_SECRET=
SMS_ALIYUN_SIGN_NAME=# ES配置
ES_HOST=
ES_PORT=9200
ES_USERNAME=
ES_PASSWORD=# RabbitMQ配置
RABBITMQ_HOST=
RABBITMQ_PORT=5672
RABBITMQ_USER=
RABBITMQ_PASSWORD=
RABBITMQ_VHOST=/
🚀 四、部署实施步骤
步骤1: 安装Nacos服务器
# 下载Nacos
wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.tar.gz
tar -xvf nacos-server-2.2.3.tar.gz
cd nacos/bin# 单机模式启动
sh startup.sh -m standalone# 访问Nacos控制台
# http://localhost:8848/nacos
# 默认账号密码: nacos/nacos
步骤2: 创建命名空间
登录Nacos控制台,创建三个命名空间:
develop
- 开发环境test
- 测试环境production
- 生产环境
步骤3: 安装PHP依赖
# 进入项目目录
cd c:\Users\DCKJ\Downloads\dbb_live_api-master# 安装Nacos SDK
composer require nacos-group/nacos-sdk-php
步骤4: 创建配置文件
按照上述方案创建以下文件:
config/nacos.php
- Nacos配置app/Providers/NacosServiceProvider.php
- 服务提供者app/Console/Commands/NacosConfigCommand.php
- 管理命令app/Services/NacosConfigListener.php
- 配置监听器
步骤5: 注册服务提供者
修改 config/app.php
:
'providers' => [// ... existing providersApp\Providers\NacosServiceProvider::class,
],
步骤6: 更新.env配置
在.env
文件中添加Nacos相关配置:
# Nacos配置中心
NACOS_ENABLED=true
NACOS_HOST=127.0.0.1
NACOS_PORT=8848
NACOS_USERNAME=nacos
NACOS_PASSWORD=nacos
NACOS_NAMESPACE_ID=production
NACOS_GROUP=DEFAULT_GROUP
NACOS_DATA_ID_APP=dbb_live_api
NACOS_DATA_ID_DATABASE=database
NACOS_DATA_ID_REDIS=redis
NACOS_DATA_ID_THIRD_PARTY=third_party
NACOS_FORMAT=properties
NACOS_ENABLE_LISTENER=false
NACOS_CACHE_TTL=300
步骤7: 同步配置到Nacos
# 同步.env配置到Nacos
php artisan nacos:config sync# 或手动发布配置
php artisan nacos:config publish --data-id=dbb_live_api --content="$(cat .env)"
步骤8: 验证配置加载
# 获取配置
php artisan nacos:config get --data-id=dbb_live_api# 清除配置缓存
php artisan cache:clear# 重启应用
🔍 五、配置管理最佳实践
5.1 配置分级管理
优先级(从高到低):
1. 本地.env文件 (开发调试用)
2. Nacos应用私有配置
3. Nacos环境配置
4. Nacos公共配置
5.2 敏感信息加密
在Nacos中存储敏感信息时,建议使用加密:
创建 app/Services/NacosEncryption.php
:
<?phpnamespace App\Services;class NacosEncryption
{private $key;public function __construct(){$this->key = env('NACOS_ENCRYPTION_KEY', env('APP_KEY'));}public function encrypt($value){return openssl_encrypt($value, 'AES-256-CBC', $this->key, 0, substr($this->key, 0, 16));}public function decrypt($value){return openssl_decrypt($value, 'AES-256-CBC', $this->key, 0, substr($this->key, 0, 16));}
}
5.3 配置变更审计
在Nacos控制台可查看配置变更历史,建议:
- 所有生产配置变更需要审批
- 保留配置变更日志
- 支持配置回滚
5.4 灰度发布策略
// 在NacosServiceProvider中实现灰度逻辑
protected function isGrayRelease()
{$serverName = env('CURRENT_SERVER');$grayServers = explode(',', env('GRAY_SERVERS', ''));return in_array($serverName, $grayServers);
}
📊 六、监控与运维
6.1 健康检查
创建 app/Http/Controllers/HealthController.php
:
<?phpnamespace App\Http\Controllers;use Illuminate\Support\Facades\Cache;class HealthController extends Controller
{public function check(){$status = ['app' => 'ok','nacos' => 'unknown','database' => 'unknown','redis' => 'unknown',];try {// 检查Nacos连接$nacos = app('nacos');$config = $nacos->getConfig(config('nacos.data_ids.app'),config('nacos.group'),config('nacos.namespace_id'));$status['nacos'] = 'ok';} catch (\Exception $e) {$status['nacos'] = 'error: ' . $e->getMessage();}try {// 检查数据库\DB::connection()->getPdo();$status['database'] = 'ok';} catch (\Exception $e) {$status['database'] = 'error';}try {// 检查RedisCache::put('health_check', time(), 10);$status['redis'] = 'ok';} catch (\Exception $e) {$status['redis'] = 'error';}return response()->json($status);}
}
6.2 配置监控脚本
创建 app/Console/Commands/NacosMonitorCommand.php
:
<?phpnamespace App\Console\Commands;use Illuminate\Console\Command;
use App\Services\NacosConfigListener;class NacosMonitorCommand extends Command
{protected $signature = 'nacos:monitor';protected $description = '监听Nacos配置变化';public function handle(){$this->info('Starting Nacos config monitor...');$listener = new NacosConfigListener();// 监听应用配置$listener->addListener(config('nacos.data_ids.app'),config('nacos.group'),function ($config) {$this->info('App config changed, reloading...');// 这里可以执行配置重载逻辑\Artisan::call('config:clear');\Artisan::call('cache:clear');});$listener->listen();}
}
📋 七、回滚方案
如果Nacos出现问题,提供以下回滚策略:
7.1 本地配置降级
在 NacosServiceProvider
中添加降级逻辑:
protected function loadNacosConfig()
{try {// 尝试从Nacos加载$this->fetchFromNacos();} catch (\Exception $e) {\Log::error('Nacos unavailable, fallback to local config');// 降级到本地.env文件$this->loadFromLocalEnv();}
}protected function loadFromLocalEnv()
{$envFile = base_path('.env');if (file_exists($envFile)) {$this->info('Using local .env configuration');// .env已自动加载,无需额外操作}
}
7.2 紧急关闭Nacos
# 在.env中设置
NACOS_ENABLED=false
✅ 八、验收检查清单
📚 九、相关文档
- Nacos官方文档: https://nacos.io/zh-cn/docs/what-is-nacos.html
- nacos-sdk-php: https://github.com/nacos-group/nacos-sdk-php
- Laravel配置管理: https://laravel.com/docs/9.x/configuration