   'phpDocumentor\Descriptor\FileDescriptor * hash d378995e60c55cb209433e34cfc27481 * pathProcess/Config.php	 * source&y<?php
/**
 * 配置管理进程类
 *
 * @author camera360_server@camera360.com
 * @copyright Chengdu pinguo Technology Co.,Ltd.
 */

namespace PG\MSF\Process;

use Noodlehaus\Config as Conf;
use PG\MSF\Marco;
use PG\MSF\MSFServer;

/**
 * Class Config
 * @package PG\MSF\Process
 */
class Config extends ProcessBase
{

    /**
     * Redis探测失败次数上限
     */
    const FAILURE_LIMIT = 2;

    /**
     * @var float 上一分钟
     */
    public $lastMinute;

    /**
     * @var array Redis探测retry次数
     */
    protected $redisRetryTimes = [];

    /**
     * Config constructor.
     *
     * @param Conf $config 配置对象
     * @param MSFServer $MSFServer Server运行实例
     */
    public function __construct(Conf $config, MSFServer $MSFServer)
    {
        parent::__construct($config, $MSFServer);
        writeln('Config  Manager: Enabled');
        $this->lastMinute = ceil(time() / 60);
        swoole_timer_tick(3000, [$this, 'checkRedisProxy']);
        swoole_timer_tick(1000, [$this, 'stats']);
    }

    /**
     * 汇总各个Worker的运行状态信息
     */
    public function stats()
    {
        $data = [
            'worker' => [
                // worker进程ID
                // 'pid' => 0,
                // 协程统计信息
                // 'coroutine' => [
                // 当前正在处理的请求数
                // 'total' => 0,
                //],
                // 内存使用
                // 'memory' => [
                // 峰值
                // 'peak'  => '',
                // 当前使用
                // 'usage' => '',
                //],
                // 请求信息
                //'request' => [
                // 当前Worker进程收到的请求次数
                //'worker_request_count' => 0,
                //],
            ],
            'tcp' => [
                // 服务器启动的时间
                'start_time' => '',
                // 当前连接的数量
                'connection_num' => 0,
                // 接受了多少个连接
                'accept_count' => 0,
                // 关闭的连接数量
                'close_count' => 0,
                // 当前正在排队的任务数
                'tasking_num' => 0,
                // Server收到的请求次数
                'request_count' => 0,
                // 消息队列中的Task数量
                'task_queue_num' => 0,
                // 消息队列的内存占用字节数
                'task_queue_bytes' => 0,
            ],
        ];

        $workerIds = range(0, $this->MSFServer->server->setting['worker_num'] - 1);
        foreach ($workerIds as $workerId) {
            $workerInfo = @$this->MSFServer->sysCache->get(Marco::SERVER_STATS . $workerId);
            if ($workerInfo) {
                $data['worker']['worker' . $workerId] = $workerInfo;
            } else {
                $data['worker']['worker' . $workerId] = [];
            }
        }

        $lastStats = $this->MSFServer->sysCache->get(Marco::SERVER_STATS);
        $data['tcp'] = $this->MSFServer->server->stats();
        $data['running']['qps'] = $data['tcp']['request_count'] - $lastStats['tcp']['request_count'];

        if (!isset($lastStats['running']['last_qpm'])) {
            $data['running']['last_qpm'] = 0;
        } else {
            $data['running']['last_qpm'] = $lastStats['running']['last_qpm'];
        }

        if ($this->lastMinute >= ceil(time() / 60)) {
            if (!empty($lastStats) && !isset($lastStats['running']['qpm'])) {
                $lastStats['running']['qpm'] = 0;
            }

            $data['running']['qpm'] = $lastStats['running']['qpm'] + $data['running']['qps'];
        } else {
            if (!empty($lastStats['running']['qpm'])) {
                $data['running']['last_qpm'] = $lastStats['running']['qpm'];
            }
            $data['running']['qpm'] = $data['running']['qps'];
            $this->lastMinute = ceil(time() / 60);
        }

        unset($data['tcp']['worker_request_count']);
        $this->MSFServer->sysCache->set(Marco::SERVER_STATS, $data);
    }

    /**
     * 检测Redis Proxy状态
     *
     * @return bool
     */
    public function checkRedisProxy()
    {
        $host             = gethostname();
        $redisProxyConfig = $this->config->get('redis_proxy', null);
        $redisConfig      = $this->config->get('redis', null);

        if (empty($redisProxyConfig)) {
            return true;
        }

        foreach ($redisProxyConfig as $proxyName => $proxyConfig) {
            if ($proxyName == 'active') {
                continue;
            }

            //分布式
            if ($proxyConfig['mode'] == Marco::CLUSTER) {
                $pools     = $proxyConfig['pools'];
                $goodPools = [];
                foreach ($pools as $pool => $weight) {
                    try {
                        $redis = new \Redis();
                        $redis->connect($redisConfig[$pool]['ip'], $redisConfig[$pool]['port'], 1.5);
                        if ($redis->set('msf_active_cluster_check_' . $host, 1, 3)) {
                            $goodPools[$pool] = $weight;
                        }
                    } catch (\Throwable $e) {
                        $error = $redisConfig[$pool]['ip'] . ':' . $redisConfig[$pool]['port'] . " " . $e->getMessage();
                        $this->MSFServer->log->error($error);
                    }
                    $redis->close();

                    //容忍一定次数的错误重试
                    if (isset($goodPools[$pool])) {
                        $this->redisRetryTimes[$pool] = 0;
                    } else {
                        if (!isset($this->redisRetryTimes[$pool])) {
                            $this->redisRetryTimes[$pool] = 0;
                        }

                        $this->redisRetryTimes[$pool]++;
                        if ($this->redisRetryTimes[$pool] < self::FAILURE_LIMIT) {
                            $goodPools[$pool] = $weight;
                        }
                    }
                }
                $this->MSFServer->sysCache->set($proxyName, $goodPools);
            }

            //主从
            if ($proxyConfig['mode'] == Marco::MASTER_SLAVE) {
                $oldConfig = $this->MSFServer->sysCache->get($proxyName);
                $pools     = $proxyConfig['pools'];
                $master    = '';
                $slaves    = [];
                //主
                foreach ($pools as $pool) {
                    if ($master != '') {
                        break;
                    }

                    try {
                        $redis = new \Redis();
                        $redis->connect($redisConfig[$pool]['ip'], $redisConfig[$pool]['port'], 1.5);
                        if ($redis->set('msf_active_master_slave_check_' . $host, 1, 3)) {
                            $master = $pool;
                        }
                    } catch (\Throwable $e) {
                        //探测主节点时忽略写从的异常信息
                        if (stripos($e->getMessage(), 'readonly') === false) {
                            $error = $redisConfig[$pool]['ip'] . ':' . $redisConfig[$pool]['port'] . ' ' . $e->getMessage();
                            $this->MSFServer->log->error($error);
                        }
                    }
                    $redis->close();
                }

                // 避免主从同步的延迟
                sleep(1);

                //永远不主动踢出master节点
                if ($master != '') {
                    $this->redisRetryTimes[$proxyName] = 0;
                } else {
                    if (!isset($this->redisRetryTimes[$proxyName])) {
                        $this->redisRetryTimes[$proxyName] = 0;
                    }

                    $this->redisRetryTimes[$proxyName]++;
                    $master = $oldConfig['master'] ?? '';
                }

                //从
                if (count($pools) == 1) {
                    $slaves[] = $master;
                    $this->MSFServer->sysCache->set($proxyName, ['master' => $master, 'slaves' => $slaves]);
                    continue;
                }

                foreach ($pools as $pool) {
                    if ($master == $pool) {
                        continue;
                    }

                    try {
                        $redis = new \Redis();
                        $redis->connect($redisConfig[$pool]['ip'], $redisConfig[$pool]['port'], 1.5);
                        if ($redis->get('msf_active_master_slave_check_' . $host) == 1) {
                            $slaves[] = $pool;
                        }
                    } catch (\Throwable $e) {
                        $error = $redisConfig[$pool]['ip'] . ':' . $redisConfig[$pool]['port'] . " " . $e->getMessage();
                        $this->MSFServer->log->error($error);
                    }
                    $redis->close();

                    //容忍一定次数的从节点错误
                    if (in_array($pool, $slaves)) {
                        $this->redisRetryTimes[$pool] = 0;
                    } else {
                        if (!isset($this->redisRetryTimes[$pool])) {
                            $this->redisRetryTimes[$pool] = 0;
                        }
                        $this->redisRetryTimes[$pool]++;
                        if ($this->redisRetryTimes[$pool] < self::FAILURE_LIMIT) {
                            $slaves[] = $pool;
                        }
                    }
                }

                $this->MSFServer->sysCache->set($proxyName, ['master' => $master, 'slaves' => $slaves]);
            }
        }

        return true;
    }
}
 * namespaceAliases#phpDocumentor\Descriptor\Collection * itemsConf\Noodlehaus\ConfigMarco\PG\MSF\Marco	MSFServer\PG\MSF\MSFServer * includes	  * constants	  * functions	 
 * classes	\PG\MSF\Process\Config(phpDocumentor\Descriptor\ClassDescriptor	 * parent\PG\MSF\Process\ProcessBase * implements	  * abstract * final	FAILURE_LIMIT+phpDocumentor\Descriptor\ConstantDescriptor" * types  * value2 * fqsen%\PG\MSF\Process\Config::FAILURE_LIMIT * name * namespace\PG\MSF\Process
 * package
 * summaryRedis探测失败次数上限 * description * fileDescriptor  * line * tags	 	 * errors	  * inheritedElement  * properties	
lastMinute+phpDocumentor\Descriptor\PropertyDescriptor" 
 * default 	 * static * visibilitypublic "\PG\MSF\Process\Config::lastMinute"/# %&() *+	var	 *phpDocumentor\Descriptor\Tag\VarDescriptor * variableName	 -phpDocumentor\Descriptor\Type\FloatDescriptor "6(上一分钟,	 ,	 - redisRetryTimes0" 1array()23	protected '\PG\MSF\Process\Config::redisRetryTimes";# %&() *#+	6	 78	 3phpDocumentor\Descriptor\Type\UnknownTypeDescriptor"array"6(Redis探测retry次数,	 ,	 - 
 * methods	__construct)phpDocumentor\Descriptor\MethodDescriptor"234 * arguments	$config+phpDocumentor\Descriptor\ArgumentDescriptor	 * method"3	 ?"1  * byReference * isVariadic "F# %&(配置对象) * +	 ,	 - 
$MSFServerGH"3	 ?"1 IJ "L# %&(Server运行实例) * +	 ,	 -  %\PG\MSF\Process\Config::__construct()"C# %&Config constructor.() *++	param	 ,phpDocumentor\Descriptor\Tag\ParamDescriptor8F"7"P(K,	 Q8L"?"P(M,	 return	 ,	 - statsD"234E	  \PG\MSF\Process\Config::stats()"S# %&'汇总各个Worker的运行状态信息() *7+	R	 P	 ,	 - checkRedisProxyD"234E	  )\PG\MSF\Process\Config::checkRedisProxy()"V# %&检测Redis Proxy状态() *+	R	 -phpDocumentor\Descriptor\Tag\ReturnDescriptor	 /phpDocumentor\Descriptor\Type\BooleanDescriptor "R(,	 P	 ,	 -  * usedTraits	  "Config#$%PG\MSF\Process&Class Config()" *+	package	 &phpDocumentor\Descriptor\TagDescriptor"_(],	 
subpackage	 ,	 -  * interfaces	 	 * traits	 
 * markers	  "
Config.php# %Default&配置管理进程类() * +	author	 -phpDocumentor\Descriptor\Tag\AuthorDescriptor"h(camera360_server@camera360.com,	 	copyright	 `"k("Chengdu pinguo Technology Co.,Ltd.,	 _	 `"_(f,	 a	 ,	 - 