PHP服务注册与发现机制实现在微服务架构中服务实例的动态变化需要服务注册与发现机制。今天说说PHP中实现服务注册与发现的几种方式。基于Redis的服务注册中心是最简单的实现方式。phpclass ServiceRegistry{private Redis $redis;private string $prefix sr:;private int $heartbeatInterval 10;public function __construct(Redis $redis, string $prefix sr:){$this-redis $redis;$this-prefix $prefix;}public function register(string $serviceName, string $host, int $port, array $metadata []): string{$instanceId uniqid({$serviceName}_, true);$instance [id $instanceId,service $serviceName,host $host,port $port,metadata $metadata,status up,registered_at time(),];$key $this-getInstanceKey($serviceName, $instanceId);$this-redis-hMSet($key, $instance);$this-redis-expire($key, $this-heartbeatInterval * 3);$this-redis-sAdd($this-getServiceSetKey($serviceName), $instanceId);return $instanceId;}public function heartbeat(string $serviceName, string $instanceId): bool{$key $this-getInstanceKey($serviceName, $instanceId);if (!$this-redis-exists($key)) return false;$this-redis-expire($key, $this-heartbeatInterval * 3);return true;}public function deregister(string $serviceName, string $instanceId): void{$key $this-getInstanceKey($serviceName, $instanceId);$this-redis-del($key);$this-redis-sRem($this-getServiceSetKey($serviceName), $instanceId);}public function discover(string $serviceName): ?array{$instanceIds $this-redis-sMembers($this-getServiceSetKey($serviceName));if (empty($instanceIds)) return null;$instances [];foreach ($instanceIds as $id) {$key $this-getInstanceKey($serviceName, $id);$data $this-redis-hGetAll($key);if ($data) {$instances[] $data;}}if (empty($instances)) return null;return $instances[array_rand($instances)];}public function discoverAll(string $serviceName): array{$instanceIds $this-redis-sMembers($this-getServiceSetKey($serviceName));$instances [];foreach ($instanceIds as $id) {$key $this-getInstanceKey($serviceName, $id);$data $this-redis-hGetAll($key);if ($data) {$instances[] $data;}}return $instances;}public function getAllServices(): array{$keys $this-redis-keys($this-prefix . set:*);$services [];foreach ($keys as $key) {$name str_replace($this-prefix . set:, , $key);$services[$name] $this-discoverAll($name);}return $services;}private function getInstanceKey(string $service, string $id): string{return {$this-prefix}instance:{$service}:{$id};}private function getServiceSetKey(string $service): string{return {$this-prefix}set:{$service};}}class ServiceProvider{private ServiceRegistry $registry;private string $serviceName;private string $host;private int $port;private string $instanceId;private bool $running false;public function __construct(ServiceRegistry $registry, string $serviceName, string $host, int $port){$this-registry $registry;$this-serviceName $serviceName;$this-host $host;$this-port $port;}public function start(): void{$this-instanceId $this-registry-register($this-serviceName,$this-host,$this-port,[version 1.0, region cn-beijing]);$this-running true;echo 服务 {$this-serviceName} 已注册 (ID: {$this-instanceId})\n;// 启动心跳$this-startHeartbeat();}private function startHeartbeat(): void{while ($this-running) {$this-registry-heartbeat($this-serviceName, $this-instanceId);sleep(5);}}public function stop(): void{$this-running false;$this-registry-deregister($this-serviceName, $this-instanceId);echo 服务 {$this-serviceName} 已注销\n;}}class ServiceConsumer{private ServiceRegistry $registry;private array $cache [];public function __construct(ServiceRegistry $registry){$this-registry $registry;}public function call(string $serviceName, string $path, string $method GET, array $data []): array{$instance $this-getInstance($serviceName);if ($instance null) {throw new RuntimeException(服务不可用: {$serviceName});}$url http://{$instance[host]}:{$instance[port]}{$path};$ch curl_init($url);$options [CURLOPT_RETURNTRANSFER true,CURLOPT_TIMEOUT 5,];if (strtoupper($method) POST) {$options[CURLOPT_POST] true;$options[CURLOPT_POSTFIELDS] json_encode($data);}curl_setopt_array($ch, $options);$response curl_exec($ch);$httpCode curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);return [status $httpCode,body json_decode($response, true) ?? [],instance $instance,];}private function getInstance(string $serviceName): ?array{if (!isset($this-cache[$serviceName]) || rand(0, 9) 0) {$this-cache[$serviceName] $this-registry-discover($serviceName);}return $this-cache[$serviceName];}}?基于文件的服务注册适合小规模部署。phpclass FileServiceRegistry{private string $registryFile;public function __construct(string $registryFile /tmp/service_registry.json){$this-registryFile $registryFile;}private function loadRegistry(): array{if (!file_exists($this-registryFile)) return [];return json_decode(file_get_contents($this-registryFile), true) ?: [];}private function saveRegistry(array $registry): void{file_put_contents($this-registryFile, json_encode($registry, JSON_PRETTY_PRINT), LOCK_EX);}public function register(string $service, string $host, int $port, array $metadata []): void{$registry $this-loadRegistry();$registry[$service][] [host $host,port $port,metadata $metadata,registered_at date(Y-m-d H:i:s),last_heartbeat time(),];$this-saveRegistry($registry);}}?服务注册与发现是微服务的核心基础设施。基于Redis的方案简单高效适合中小规模。大型系统通常用Consul、etcd或ZooKeeper。选择合适的注册中心取决于系统的规模和要求。