#!/usr/bin/env php '{{REDIS_HOST}}', 'port' => '{{REDIS_PORT}}', 'password' => '{{REDIS_PASSWORD}}', 'prefix' => '{{REDIS_PREFIX}}', ]; /** 好了,不要再编辑了。配置到此为止了。 **/ $nginx_conf = ''; $nginx_file_md5 = ''; $prefix = $redis_info['prefix']; // 检查是否存在配置文件 if (!file_exists($nginx_conf_path)) { echo 'nginx.conf not found'; exit; } else { $nginx_conf = file_get_contents($nginx_conf_path); $nginx_file_md5 = md5_file($nginx_conf_path); } // 检查redis_info是否正确 foreach ($redis_info as $key => $value) { if (empty($value)) { echo "redis_info[$key] is empty"; exit; } } $redis = new Redis(); try { $redis->connect($redis_info['host'], $redis_info['port']); $redis->auth($redis_info['password']); // set db 0 $redis->select(0); } catch (RedisException $e) { echo 'Connection to Redis failed: ' . $e->getMessage(); } try { if ($redis->ping('')) { output('redis is ok'); } } catch (RedisException $e) { output('redis is error'); } // 检验环境 // 检测 Nginx 是否存在 which nginx $nginx_path = trim(shell_exec('which nginx')); if (empty($nginx_path)) { echo 'nginx not found'; redis_publish('edge.error', [ 'message' => '此节点上并没有安装 Nginx ,但是 Edge 被启动了,现在已经退出。', ]); exit; } redis_publish('edge.launched'); $last_run_at = time() - 100; $ip = ''; // 获取本机 IP ifconfig.me $ip = trim(shell_exec('curl -s ifconfig.me')); $run_count = 0; // 逻辑部分 while (true) { if ($run_count >= 10000) { $run_count = 0; // 重新获取 IP $ip = trim(shell_exec('curl -s ifconfig.me')); } redis_hset('nodes', $node_id, [ 'type' => 'edge', 'id' => 'edge-' . $node_id, 'ip' => $ip, // utc +8 timestamp 'last_heartbeat' => time(), ]); // 上次运行时间需要满 60s,才继续,否则 continue if (time() - $last_run_at < 60) { sleep(1); continue; } // 重新载入 nginx.conf if (!file_exists($nginx_conf_path)) { echo 'nginx.conf not found'; redis_publish('edge.error', [ 'message' => 'Nginx 配置文件在启动后被删除,Edge 进程退出。', ]); exit; } else { $nginx_conf = file_get_contents($nginx_conf_path); $nginx_file_md5 = md5_file($nginx_conf_path); } // 检查 laecloud_database_cluster:nodes 是否存在 try { if (!$redis->exists($prefix . 'cluster:nodes')) { output('cluster:nodes not found'); } } catch (RedisException $e) { output('redis is error'); } $nodes = redis_hgetAll('nodes'); if (!$nodes) { output('nodes is empty'); continue; } foreach ($nodes as $node) { // if node last_heartbeat(utc+8 timestamp) is over 10s, skip if (time() - $node['last_heartbeat'] > 10) { // 删除节点 redis_hdel('nodes', $node['id']); } } $conf = ''; foreach ($nodes as $node) { // only allow node type master, slave if (!in_array($node['type'], ['master', 'slave'])) { continue; } output('node_type: ' . $node['type']); output('node_id: ' . $node['id']); output('================================================================'); $temp_conf = "#node {$node['type']}:{$node['id']}\n"; $temp_conf .= "server {$node['ip']}"; if (isset($node['weight'])) { if ($node['weight'] !== '0') { $temp_conf .= " weight={$node['weight']} "; } } else { $temp_conf .= ' weight=1 '; } if ($node['type'] == 'master') { if (count($nodes) <= 2) { $temp_conf .= ' backup '; } } $temp_conf .= ' max_fails=1 fail_timeout=10s '; $temp_conf .= ";\n"; echo $temp_conf . PHP_EOL; output('================================================================'); $conf .= $temp_conf . PHP_EOL; } output('!!!!!!!!!!!!!!!!!'); echo $conf; output('!!!!!!!!!!!!!!!!!'); $add_header = <<get($prefix . 'cluster:' . $key); } catch (RedisException $e) { exit('redis get error: ' . $e->getMessage()); } if (empty($value)) { return $default; } return $value; } function redis_hget($key, $hash_key, $default = null) { global $redis, $prefix; try { $value = $redis->hget($prefix . 'cluster:' . $key, $hash_key); } catch (RedisException $e) { exit('redis get error: ' . $e->getMessage()); } if (empty($value)) { return $default; } return $value; } function redis_hgetAll($key) { global $redis, $prefix; try { $value = $redis->hGetAll($prefix . 'cluster:' . $key); } catch (RedisException $e) { exit('redis get error: ' . $e->getMessage()); } // json_decode all foreach ($value as $k => $v) { $value[$k] = json_decode($v, true); } return $value; } function redis_hset($key, $hash_key, $value) { global $redis, $prefix; try { $redis->hset($prefix . 'cluster:' . $key, $hash_key, json_encode($value)); } catch (RedisException $e) { echo 'redis get error: ' . $e->getMessage(); } } function redis_hdel($key, $hash_key): void { global $redis, $prefix; try { $redis->hdel($prefix . 'cluster:' . $key, $hash_key); } catch (RedisException $e) { echo 'redis get error: ' . $e->getMessage(); } } function redis_publish($event, $message = []): void { global $redis, $prefix, $node_id; $data = [ 'event' => $event, 'node' => [ 'type' => 'edge', 'id' => $node_id, ], 'data' => $message, ]; $data = json_encode($data); try { $redis->publish($prefix . 'cluster_ready', $data); } catch (RedisException $e) { echo 'redis publish error: ' . $e->getMessage(); } }