Hyperf方案 微服务迁移策略(单体到微服务)

张开发
2026/6/5 23:59:35 15 分钟阅读
Hyperf方案 微服务迁移策略(单体到微服务)
单体迁移微服务核心策略绞杀者模式Strangler Fig逐步替换而非重写。 ──---─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 迁移路线 单体应用 ↓ 第一步API Gateway 分流 ↓ 第二步抽离高价值/高负载模块 ↓ 第三步数据库解耦 ↓ 第四步事件驱动异步化 ↓ 完成全微服务 所需库composerrequire hyperf/json-rpc\hyperf/rpc-client\hyperf/service-governance-nacos\hyperf/async-queue\hyperf/kafka\hyperf/config-nacos ---1. API Gateway 分流绞杀者入口?php namespace App\Middleware;use Hyperf\HttpServer\Contract\RequestInterface;use Psr\Http\Message\ResponseInterface;use Psr\Http\Server\MiddlewareInterface;use Psr\Http\Server\RequestHandlerInterface;use GuzzleHttp\Client;/** * 新模块路由到微服务旧模块继续走单体 */ class StranglerMiddleware implements MiddlewareInterface{// 已迁移到微服务的路由前缀 private array$migrated[/api/ordershttp://order-service,/api/paymentshttp://payment-service,/api/usershttp://user-service,];publicfunction__construct(private Client$http){}publicfunctionprocess(ServerRequestInterface$request, RequestHandlerInterface$handler): ResponseInterface{$path$request-getUri()-getPath();foreach($this-migrated as$prefix$target){if(str_starts_with($path,$prefix)){return$this-proxy($request,$target);}}// 未迁移模块继续走单体逻辑return$handler-handle($request);}privatefunctionproxy(ServerRequestInterface$request, string$target): ResponseInterface{$response$this-http-request(method:$request-getMethod(), uri:$target.$request-getUri()-getPath(), options:[headers$request-getHeaders(),json$request-getParsedBody(),query$request-getQueryParams(),]);return$this-response -withStatus($response-getStatusCode())-withBody($response-getBody());}}---2. 双写过渡数据同步 迁移期间新旧系统同时写入确保数据一致。?php namespace App\Service;use Hyperf\AsyncQueue\Driver\DriverFactory;class OrderService{publicfunction__construct(private LegacyOrderRepository$legacy, // 单体 DB private DriverFactory$queue,){}publicfunctioncreate(int$userId, array$items): array{//1. 写入单体主$order$this-legacy-create($userId,$items);//2. 异步同步到新服务副$this-queue-get(default)-push(new SyncOrderToMicroserviceJob($order-toArray()));return$order-toArray();}}同步 Job?php namespace App\Job;use Hyperf\AsyncQueue\Job;class SyncOrderToMicroserviceJob extends Job{publicfunction__construct(private array$order){}publicfunctionhandle(): void{// 写入新微服务 DB幂等处理 Order::updateOrCreate([legacy_id$this-order[id]],$this-order);}}---3. 事件驱动解耦Kafka 用事件替代模块间直接调用解耦单体内部依赖。?php namespace App\Service;use Hyperf\Kafka\Producer;class OrderService{publicfunction__construct(private Producer$producer){}publicfunctioncreate(int$userId, array$items): array{$orderOrder::create([user_id$userId,totalcollect($items)-sum(price)]);// 发布事件下游服务自行消费替代直接调用$this-producer-send(topic:order.created, value: json_encode($order-toArray()), key:(string)$order-id,);return$order-toArray();}}消费方库存/通知服务?php namespace App\Consumer;use Hyperf\Kafka\AbstractConsumer;use Hyperf\Kafka\Annotation\Consumer;use longlang\phpkafka\Consumer\ConsumeMessage;#[Consumer(topic: order.created, groupId: inventory-service, autoCommit: false)]class OrderCreatedConsumer extends AbstractConsumer{publicfunctionconsume(ConsumeMessage$message): string{$orderjson_decode($message-getValue(),true);// 扣减库存 Inventory::where(product_id,$order[product_id])-decrement(stock,$order[qty]);returnself::ACK;}}---4. 数据库解耦分库策略?php // config/autoload/databases.phpreturn[// 单体库迁移期保留legacy[drivermysql,hostenv(LEGACY_DB_HOST),databaseenv(LEGACY_DB_NAME),], // 新订单服务独立库order[drivermysql,hostenv(ORDER_DB_HOST),databaseorder_service,],];迁移期 Model 双读 class Order extends Model{// 切换此处完成数据库迁移 protected string$connectionenv(ORDER_DB_DRIVER,legacy);}---5. 功能开关灰度切流?php namespace App\Service;use Hyperf\ConfigNacos\NacosClient;class FeatureFlag{publicfunction__construct(private NacosClient$nacos){}publicfunctionisMigrated(string$module): bool{// Nacos 动态配置无需重启切流return(bool)config(migration.{$module},false);}}控制器中使用#[PostMapping(path: orders)]publicfunctioncreate(): array{if($this-flag-isMigrated(order)){// 走新微服务return$this-orderRpcClient-create($this-request-input(user_id),$this-request-input(items),);}// 走单体逻辑return$this-legacyOrderService-create($this-request-input(user_id),$this-request-input(items),);}--- 迁移检查清单 阶段一准备 ✓ 部署 API GatewayStranglerMiddleware ✓ 接入 Nacos 配置中心 ✓ 接入链路追踪hyperf/tracer 阶段二抽离 ✓ 高负载模块优先订单/支付 ✓ 双写过渡验证数据一致性 ✓ 功能开关控制流量比例1% →10% →100% 阶段三解耦 ✓ 模块间调用改为 Kafka 事件 ✓ 独立数据库停止双写 ✓ 下线单体对应模块 --- 核心要点 - 绞杀者模式网关层分流新旧并行逐步替换不停服 - 双写 功能开关是迁移期最重要的安全网 - 事件驱动解耦比 RPC 更适合迁移期降低服务间强依赖 - 数据库解耦是最后一步也是最难的一步用 legacy_id 字段做映射

更多文章