1、apollo上创建项目
输入各项参数,AppId可以使用项目英文,而应用名称可使用项目中文
2、添加需要用到的集群
3、生成秘钥,选择DEV环境的生成并且启用
4、laravel接入apollo,添加apollo的命令与配置
在app/Console/Commands/目录下创建apollo定时任务文件ApolloCommentCount.php,内容如下
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class ApolloCommentCount extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:apollo.sync';
/**
* The console command description.
*
* @var string
*/
protected $description = '阿波罗配置同步';
//AppId
protected $app_id;
//链接
protected $server;
//集群
protected $cluster;
//密钥
protected $secret;
//空间
protected $namespaces;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->app_id = config('apollo.app_id');
$this->server = config('apollo.server');
$this->cluster = config('apollo.cluster');
$this->secret = config('apollo.secret');
$this->namespaces = explode(',', config('apollo.namespace'));
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->doSync();
}
protected function sign($pathWithQuery, $secret, $time)
{
$data = join("\n", [$time, $pathWithQuery]);
$sign = base64_encode(hash_hmac('sha1', $data, $secret, true));
return $sign;
}
protected function doSync()
{
try {
//获取毫秒级时间戳
$time = (string)sprintf('%.0f', microtime('string') * 1000);
$cfgs = [];
foreach ($this->namespaces as $namespace) {
$pathWithQuery = '/configs/' . $this->app_id . '/' . $this->cluster . '/';
$url = $this->server . $pathWithQuery;
$label = $_SERVER['HOSTNAME'] ?? '';
$releaseKey = Redis::get($pathWithQuery . $namespace . $label);
$url = $url . $namespace . '?releaseKey=' . $releaseKey;
$query = $pathWithQuery . $namespace . '?releaseKey=' . $releaseKey;
$sign = $this->sign($query, $this->secret, $time);
$header = [
'Authorization' => 'Apollo ' . $this->app_id . ':' . $sign,
'Timestamp' => $time,
];
$client = new \GuzzleHttp\Client(['timeout' => 3.00, 'headers' => $header]);
$response = $client->request('GET', $url);
$body = json_decode($response->getBody()->getContents(), true);
if ($response->getStatusCode() == 304) {
continue;
}
$releaseKey = Arr::get($body, 'releaseKey', []);
Redis::set($pathWithQuery . $namespace . $label, $releaseKey);
$cfg = Arr::get($body, 'configurations', []);
if (!$cfg) {
continue;
}
$cfgs = array_merge($cfgs, $cfg);
}
if ($cfgs) {
foreach ($_ENV as $key => $value) {
if(isset($cfgs[$key])){
$cfgs[$key] = $cfgs[$key] ?? $_ENV[$key];
}
}
$items = [];
foreach ($cfgs as $key => $value) {
data_set($items, $key, $value);
}
$content = '';
foreach ($items as $k => $item) {
$this->line('Saving [' . $k . ']');
$content .= $k . '=' . $item . "\n";
}
$fileName = '.env';
$fileName_back = '.env_back';
if ($content) {
Storage::disk('env')->put($fileName, $content);
Storage::disk('env')->put($fileName_back, $content);
}
}
} catch (\Exception $ex) {
Log::channel('cron')->error('apollo',[$ex->getMessage()]);
}
}
}
在config/filesystems.php文件中加入env文件配置,在 disks数组中 加入
'env' => [
'driver' => 'local',
'root' => base_path(),
],
在config/logging.php文件中加入cron日志配置
//定时任务的日志配置
'cron' => [
'driver' => 'daily',
'path' => storage_path('logs/cron/cron.log'),
'level' => 'debug',
'days' => 14,
],
在.env文件中加入apollo配置,{}为变量信息,根据实际情况录入
#apollo地址
APOLLO_SERVER={阿波罗地址}
#apollo的appId
APOLLO_APP_ID={阿波罗的AppId}
#apollo的分支
APOLLO_CLUSTER={阿波罗的分支}
#apollo的空间
APOLLO_NAMESPACE={阿波罗的空间}
#apollo的key
APOLLO_SECRET={阿波罗的秘钥}
进入管理秘钥查看秘钥
5、将.env中的配置全部添加到apollo上,可以使用文本形式,更加快捷
发布一下
6、在config目录下添加config文件,内容如下
<?php
return [
'server' => env('APOLLO_SERVER','http://127.0.0.1:8080'),
'app_id' => env('APOLLO_APP_ID','SampleApp'),
'cluster' => env('APOLLO_CLUSTER','dev'),
'namespace' => env('APOLLO_NAMESPACE','application'),
'secret' => env('APOLLO_SECRET'),
];
7、在项目目录下运行命令php artisan command:apollo.sync 即可获取,如果运行报错请查看storage/logs/cron目录下的报错日志, 根据日志调试
这是获取后的数据
8、线上的项目一般都需要实时更新,可以通过定时器来解决,定时运行命令获取配置,docker则进入容器中执行
php artisan command:apollo.sync
一下为进入docker的操作命令
9、补充说明,如果没有.env文件要进行创建,复制一份.env.example文件(laravel自带的),改名为.env,修改配置,再加入apollo信息即可
还有记得配置好redis,因为要用到redis,否则会获取配置失败,并且日志中报Connection refused错误
10、tp框架使用方法差不多,可以在app/command中添加Apollo.php文件实现
<?php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;
use think\facade\Log;
class Apollo extends Command
{
//AppId
protected $app_id;
//链接
protected $server;
//集群
protected $cluster;
//密钥
protected $secret;
//空间
protected $namespaces;
public function __construct()
{
parent::__construct();
$this->app_id = config('apollo.app_id');
$this->server = config('apollo.server');
$this->cluster = config('apollo.cluster');
$this->secret = config('apollo.secret');
$this->namespaces = explode(',', config('apollo.namespace'));
}
protected function configure()
{
// 指令配置
$this->setName('Apollo');
// 设置参数
}
protected function execute(Input $input, Output $output)
{
try {
//获取毫秒级时间戳
$time = (string)sprintf('%.0f', microtime('string') * 1000);
$cfgs = [];
foreach ($this->namespaces as $namespace) {
$pathWithQuery = '/configs/' . $this->app_id . '/' . $this->cluster . '/';
$url = $this->server . $pathWithQuery;
$label = $_SERVER['HOSTNAME'] ?? '';
$releaseKey = Cache::get($pathWithQuery . $namespace . $label);
//$releaseKey = (new \think\cache\driver\Redis)->get($pathWithQuery . $namespace);
$url = $url . $namespace . '?releaseKey=' . $releaseKey;
$query = $pathWithQuery . $namespace . '?releaseKey=' . $releaseKey;
$sign = $this->sign($query, $this->secret, $time);
$header = [
'Authorization:Apollo ' . $this->app_id . ':' . $sign,
'Timestamp:'. $time,
];
$body = $this->get_curl($url,$header);
if ($body['error'] != 200) {
continue;
}
$releaseKey = $body['releaseKey'];
//(new \think\cache\driver\Redis)->set($pathWithQuery . $namespace, $releaseKey);
Cache::set($pathWithQuery . $namespace. $label, $releaseKey,3600);
$cfg = $body['configurations'];
if (!$cfg) {
continue;
}
$cfgs = array_merge($cfgs, $cfg);
}
if ($cfgs) {
foreach ($_ENV as $key => $value) {
$cfgs[$key] = $cfgs[$key] ?? $_ENV[$key];
}
$content = '';
foreach ($cfgs as $k => $item) {
$output->writeln('Saving [' . $k . ']');
$content .= $k . '=' . $item . "\n";
}
$fileName = '.env';
$fileName_back = '.env_back';
if ($content) {
$gao_file = fopen($fileName,"w+");
fwrite($gao_file, $content);
fclose($gao_file);
$gao_file = fopen($fileName_back,"w+");
fwrite($gao_file, $content);
fclose($gao_file);
}
}
} catch (\Exception $ex) {
Log::error('apollo',[$ex->getMessage()]);
}
}
function get_curl($url,$header){
$curl = curl_init(); //初始化curl
curl_setopt($curl, CURLOPT_URL, $url); //抓取指定网页
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
curl_setopt($curl, CURLOPT_TIMEOUT, 30); //超时设置
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
ob_start();
//执行命令
$result = curl_exec($curl);
ob_end_clean();
$return_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$result = json_decode($result, true);
$result['error'] = $return_code;
return $result;
}
protected function sign($pathWithQuery, $secret, $time)
{
$data = join("\n", [$time, $pathWithQuery]);
$sign = base64_encode(hash_hmac('sha1', $data, $secret, true));
return $sign;
}
}