Home >PHP Framework >Laravel >About Nacos solving configuration switching in laravel multiple environments

About Nacos solving configuration switching in laravel multiple environments

藏色散人
藏色散人forward
2021-02-19 17:03:343370browse

The following column will introduce you to Nacos’s method of solving laravel configuration switching in multiple environments from the Laravel Tutorial column. I hope it will be helpful to friends in need!

Preface

For the environment in which the application runs, it is often useful to have different configurations for different environments. For example, you may want to use a different cache driver locally than the one used by the production server.

Pain Point

  • .env The configuration cannot distinguish between multiple environments (development, testing, production)
  • .env Configuration sharing is too troublesome (team LAN environment)
  • Configuration cannot be managed in real time, configuration additions, deletions and modifications

  • Automated deployment configuration The .env file is too cumbersome

Nacos Introduction

Nacos is Alibaba’s latest open source project. Its core positioning is “an easier-to-use Help build a dynamic service discovery, configuration and service management platform for cloud native applications", project address: nacos.io/zh-cn/

Application

Mainly used here The configuration management of Nacos is done, and functions such as dynamic services are not used. The principle is also very simple, directly modify the .env file through the interface. The Nacos service can be directly used using the Application Configuration Management provided by Alibaba Cloud, without installation. The link is as follows: acmnext.console.aliyun.com/

Code

<?php

namespace App\Console\Commands;use GuzzleHttp\Client;use Illuminate\Console\Command;use Illuminate\Support\Facades\Artisan;use Illuminate\Support\Facades\Validator;class NacosTools extends Command{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = &#39;nacos {action?}&#39;;

    private $accessKey;
    private $secretKey;
    private $endpoint = &#39;acm.aliyun.com&#39;;
    private $namespace;
    private $dataId;
    private $group;
    private $port = 8080;
    private $client;

    private $serverUrl;

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = &#39;Nacos 管理工具&#39;;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     * @throws \Exception
     */
    public function handle()
    {
        $this->accessKey = env('NACOS_ACCESS_KEY');
        $this->secretKey = env('NACOS_SECRET_KEY');
        $this->endpoint = env('NACOS_ENDPOINT');
        $this->namespace = env('NACOS_NAMESPACE');
        $this->port = env('NACOS_PORT', $this->port);
        $this->dataId = env('NACOS_DATA_ID');
        $this->group = env('NACOS_GROUP');

        if (!$this->validate()) {
            $this->error('请检查配置参数');

            return;
        }

        $this->client = new Client(['verify' => false]);

        $this->info('Nacos 配置工具');

        $actions = [
            '获取配置',
            '发布配置',
            '删除配置',
        ];

        if (is_null($this->argument('action'))) {
            $action = $this->choice('请选择操作',
                $actions,
                $actions[0]);
        } else {
            if (in_array($this->argument('action'), array_keys($actions))) {
                $action = $actions[$this->argument('action')];
            } else {
                $action = $this->choice('请选择操作',
                    $actions,
                    $actions[0]);
            }
        }

        $this->do($action);
    }

    public function do($action = '获取配置')
    {
        switch ($action) {
            default:
            case '获取配置':
                $config = $this->getConfig();

                if ($config) {
                    file_put_contents('.env', $config);
                    $this->info('获取配置成功');
                } else {
                    $this->error('获取配置失败');
                }

                break;
            case '发布配置':
                if ($this->publishConfig()) {
                    $this->info('发布配置成功');
                } else {
                    $this->error('发布配置失败');
                }

                break;

            case '删除配置':
                if ($this->removeConfig()) {
                    $this->info('删除配置成功');
                } else {
                    $this->error('删除配置失败');
                }

                break;
        }
    }

    /**
     * 验证配置参数
     *
     * Date: 2020/6/10
     * @return bool
     */
    private function validate()
    {
        $data = [
            'accessKey' => $this->accessKey,
            'secretKey' => $this->secretKey,
            'endpoint'  => $this->endpoint,
            'namespace' => $this->namespace,
            'dataId'    => $this->dataId,
            'group'     => $this->group,
        ];

        $rules = [
            'accessKey' => 'required',
            'secretKey' => 'required',
            'endpoint'  => 'required',
            'namespace' => 'required',
            'dataId'    => 'required',
            'group'     => 'required',
        ];

        $messages = [
            'accessKey.required' => '请填写`.env`配置 NACOS_ACCESS_KEY',
            'secretKey.required' => '请填写`.env`配置 NACOS_SECRET_KEY',
            'endpoint.required'  => '请填写`.env`配置 NACOS_ENDPOINT',
            'namespace.required' => '请填写`.env`配置 NACOS_NAMESPACE',
            'dataId.required'    => '请填写`.env`配置 NACOS_DATA_ID',
            'group.required'     => '请填写`.env`配置 NACOS_GROUP',
        ];

        $validator = Validator::make($data, $rules, $messages);

        if ($validator->fails()) {
            foreach ($validator->getMessageBag()->toArray() as $item) {
                foreach ($item as $value) {
                    $this->error($value);
                }
            }

            return false;
        }

        return true;
    }

    /**
     * 获取配置
     *
     * Date: 2020/6/10
     * @return bool
     */
    private function getConfig()
    {
        $acmHost = str_replace(['host', 'port'], [$this->getServer(), $this->port],
            'http://host:port/diamond-server/config.co');

        $query = [
            'dataId' => urlencode($this->dataId),
            'group'  => urlencode($this->group),
            'tenant' => urlencode($this->namespace),
        ];

        $headers = $this->getHeaders();

        $response = $this->client->get($acmHost, [
            'headers' => $headers,
            'query'   => $query,
        ]);

        if ($response->getReasonPhrase() == 'OK') {
            return $response->getBody()->getContents();
        } else {
            return false;
        }
    }

    /**
     * 发布配置
     *
     * Date: 2020/6/10
     * @return bool
     */
    public function publishConfig()
    {
        $acmHost = str_replace(
            ['host', 'port'],
            [$this->getServer(), $this->port],
            'http://host:port/diamond-server/basestone.do?method=syncUpdateAll');

        $headers = $this->getHeaders();

        $formParams = [
            'dataId'  => urlencode($this->dataId),
            'group'   => urlencode($this->group),
            'tenant'  => urlencode($this->namespace),
            'content' => file_get_contents('.env'),
        ];

        $response = $this->client->post($acmHost, [
            'headers'     => $headers,
            'form_params' => $formParams,
        ]);

        $result = json_decode($response->getBody()->getContents(), 1);

        return $result['message'] == 'OK';
    }

    public function removeConfig()
    {
        $acmHost = str_replace(['host', 'port'], [$this->getServer(), $this->port],
            'http://host:port/diamond-server//datum.do?method=deleteAllDatums');

        $headers = $this->getHeaders();

        $formParams = [
            'dataId' => urlencode($this->dataId),
            'group'  => urlencode($this->group),
            'tenant' => urlencode($this->namespace),
        ];

        $response = $this->client->post($acmHost, [
            'headers'     => $headers,
            'form_params' => $formParams,
        ]);

        $result = json_decode($response->getBody()->getContents(), 1);

        return $result['message'] == 'OK';
    }

    /**
     * 获取配置服务器地址
     *
     * Date: 2020/6/10
     * @return string
     */
    private function getServer()
    {
        if ($this->serverUrl) {
            return $this->serverUrl;
        }

        $serverHost = str_replace(
            ['host', 'port'],
            [$this->endpoint, $this->port],
            'http://host:port/diamond-server/diamond');

        $response = $this->client->get($serverHost);

        return $this->serverUrl = rtrim($response->getBody()->getContents(), PHP_EOL);
    }

    /**
     * 获取请求头
     *
     * Date: 2020/6/10
     * @return array
     */
    private function getHeaders()
    {
        $headers = [
            'Diamond-Client-AppName' => 'ACM-SDK-PHP',
            'Client-Version'         => '0.0.1',
            'Content-Type'           => 'application/x-www-form-urlencoded; charset=utf-8',
            'exConfigInfo'           => 'true',
            'Spas-AccessKey'         => $this->accessKey,
            'timeStamp'              => round(microtime(true) * 1000),
        ];

        $headers['Spas-Signature'] = $this->getSign($headers['timeStamp']);

        return $headers;
    }

    /**
     * 获取签名
     *
     * @param $timeStamp
     * Date: 2020/6/10
     * @return string
     */
    private function getSign($timeStamp)
    {
        $signStr = $this->namespace.'+';

        if (is_string($this->group)) {
            $signStr .= $this->group."+";
        }

        $signStr = $signStr.$timeStamp;

        return base64_encode(hash_hmac(
            'sha1',
            $signStr,
            $this->secretKey,
            true
        ));
    }}

Usage example

  1. Register an account , I won’t talk about opening services
  2. .env Add configuration itemsNACOS_ACCESS_KEY NACOS_SECRET_KEY etc.
  3. php artisan nacos 0 Get configuration
  4. php artisan nacos 1 Publish configuration
  5. php artisan nacos 2 Delete configuration

##Configuration item description
NACOS_ENDPOINT= #nacos节点 如使用阿里云服务 即:acm.aliyun.comNACOS_DATA_ID= #项目ID 可以填项目名NACOS_GROUP= #分组ID 这里可以用于区分环境 建议 local production test 等值NACOS_NAMESPACE= # 命名空间 建议用来区分服务器 server-A server-BNACOS_ACCESS_KEY= #阿里云access_key 建议使用子账号access_keyNACOS_SECRET_KEY= #阿里云secret_key 建议使用子账号secret_key

Summary

After using nacos, you no longer have to worry about

.env.example Forgetting to add configuration items, shared configuration is not a trouble, and automatic deployment is not Frequent configuration changes are required.                     

The above is the detailed content of About Nacos solving configuration switching in laravel multiple environments. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete