当前位置: 首页 > news >正文

Hyperf方案 服务注册与发现

<?php/** * 案例标题:服务注册与发现 * 说明:基于Consul实现微服务注册、注销和健康检查,服务启动时自动注册,关闭时自动注销 * 需要安装的包: * composer require hyperf/service-governance * composer require hyperf/service-governance-consul * composer require hyperf/guzzle */declare(strict_types=1);// ========== config/autoload/services.php ==========// 服务治理配置,告诉框架用Consul做注册中心return['drivers'=>['consul'=>['uri'=>env('CONSUL_URI','http://127.0.0.1:8500'),// Consul地址],],];// ========== app/Service/ConsulRegistrar.php ==========namespaceApp\Service;useGuzzleHttp\Client;useHyperf\Contract\ConfigInterface;usePsr\Log\LoggerInterface;/** * 手动封装Consul注册逻辑,方便自定义健康检查路径和服务元信息 */classConsulRegistrar{privateClient$http;// HTTP客户端,用来调Consul APIprivatestring$serviceId;// 服务唯一ID,用于注销时找到自己publicfunction__construct(privateConfigInterface$config,privateLoggerInterface$logger){$consulUri=env('CONSUL_URI','http://127.0.0.1:8500');$this->http=newClient(['base_uri'=>$consulUri,'timeout'=>5.0,// 5秒超时,别让注册阻塞太久]);// 服务ID用 服务名-IP-端口 拼,保证同一台机器起多个实例也不冲突$this->serviceId=sprintf('%s-%s-%d',env('SERVICE_NAME','hyperf-app'),$this->getLocalIp(),env('SERVICE_PORT',9501));}/** * 服务启动时调这个,把自己注册到Consul */publicfunctionregister():void{$payload=['ID'=>$this->serviceId,'Name'=>env('SERVICE_NAME','hyperf-app'),// 服务名,同名多个实例会自动负载均衡'Address'=>$this->getLocalIp(),// 服务IP,Consul用这个找你'Port'=>(int)env('SERVICE_PORT',9501),// 监听端口'Tags'=>['hyperf',env('APP_ENV','dev')],// 标签,方便过滤'Meta'=>['version'=>env('APP_VERSION','1.0.0'),// 版本号,灰度发布会用到],'Check'=>[// 健康检查,Consul每隔10秒来戳一下这个HTTP接口'HTTP'=>sprintf('http://%s:%d/health',$this->getLocalIp(),env('SERVICE_PORT',9501)),'Interval'=>'10s',// 检查间隔'Timeout'=>'5s',// 检查超时'DeregisterCriticalServiceAfter'=>'30s',// 连续失败30秒后自动注销,防止僵尸服务],];try{$this->http->put('/v1/agent/service/register',['json'=>$payload,]);$this->logger->info("服务注册成功",['service_id'=>$this->serviceId]);}catch(\Exception$e){// 注册失败只记日志,不影响服务正常启动$this->logger->error("服务注册失败: ".$e->getMessage());}}/** * 服务停止时调这个,主动从Consul摘掉自己 * 不主动注销的话要等健康检查失败才能自动清掉,有延迟 */publicfunctionderegister():void{try{$this->http->put("/v1/agent/service/deregister/{$this->serviceId}");$this->logger->info("服务注销成功",['service_id'=>$this->serviceId]);}catch(\Exception$e){$this->logger->error("服务注销失败: ".$e->getMessage());}}/** * 发现某个服务的所有健康实例,返回地址列表 * 调用其他微服务前先来这里查一下地址 */publicfunctiondiscover(string$serviceName):array{try{$response=$this->http->get("/v1/health/service/{$serviceName}",['query'=>['passing'=>true],// 只返回健康的实例]);$services=json_decode($response->getBody()->getContents(),true);// 把Consul返回的数据整理成简洁的地址列表returnarray_map(function($item){return['address'=>$item['Service']['Address'],'port'=>$item['Service']['Port'],'version'=>$item['Service']['Meta']['version']??'unknown',];},$services);}catch(\Exception$e){$this->logger->error("服务发现失败: ".$e->getMessage());return[];}}/** * 获取本机内网IP,注册到Consul的地址 */privatefunctiongetLocalIp():string{// 先看环境变量有没有手动配,Docker里容器IP不一定准if($ip=env('SERVICE_HOST','')){return$ip;}// 没配就自动取,获取eth0或第一个非回环地址$ip=gethostbyname(gethostname());return$ip?:'127.0.0.1';}}// ========== app/Listener/RegisterServiceListener.php ==========namespaceApp\Listener;useApp\Service\ConsulRegistrar;useHyperf\Event\Contract\ListenerInterface;useHyperf\Framework\Event\MainWorkerStart;/** * 监听Worker启动事件,主Worker起来就注册服务 */classRegisterServiceListenerimplementsListenerInterface{publicfunction__construct(privateConsulRegistrar$registrar){}publicfunctionlisten():array{return[MainWorkerStart::class];// 只在主Worker启动时注册一次}publicfunctionprocess(object$event):void{$this->registrar->register();// 服务启动,去Consul报到}}
http://www.jsqmd.com/news/589154/

相关文章:

  • 天玑学堂Agent面试总结(一)「持续更新」
  • 2026年超火!这款大家都在玩的游戏,究竟有何独特魅力?
  • PID控制理论详解
  • Hyperf方案 Docker容器化部署
  • # MAUI 中的异步加载优化实战:从理论到高性能 UI 体验提升在现代跨平台移动开发中,*
  • Python flask django高校学生综合医疗健康服务管理系统设计与实现
  • 多核通信中的环形缓冲区设计与实现
  • 嵌入式R-Tree空间索引:轻量级矩形碰撞检测与地理围栏实现
  • Windows下OpenClaw安装避坑指南:Qwen3.5-9B-AWQ-4bit联调实录
  • STLink与STM8/32单片机连接与调试指南
  • 修改docker镜像源
  • VoltLora库详解:RYLR998 LoRa模块AT命令驱动实践
  • 程序员副业全攻略:从技术到变现
  • 嵌入式系统架构设计:从前后台到RTOS的实践指南
  • 【源码深度】Android 触摸事件分发机制全解析|吃透 dispatch、intercept、onTouchEvent 与滑动冲突|Android全栈体系150讲-09
  • OpenClaw内存优化技巧:Phi-3-vision-128k-instruct大模型加载的资源配置
  • OpenClaw+千问3.5-9B:自动化学术论文阅读助手
  • Spring Security 2026 最佳实践:构建安全可靠的应用系统
  • 支持安卓的可行性与方向 | Swift 周报 issue 81
  • 电子元器件失效机理与预防全解析
  • OpenClaw调试指南:解决Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF模型响应超时问题
  • Java 设计模式在 Spring 中的现代应用:构建优雅的企业级应用
  • OpenClaw开源贡献:为Qwen3-4B开发新技能并提交社区
  • 解决《十字军之王II》中文显示难题:双字节字符补丁全攻略
  • Android SPI CAN管理芯片适配
  • 单片机产品设计全流程与实战经验分享
  • SEO网站页面优化的常见问题有什么_SEO网站页面优化的步骤是什么
  • ViT推理超快
  • 3个颠覆式创新:抖音批量下载工具如何解决内容采集效率难题
  • PinButtonEvents:嵌入式按钮事件处理框架深度解析