ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Hyperf 服务注册指南:基于 Consul 服务中心的 `[RpcService]` 实战与底层原理

Hyperf 服务注册指南:基于 Consul 服务中心的 `[RpcService]` 实战与底层原理 后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载本篇技术指南以 Hyperf 框架的hyperf/service-governance服务治理组件为核心完整讲解微服务架构下服务注册Server Register的设计动机、安装步骤、#[RpcService]注解的四个关键参数并结合当前仓库源码逐层剖析服务注册的完整执行链路、Consul 驱动的注册与健康检查实现以及服务发现的数据来源。读完本文你将能够在 Hyperf 项目中独立完成基于 JSON RPC 协议的服务发布与注册配置并理解服务注册失败的自动重试、服务 ID 生成、健康检查探活等底层机制。服务注册与服务中心微服务化后的必然需求随着业务系统不断拆分服务数量会持续增长每个服务背后往往还挂载着数量庞大的集群节点。为了保证整个系统的正常运转必须有一个集中式组件来汇聚散落在各个节点上的服务信息——包括服务的名称、地址、端口、节点数量等这个集中式组件通常被称为服务中心Service Center。服务中心的工作模式可以归纳为三个步骤注册Register每个服务节点在启动后向服务中心上报自身信息当节点状态发生变化时实时更新上报结果存储Store服务中心聚合所有服务的名称、地址、端口、数量等信息发现Discover服务调用方请求某个服务时先从服务中心获取该服务提供方的 IP、端口等节点信息再通过默认或自定义策略挑选一个提供方发起访问。在 Hyperf 中服务治理组件当前基于Consul实现了服务中心的接入本文即围绕该实现展开。安装服务治理组件注册服务前需要先通过 Composer 安装服务治理组件composer require hyperf/service-governance从 service-governance 的 composer.json 可以看到该组件要求 PHP 8.2并依赖hyperf/contract与hyperf/support同时它以suggest形式声明了配套能力hyperf/event与hyperf/framework用于支撑注册监听器RegisterServiceListener的运行hyperf/service-governance-consul用于提供 Consul 适配驱动hyperf/service-governance-nacos则用于 Nacos 适配驱动。组件安装完成后其 ConfigProvider 会自动完成配置与依赖的注册发布配置文件可通过以下命令生成php bin/hyperf.php vendor:publish hyperf/service-governance通过#[RpcService]注解注册服务在 Hyperf 中服务注册可以通过一个类上定义的#[RpcService]注解来完成该注解可视为“服务发布”的声明。目前已完成适配的协议为 JSON RPC更多细节可参考 JSON RPC 服务指南。?php namespace App\JsonRpc; use Hyperf\RpcServer\Annotation\RpcService; #[RpcService(name: CalculatorService, protocol: jsonrpc-http, server: jsonrpc-http)] class CalculatorService implements CalculatorServiceInterface { // Implement an add method with only int type in this example. public function calculate(int $a, int $b): int { // Specific implementation of the service method return $a $b; } }使用#[RpcService]注解时必须引入use Hyperf\RpcServer\Annotation\RpcService;。从 RpcService 注解的源码定义 可以确认该注解是一个目标为类的 PHP 8 原生属性#[Attribute(Attribute::TARGET_CLASS)]继承自Hyperf\Di\Annotation\AbstractAnnotation构造函数共接收 4 个参数参数类型默认值作用说明namestring服务名称需保证全局唯一Hyperf 会基于该属性生成对应的服务 ID 并注册到服务中心protocolstringjsonrpc-http服务对外暴露的协议目前仅支持jsonrpc与jsonrpc-http分别对应 TCP 与 HTTP 两种传输场景下的协议serverstringjsonrpc-http承载该服务类的 Server 名称对应config/autoload/server.php中servers数组下的namepublishTostring服务发布的目标服务中心目前仅支持consul留空null表示不发布到服务中心参数详解namename是该服务的唯一标识取值应全局唯一。在 Consul 驱动中服务 IDID正是基于服务名称生成若注解未显式指定id元数据驱动会通过getLastServiceId()查询 Consul 中已注册的同名服务取最大编号后缀并自增最终形如CalculatorService-0、CalculatorService-1见 ConsulDriver::generateId。这意味着同名服务的多个节点会以递增编号的 ID 形式共存于服务中心。参数详解protocolprotocol决定服务以何种协议暴露目前支持两个取值jsonrpc基于 TCP 传输的 JSON RPC 协议jsonrpc-http基于 HTTP 传输的 JSON RPC 协议为默认值。该取值对应Hyperf\Rpc\ProtocolManager中注册的协议key。两者本质上都是 JSON RPC 协议区别在于数据格式化方式、数据打包方式与数据传输器。同时protocol还会被写入 Consul 注册信息中的Meta.Protocol元数据服务发现阶段会依据它做节点协议匹配过滤详见下文“服务发现”一节。参数详解serverserver指定承载该服务类的 Server 名称默认值为jsonrpc-http。该值必须与config/autoload/server.php配置文件中servers数组下的某个name一一对应——也就是说在使用#[RpcService]发布服务之前必须先定义一个对应的 Server例如// config/autoload/server.php return [ servers [ [ name jsonrpc-http, type CoServer, host 0.0.0.0, port 9503, callbacks [ request [Hyperf\JsonRpc\HttpServer::class, onRequest], ], ], ], ];注册监听器在启动阶段会读取该配置将server名称解析为实际的主机与端口再向服务中心提交注册详见下文源码链路分析。参数详解publishTopublishTo定义服务要发布到的服务中心留空null表示不将服务发布到服务中心此时需要自行处理服务发现问题consul发布到 Consul需要先配置 hyperf/consul 组件的相关配置即services.drivers.consul下的uri、token、check等项见下文。原文档指出当前仅支持consul而从当前仓库源码结构看src/service-governance-nacos 目录已提供 Nacos 驱动适配发布配置中也预置了完整的nacos驱动配置项见 services.php可以推断服务治理驱动具备向多服务中心扩展的能力。服务注册的源码执行链路#[RpcService]注解只是“声明”真正向服务中心发起注册的动作由 RegisterServiceListener 完成。下面按执行顺序拆解整条链路。1. 注解收集ServiceManager 的内存注册表ServiceManager 是框架内存中的服务注册表其register(string $name, string $path, array $metadata)方法以服务名 → 路径 → 协议 → 元数据的多层结构存储所有被注解声明的服务ServiceManager::register。#[RpcService]注解解析后即通过该方法写入 ServiceManager同时提供deregister()与all()分别用于注销与全量读取。2. 事件触发监听 MainWorkerStart / MainCoroutineServerStartRegisterServiceListener 的listen()方法声明监听两个启动事件RegisterServiceListener::listenHyperf\Framework\Event\MainWorkerStart传统 Worker 模型下主 Worker 启动Hyperf\Server\Event\MainCoroutineServerStart协程 Server 模型下主协程 Server 启动。这意味着服务注册发生在服务端主进程启动完成、对外提供服务之前保证服务发布与节点监听同步就绪。3. 开关控制services.enable.register监听器首先通过getEnableRegister()读取配置项services.enable.register决定是否执行注册RegisterServiceListener::getEnableRegister默认值为true。若需关闭自动注册可将该配置改为false。4. 节点解析从 server 配置计算真实地址注册前需要把每个server名称解析为具体的 IP 与端口。getServers()方法遍历server.servers配置并做如下处理RegisterServiceListener::getServers过滤掉缺少name、host、port的非法配置当host为0.0.0.0或localhost时通过Hyperf\Contract\IPReaderInterface读取本机真实内网 IP确保注册到 Consul 的是可被其他节点访问的地址校验 host 为合法 IP校验端口为 0~65535 的数值否则抛出InvalidArgumentException。5. 驱动分发DriverManager 与驱动注册DriverManager 以名称索引维护所有服务治理驱动实现DriverInterface。Consul 驱动在应用启动阶段由 RegisterDriverListener 监听BootApplication事件完成注册$this-driverManager-register(consul, make(ConsulDriver::class));因此监听器只需通过$this-governanceManager-get($service[publishTo])即可按publishTo的值取到对应驱动RegisterServiceListener。6. 注册执行与失败重试监听器遍历 ServiceManager 中全部服务逐个调用驱动的isRegistered()检查是否已注册未注册则调用register()提交。整个流程包裹在最多 10 次的重试循环中RegisterServiceListener::process一旦连接服务中心失败例如 Consul 尚未启动会记录错误日志Cannot register service, connect service center failed, re-register after 1 seconds.并sleep(1)后重试最多重试 10 次。Consul 驱动的注册实现与健康检查Consul 驱动的核心实现位于 ConsulDriver它实现了Hyperf\ServiceGovernance\DriverInterface。注册请求的组装register()方法ConsulDriver::register会构造如下注册请求体提交给 Consul 的 Agent API$requestBody [ Name $name, ID $nextId, Address $host, Port $port, Meta [ Protocol $protocol, ], ];其中ID未显式指定时按“同名服务最大编号自增”规则生成。提交成功后驱动会将服务名/协议/主机/端口记录到本地registeredServices数组并输出日志Service %s:%s register to the consul successfully.失败则输出 warning 日志。按协议区分的健康检查注册请求会根据协议自动附加不同类型的 Consul 健康检查Check健康检查配置项interval与deregister_critical_service_after均可在services.drivers.consul.check下自定义协议Check 类型探活目标jsonrpc-httpHTTPhttp://{host}:{port}/jsonrpc、jsonrpc-tcp-length-check、multiplex.defaultTCP{host}:{port}grpcGRPCGRPCUseTLS为 false{host}:{port}健康检查的默认参数为deregister_critical_service_after: 90m服务被判定为 critical 后 90 分钟自动注销与interval: 1s每秒探活一次。这保证了异常节点能及时从服务中心被剔除调用方不会持续路由到不可用实例。Consul 客户端依赖与鉴权驱动通过ConsulAgentConsulAgent.php调用 Consul 的 Agent API。若配置了services.drivers.consul.token健康检查客户端会在请求头中注入X-Consul-Token以完成 ACL 鉴权ConsulDriver::createConsulHealth。若未安装hyperf/consul组件而尝试拉取节点信息会抛出ComponentRequiredException提示需要安装该组件。服务发现从 Consul 拉取健康节点服务注册的镜像操作是服务发现。ConsulDriver::getNodes()ConsulDriver::getNodes通过 Consul Health API 按服务名查询节点并执行两层过滤协议过滤比较节点Service.Meta.Protocol与调用方期望的metadata[protocol]不一致的节点直接跳过——这避免了 HTTP 与 TCP 两种 JSON RPC 协议节点被错误混用健康状态过滤遍历节点Checks只要存在一个状态不是passing的检查该节点即被判定为不可用而排除。只有同时通过两层过滤的节点才会被组装为[host ..., port ...]返回给服务消费者如 RPC 客户端或负载均衡器作为后续调用候选节点。该方法的isLongPolling()返回false即当前 Consul 驱动采用即时查询而非长轮询模式获取节点变更。组件配置速查services.php 与 server.php安装 service-governance 后发布生成的配置文件config/autoload/services.php对应 publish/services.php结构如下return [ enable [ discovery true, // 是否开启服务发现 register true, // 是否开启服务注册 ], consumers [], // 服务消费者列表 providers [], // 服务提供者列表 drivers [ consul [ uri http://127.0.0.1:8500, // Consul 服务地址 token , // Consul ACL Token可为空 check [ deregister_critical_service_after 90m, interval 1s, ], ], nacos [ host 127.0.0.1, port 8848, username null, password null, group_name api, namespace_id namespace_id, heartbeat 5, ephemeral true, cluster DEFAULT, grpc [ enable false, heartbeat 10, ], ], ], ];关键配置项说明enable.register注册监听器的总开关对应 RegisterServiceListener::getEnableRegisterenable.discovery服务发现开关对应 RPC 客户端侧的节点拉取行为drivers.consul.uriConsul 的 base URI默认指向本机8500端口drivers.consul.token可选的 ACL Token非空时注入X-Consul-Token请求头drivers.consul.check.*健康检查频率与异常节点注销延迟直接决定服务节点被剔除的速度。与此同时config/autoload/server.php中必须存在与#[RpcService]的server参数同名的 Server 定义含name、host、port否则注册监听器无法完成“服务名 → 实际节点地址”的解析注册流程将无法生效。小结从声明到落地的完整注册链路可以概括为#[RpcService]注解 → ServiceManager 收集 → 启动事件触发 RegisterServiceListener → 从server.servers解析真实 IP:Port → 通过 DriverManager 获取 Consul 驱动 → 组装带健康检查的注册请求提交 Consul并在失败时自动重试最多 10 次。其中name负责生成全局唯一的服务 IDprotocol决定传输方式与健康检查类型server关联具体的监听端口publishTo指定服务中心。借助 Consul 的健康检查机制与getNodes()的两层过滤服务提供方的异常节点会被自动隔离调用方始终只路由到协议匹配且状态passing的健康实例。对于不需要服务中心的轻量场景将publishTo留空并自行处理服务发现即可。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐终极指南如何在Mac上快速制作Windows启动盘并绕过硬件限制终极指南如何在Mac上快速制作Windows启动盘并绕过硬件限制 WinDiskWriter是一款专为macOS设计的免费开源Windows启动盘制作工具它桌面应用微服务服务注册中心paascloud-master中Consul配置微服务服务注册中心paascloud master中Consul配置 在分布式系统架构中服务注册中心Service Registry是微服务架构的核心组后端微服务电商认证鉴权使用 ServiceComb 注册中心Kratos 微服务的服务注册与服务发现实战指南使用 ServiceComb 注册中心Kratos 微服务的服务注册与服务发现实战指南 导读 本指南围绕 Kratos 官方生态中的 contrib/regi后端微服务RPC框架Web框架云原生上一篇PHP Font Lib 开发者手册扩展自定义字体格式支持下一篇Robo 3T与Jenkins集成MongoDB数据库自动化测试创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表