# Multi-Lane Manager

Multi-Lane Manager 是一个 Nuxt 模块，提供基于 Nacos 的服务注册、发现和请求路由功能，用于在 Nuxt 应用中实现多泳道架构。

## 多泳道架构实现原理

### 架构概览

多泳道架构通过 Nacos 服务注册与发现和请求拦截分发两大核心机制实现，使同一服务的不同实例能够并行运行并智能路由请求。

```ascii
┌─────────────────────────────────────────────────────────────────────────┐
│                                                                         │
│                           多泳道架构实现原理                              │
│                                                                         │
├─────────────────┐                              ┌─────────────────────────┤
│                 │                              │                         │
│  Nacos服务注册   │◄──────────┐  ┌──────────────►│  请求拦截与分发          │
│                 │           │  │              │                         │
└─────────────────┘           │  │              └─────────────────────────┘
        │                     │  │                         │
        ▼                     │  │                         ▼
┌─────────────────┐           │  │              ┌─────────────────────────┐
│ 服务启动自动注册  │           │  │              │ HTTP请求拦截            │
└─────────────────┘           │  │              └─────────────────────────┘
        │                     │  │                         │
        ▼                     │  │                         ▼
┌─────────────────┐           │  │              ┌─────────────────────────┐
│ 心跳维持         │           │  │              │ 泳道ID提取              │
└─────────────────┘           │  │              └─────────────────────────┘
        │                     │  │                         │
        ▼                     │  │                         ▼
┌─────────────────┐           │  │              ┌─────────────────────────┐
│ 优雅下线         │           │  │              │ 目标实例查询            │
└─────────────────┘           │  │              └─────────────────────────┘
        │                     │  │                         │
        ▼                     │  │                         ▼
┌─────────────────┐           │  │              ┌─────────────────────────┐
│ 元数据管理       │───────────┘  └──────────────│ 请求转发                │
└─────────────────┘                             └─────────────────────────┘
```

### 1. Nacos服务注册与发现

**服务注册流程**：

- 应用启动时，自动向Nacos注册当前服务实例
- 注册信息包含：服务名称、IP地址、端口、泳道ID（作为元数据）
- 启动定时任务，定期向Nacos发送心跳，维持实例健康状态
- 应用关闭时，自动向Nacos注销服务实例

**服务发现机制**：

- 根据服务名称和目标泳道ID查询Nacos服务实例
- 支持按心跳时间排序，优先选择最近心跳的健康实例
- 使用负载均衡策略（默认轮询）选择目标实例
- 支持实例健康检查，只选择健康的实例

### 2. 请求拦截与分发

**请求拦截**：

- 通过Nitro插件和服务器中间件拦截所有HTTP请求
- 支持拦截静态资源请求（如CSS/JS/HTML）和API请求

**泳道识别**：

- 从请求头（默认X-Lane-ID）或Cookie中提取目标泳道ID
- 如果未指定泳道ID，尝试路由到baseline泳道
- 如果当前实例已是目标泳道，直接在本地处理请求

**请求路由**：

- 根据目标泳道ID查询Nacos获取目标实例
- 如果找到目标实例，将请求转发到目标实例
- 如果未找到目标实例但指定了baseline泳道，尝试查找baseline泳道实例
- 如果未找到任何匹配实例，在当前实例处理请求

**请求转发**：

- 保留原始请求的方法、路径、查询参数和请求体
- 添加代理相关的请求头（X-Forwarded-For等）
- 将目标实例的响应返回给客户端
- 支持调试模式，提供详细的请求处理信息

**故障转移与健壮性**：

- 自动检测实例故障（连接失败、超时、502/503/504错误）
- 智能故障转移到其他健康实例
- 实例黑名单机制，避免重复请求故障实例
- 自动重试机制，提高请求成功率
- 实例健康状态自动恢复

## 目录

- [第一部分：使用指南](#第一部分使用指南)
  - [什么是多泳道架构](#什么是多泳道架构)
  - [功能特性](#功能特性)
  - [安装步骤](#安装步骤)
  - [多泳道部署示例](#多泳道部署示例)
  - [生产环境部署](#生产环境部署)
  - [常见问题解答](#常见问题解答)
- [第二部分：Nitro 插件编写指南](#第二部分nitro-插件编写指南)
  - [Nitro 插件基础](#nitro-插件基础)
  - [插件生命周期](#插件生命周期)
  - [注册 Nitro 插件](#注册-nitro-插件)
  - [常用钩子](#常用钩子)
  - [最佳实践](#最佳实践)
  - [调试 Nitro 插件](#调试-nitro-插件)
- [第三部分：实现细节](#第三部分实现细节)
  - [模块结构](#模块结构)
  - [核心文件说明](#核心文件说明)
  - [类型定义](#类型定义)
  - [导出函数](#导出函数)

## 第一部分：使用指南

## 什么是多泳道架构

多泳道架构是一种微服务部署模式，允许同一个服务的多个实例在不同的环境或配置下并行运行。每个"泳道"代表一个独立的服务实例集合，具有自己的配置和状态。

多泳道架构的优势：

- 支持多版本并行部署
- 便于 A/B 测试和灰度发布
- 隔离测试环境和生产环境
- 支持按团队或功能划分服务实例

## 功能特性

- 🚀 **服务自动注册**：应用启动时自动向 Nacos 注册服务
- 🔄 **心跳维持**：自动维持与 Nacos 的心跳连接
- 🔍 **服务发现**：基于泳道 ID 发现目标服务实例
- 🔀 **请求转发**：自动将请求转发到目标泳道的服务实例
- 🛑 **优雅下线**：应用关闭时自动注销服务
- 🔄 **智能路由**：未指定泳道 ID 的请求会优先路由到 baseline 泳道

## 安装步骤

### 1. 安装 Multi-Lane Manager 模块

在 Nuxt 项目中安装 Multi-Lane Manager 模块：

```bash
# 使用 npm
npm install multi-lane-manager

# 使用 yarn
yarn add multi-lane-manager

# 使用 pnpm
pnpm add multi-lane-manager
```

### 2. 配置 Nuxt 项目

在 `nuxt.config.ts` 文件中添加模块：

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    // 其他模块...
    'multi-lane-manager/nuxt'
  ],
})
```

### 3. 配置环境变量

创建 `.env` 文件或在启动命令中设置以下环境变量：

#### 环境变量列表

| 环境变量 | 必须/可选 | 默认值 | 说明 |
|---------|----------|--------|------|
| **服务标识配置** |  |  |  |
| `SERVICE_NAME` | **必须** | 无 | 服务名称，用于在 Nacos 中注册服务。如果未设置，泳道功能将被禁用。可以通过以下方式获取：1) 此环境变量，2) 其他环境变量（NITRO_APP_NAME, APP_NAME, npm_package_name），3) package.json 的 name 字段 |
| `NITRO_APP_NAME` | 可选 | 无 | Nitro 应用名称环境变量，当 SERVICE_NAME 未设置时使用 |
| `APP_NAME` | 可选 | 无 | 应用名称环境变量，当 SERVICE_NAME 和 NITRO_APP_NAME 未设置时使用 |
| `npm_package_name` | 可选 | 无 | npm 运行时提供的 package.json 中的 name 字段，当其他环境变量未设置时使用 |
| **泳道配置** |  |  |  |
| `LANE_ENABLE` | 可选 | false | 是否启用泳道功能 |
| `LANE_ID` | 可选 | baseline | 当前服务的泳道 ID |
| `LANE_TARGET_HEADER` | 可选 | X-Lane-ID | 目标泳道请求头键名 |
| `LANE_COOKIE_ENABLE` | 可选 | true | 是否启用从 cookie 中检测泳道 ID |
| **Nacos 服务器配置** |  |  |  |
| `LANE_SERVER` | 可选 | localhost:8848 | Nacos 服务器地址和端口（格式：host:port） |
| `LANE_NAMESPACE` | 可选 | public | Nacos 命名空间 |
| `LANE_GROUP_NAME` | 可选 | DEFAULT_GROUP | Nacos 分组名称 |
| **心跳配置** |  |  |  |
| `LANE_HEARTBEAT_INTERVAL` | 可选 | 5000 | 心跳间隔（毫秒），建议与 Java 客户端保持一致 |
| `LANE_INSTANCE_TTL` | 可选 | 15000 | 实例过期时间（毫秒），建议为心跳间隔的 3 倍 |
| **端口配置** |  |  |  |
| `NITRO_PORT` | 可选 | 3000 | Nitro 服务器端口，优先级高于 PORT |
| `PORT` | 可选 | 3000 | 服务器端口，当 NITRO_PORT 未设置时使用 |
| **主机配置** |  |  |  |
| `HOST` | 可选 | 自动检测 | 服务IP地址，支持自动检测容器IP |
| `POD_IP` | 可选 | 无 | Kubernetes环境下的Pod IP地址 |
| `CONTAINER_IP` | 可选 | 无 | 容器环境下的IP地址 |
| **超时配置** |  |  |  |
| `LANE_PROXY_TIMEOUT` | 可选 | 15000 | 代理请求超时时间（毫秒） |
| `LANE_REGISTRATION_TIMEOUT` | 可选 | 5000 | 注册请求超时时间（毫秒） |
| **日志配置** |  |  |  |
| `LOG_LEVEL` | 可选 | info | 日志级别，可选值: silent, fatal, error, warn, info, success, debug, trace, verbose |
| `LANE_LOG_LEVEL` | 可选 | 同 LOG_LEVEL | 泳道管理器专用日志级别，优先级低于 LOG_LEVEL |

#### 示例配置

```env
# 必须配置 - 服务标识
SERVICE_NAME=your-service-name  # 服务名称（或通过 package.json 提供）

# 泳道配置
LANE_ENABLE=true
LANE_ID=dev-lane  # 当前服务的泳道 ID
LANE_TARGET_HEADER=X-Lane-ID  # 目标泳道请求头键名

# Nacos 配置
LANE_SERVER=localhost:8848  # Nacos 服务器地址和端口
LANE_NAMESPACE=public  # Nacos 命名空间
LANE_GROUP_NAME=DEFAULT_GROUP  # Nacos 分组名称

# 心跳配置
LANE_HEARTBEAT_INTERVAL=5000  # 心跳间隔（毫秒）
LANE_INSTANCE_TTL=15000  # 实例过期时间（毫秒）

# 端口配置
NITRO_PORT=3000  # Nitro 服务器端口

# 主机配置（可选，支持自动检测）
# HOST=192.168.1.100  # 手动指定IP地址
# POD_IP=10.244.0.10  # Kubernetes Pod IP（通常由K8s自动注入）
# CONTAINER_IP=172.17.0.2  # 容器IP地址

# 日志配置
LOG_LEVEL=info  # 日志级别
```

### 4. 启动 Nacos 服务器

确保 Nacos 服务器已经启动并可访问。如果没有 Nacos 服务器，可以使用 Docker 快速启动一个：

```bash
docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m -p 8848:8848 -d nacos/nacos-server:latest
```

### 5. 启动应用

```bash
npm run dev
```

启动后，应用将自动向 Nacos 注册服务，并开始发送心跳。

## 多泳道部署示例

### 部署多个泳道实例

```bash
# 启动 dev-lane 泳道实例
NITRO_PORT=3001 LANE_ENABLE=true LANE_ID=dev-lane SERVICE_NAME=your-service npm run dev

# 启动 test-lane 泳道实例
NITRO_PORT=3002 LANE_ENABLE=true LANE_ID=test-lane SERVICE_NAME=your-service npm run dev
```

### 测试跨泳道请求

```bash
# 向 dev-lane 发送请求，但目标泳道为 test-lane
curl -H "X-Lane-ID: test-lane" http://localhost:3001/api/some-endpoint

# 向 test-lane 发送请求，但目标泳道为 dev-lane
curl -H "X-Lane-ID: dev-lane" http://localhost:3002/api/some-endpoint

# 不指定泳道ID的请求（将尝试路由到 baseline 泳道）
curl http://localhost:3001/api/some-endpoint
```

### baseline 泳道

多泳道管理器引入了 "baseline" 泳道的概念，作为默认的基准泳道：

1. **默认泳道ID**：如果应用启用了泳道功能但没有设置泳道ID，则默认使用 "baseline" 作为泳道ID
2. **智能路由**：当收到一个没有指定泳道ID的请求时：
   - 首先查询 Nacos 是否有 "baseline" 泳道的实例
   - 如果有，则将请求路由到 "baseline" 泳道的实例
   - 如果没有，则在当前实例处理请求

这种设计有以下优势：

- 提供了一个稳定的基准环境（baseline）
- 未指定泳道的请求默认使用基准环境，确保一致的用户体验
- 当基准环境不可用时，自动降级到当前实例处理，提高系统可用性

## 生产环境部署

在生产环境中部署多泳道架构时，建议：

1. **使用环境变量注入配置**：

   ```bash
   # 生产环境启动命令示例
   NODE_ENV=production LANE_ENABLE=true LANE_ID=prod-lane SERVICE_NAME=your-service LANE_SERVER=nacos.example.com:8848 node .output/server/index.mjs
   ```

2. **使用 PM2 或 Docker 管理进程**：

   ```bash
   # PM2 示例
   pm2 start ecosystem.config.js

   # Docker 示例
   docker run -e LANE_ENABLE=true -e LANE_ID=prod-lane -e SERVICE_NAME=your-service -e LANE_SERVER=nacos.example.com:8848 -p 3000:3000 your-service-image
   ```

3. **配置健康检查**：
   确保监控系统可以检查服务的健康状态，包括 Nacos 连接状态。

4. **设置合理的心跳间隔和过期时间**：
   在生产环境中，建议将心跳间隔设置为 5-10 秒，过期时间设置为心跳间隔的 2-3 倍。

## 容器环境部署

### Docker 部署

在 Docker 容器中部署时，multi-lane-manager 会自动检测容器的IP地址：

```dockerfile
# Dockerfile
FROM node:18-alpine

WORKDIR /app
COPY . .
RUN npm install
RUN npm run build

# 设置环境变量
ENV LANE_ENABLE=true
ENV LANE_ID=prod-lane
ENV SERVICE_NAME=your-service
ENV LANE_SERVER=nacos.example.com:8848

EXPOSE 3000

CMD ["node", ".output/server/index.mjs"]
```

启动容器：

```bash
docker run -d \
  --name your-service-prod \
  -e LANE_ENABLE=true \
  -e LANE_ID=prod-lane \
  -e SERVICE_NAME=your-service \
  -e LANE_SERVER=nacos.example.com:8848 \
  -p 3000:3000 \
  your-service-image
```

### Kubernetes 部署

在 Kubernetes 中部署时，建议使用 Pod IP 作为服务注册地址：

```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: your-service
  template:
    metadata:
      labels:
        app: your-service
    spec:
      containers:
      - name: your-service
        image: your-service-image:latest
        ports:
        - containerPort: 3000
        env:
        # 泳道配置
        - name: LANE_ENABLE
          value: "true"
        - name: LANE_ID
          value: "prod-lane"
        - name: SERVICE_NAME
          value: "your-service"

        # Nacos 配置
        - name: LANE_SERVER
          value: "nacos.example.com:8848"

        # Pod IP 自动注入
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

        # 其他配置
        - name: NITRO_PORT
          value: "3000"
        - name: LOG_LEVEL
          value: "info"

        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

        # 健康检查
        livenessProbe:
          httpGet:
            path: /api/lane-manager/health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10

        readinessProbe:
          httpGet:
            path: /api/lane-manager/health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
```

### IP 地址自动检测机制

multi-lane-manager 采用完全自动化的IP检测机制，无需手动配置：

1. **网络接口自动检测（核心逻辑）**：
   - 优先检测容器网络接口：`eth0`, `eth1`, `ens3`, `ens4`
   - 然后检测物理/虚拟机接口：`ens160`, `enp0s3`, `en0` 等
   - 智能过滤Docker桥接网络和虚拟接口
   - 优先选择私有网络IP（10.x.x.x, 172.16-31.x.x, 192.168.x.x）

2. **Kubernetes环境变量（备选方案）**：
   - 当网络接口检测失败时，使用 `POD_IP` 环境变量
   - 通常由Downward API自动注入

3. **其他容器环境变量（最后备选）**：
   - 当前两种方法都失败时，使用 `CONTAINER_IP` 环境变量

4. **智能过滤机制**：
   - 自动跳过内部地址（127.x.x.x）和Docker桥接网络（172.17.x.x）
   - 过滤虚拟接口（docker0, br-, veth等）
   - 优先选择私有网络IP，符合容器环境实际情况

5. **容错机制**：
   - 如果所有检测方法都失败，提供详细的错误信息和解决建议
   - 仅在极端情况下才回退到localhost

### 容器环境最佳实践

1. **完全自动化**：无需手动配置IP地址，让系统自动检测
2. **Kubernetes Pod IP注入**：使用Downward API自动注入Pod IP

   ```yaml
   env:
   - name: POD_IP
     valueFrom:
       fieldRef:
         fieldPath: status.podIP
   ```

3. **健康检查**：配置 liveness 和 readiness 探针
4. **资源限制**：设置合适的 CPU 和内存限制
5. **日志级别**：生产环境使用 `info` 级别，调试时使用 `debug`
6. **优雅关闭**：确保容器正确处理 SIGTERM 信号
7. **网络策略**：确保容器能够访问Nacos服务器
8. **监控告警**：监控服务注册状态和心跳健康

## 常见问题解答

### 1. 如何查看服务是否成功注册到 Nacos？

可以通过 Nacos 控制台查看服务注册情况，通常访问 `http://nacos-server:8848/nacos/` 并登录（默认用户名/密码：nacos/nacos）。

### 2. 如何处理跨泳道请求失败？

检查以下几点：

- 确保目标泳道的服务实例已注册并健康
- 检查网络连接是否正常
- 查看日志中的错误信息
- 使用调试头获取详细信息（见下文）

### 3. 如何调试泳道请求？

可以通过添加 `X-Lane-Debug` 请求头来获取详细的调试信息。当请求中包含此头时，响应中会包含 `X-Lane-Detail` 头，其中包含请求处理的详细信息。

```bash
# 使用 curl 发送带调试头的请求
curl -H "X-Lane-Debug: true" -H "X-Lane-ID: test-lane" http://localhost:3000/api/some-endpoint
```

响应头中的 `X-Lane-Detail` 包含以下信息：

- 请求时间和路径
- 当前泳道和服务名称
- 目标泳道信息（如果有）
- 请求处理方式（本地处理或跨泳道转发）
- 如果是跨泳道请求，还包括目标实例信息和负载均衡策略
- 如果发生错误，包含错误信息

这对于排查泳道路由和转发问题非常有用。

### 4. 如何自定义请求转发逻辑？

可以通过修改 `nuxt.config.ts` 中的配置选项自定义请求转发逻辑：

```typescript
multiLaneManager: {
  // 自定义目标泳道请求头键名
  targetLaneHeaderKey: 'x-custom-lane',

  // 自定义代理请求超时时间
  proxyTimeout: 30000,
}
```

### 5. 如何在 CI/CD 流程中集成多泳道架构？

在 CI/CD 流程中，可以为每个分支或环境配置不同的泳道 ID，例如：

- `main` 分支 → `prod-lane`
- `develop` 分支 → `dev-lane`
- 特性分支 → `feature-{branch-name}-lane`

这样可以实现按分支或环境隔离服务实例。

## 第二部分：Nitro 插件编写指南

### Nitro 插件基础

Nitro 插件是 Nuxt 3 中一种强大的扩展机制，允许您在服务器启动时执行代码、添加中间件、注册钩子等。Multi-Lane Manager 使用 Nitro 插件来实现服务注册和健康检查功能。

> 💡 **提示**：Nitro 插件与 Nuxt 插件不同。Nitro 插件在服务器端运行，而 Nuxt 插件可以在客户端和服务器端运行。Nitro 插件更适合处理服务器端的任务，如服务注册、数据库连接等。

Nitro 插件是一个导出默认函数的 JavaScript/TypeScript 文件，该函数接收 `nitroApp` 对象作为参数：

```typescript
// my-nitro-plugin.ts
export default (nitroApp) => {
  // 插件代码
}
```

### 插件生命周期

Nitro 插件在服务器启动过程中被加载和执行，具体时机如下：

1. **加载阶段**：模块代码被加载到内存中
2. **初始化阶段**：插件默认导出函数被执行
3. **运行阶段**：服务器运行期间，插件注册的钩子会在相应事件发生时被调用
4. **关闭阶段**：服务器关闭时，插件可以执行清理操作

下图展示了 Nitro 插件的生命周期：

```ascii
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│                 │     │                 │     │                 │     │                 │
│   加载阶段      │────▶│   初始化阶段    │────▶│    运行阶段     │────▶│    关闭阶段     │
│                 │     │                 │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘     └─────────────────┘
       │                       │                       │                       │
       ▼                       ▼                       ▼                       ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ 模块代码被加载  │     │ 插件默认函数    │     │ 钩子函数被调用  │     │ 清理资源       │
│ 到内存中        │     │ 被执行          │     │ (request等)     │     │ 注销服务       │
└─────────────────┘     └─────────────────┘     └─────────────────┘     └─────────────────┘
```

### 注册 Nitro 插件

在 Nuxt 模块中注册 Nitro 插件的方法：

```typescript
// 在 Nuxt 模块的 setup 函数中
nuxt.hook('nitro:config', (nitroConfig) => {
  // 确保 plugins 数组存在
  nitroConfig.plugins = nitroConfig.plugins || [];

  // 添加插件
  nitroConfig.plugins.push(resolve('./runtime/my-nitro-plugin'));
});
```

### 常用钩子

Nitro 插件可以使用以下常用钩子：

- **`request`**：处理每个请求
- **`close`**：服务器关闭时执行清理操作
- **`error`**：处理服务器错误

```typescript
// 注册请求钩子
nitroApp.hooks.hook('request', async (event) => {
  // 处理请求
});

// 注册关闭钩子
nitroApp.hooks.hook('close', async () => {
  // 执行清理操作
});

// 注册错误钩子
nitroApp.hooks.hook('error', async (error, event) => {
  // 处理错误
});
```

### 最佳实践

1. **模块化设计**：将插件代码分解为多个专门的函数，提高可维护性
2. **错误处理**：使用 try/catch 捕获异常，避免插件错误导致服务器崩溃
3. **资源清理**：在服务器关闭时释放资源，如关闭连接、取消定时器等
4. **日志记录**：使用日志系统记录插件的运行状态和错误信息
5. **类型安全**：使用 TypeScript 类型定义，提高代码质量和开发体验

### 调试 Nitro 插件

调试 Nitro 插件可以使用以下方法：

**日志输出**：在插件中添加详细的日志输出，记录插件的执行流程和状态

```typescript
logger.info('Nitro 插件初始化');
logger.debug('配置:', config);
```

**环境变量**：使用环境变量控制插件的行为，如启用/禁用功能、设置日志级别等

```typescript
if (process.env.DEBUG_NITRO_PLUGIN === 'true') {
  logger.level = 'debug';
}
```

**健康检查端点**：添加健康检查端点，返回插件的状态信息

```typescript
nitroApp.hooks.hook('request', (event) => {
  if (event.path === '/api/plugin-status') {
    event.node.res.end(JSON.stringify({
      status: 'running',
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      // 其他状态信息
    }));
  }
});
```

**错误监控**：捕获并记录插件中的错误，便于排查问题

```typescript
try {
  // 插件代码
} catch (error) {
  logger.error('插件错误:', error);
  // 可以将错误发送到监控系统
}
```

## 第三部分：实现细节

### 模块结构

```text
packages/multi-lane-manager/
├── src/
│   ├── index.ts                # 主入口文件
│   ├── types.ts                # 类型定义
│   ├── module.ts               # Nuxt 模块定义
│   ├── runtime/
│   │   ├── nitro-plugin.ts     # Nitro 插件（服务注册和健康检查）
│   │   ├── server-middleware.ts # 服务器中间件（请求转发）
│   │   └── server-utils.ts     # 服务器工具函数
│   └── utils/
│       ├── config.ts           # 配置管理
│       ├── logger.ts           # 日志管理
│       ├── nacos.ts            # Nacos 服务管理
│       └── proxy.ts            # 请求转发
└── README.md                   # 文档
```

### 核心文件说明

#### 1. `module.ts`

Nuxt 模块定义文件，负责注册 Nitro 插件和服务器中间件。

```typescript
// module.ts
export default defineNuxtModule({
  meta: {
    name: "multi-lane-manager",
    configKey: "multiLaneManager",
  },
  setup(_options, nuxt) {
    // 添加 Nitro 插件
    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.plugins = nitroConfig.plugins || [];
      nitroConfig.plugins.push(resolve('./runtime/nitro-plugin'));
    });

    // 添加服务器中间件
    addServerHandler({
      handler: resolve('./runtime/server-middleware'),
      middleware: true,
    });
  },
});
```

#### 2. `runtime/nitro-plugin.ts`

Nitro 插件文件，负责服务注册、心跳维持和健康检查。

```typescript
// nitro-plugin.ts
export default (nitroApp) => {
  // 立即注册服务
  (async () => {
    try {
      const port = getServerPort();
      await registerServiceInstance(port);
      // 设置优雅下线
    } catch (error) {
      // 错误处理
    }
  })();

  // 添加健康检查路由
  nitroApp.hooks.hook('request', (event) => {
    if (event.path === '/api/lane-manager/health') {
      // 返回健康状态
    }
  });
};
```

#### 3. `runtime/server-middleware.ts`

服务器中间件文件，负责跨泳道请求转发。

```typescript
// server-middleware.ts
import { createServerMiddleware } from './server-utils';

// 导出中间件函数
export default createServerMiddleware();
```

#### 4. `utils/nacos.ts`

Nacos 服务管理文件，负责服务注册、注销、心跳维持和服务发现。

```typescript
// nacos.ts
export async function registerServiceInstance(port: number): Promise<boolean> {
  // 向 Nacos 注册服务实例
}

export async function deregisterServiceInstance(port: number): Promise<boolean> {
  // 从 Nacos 注销服务实例
}

export async function sendHeartbeat(port: number): Promise<boolean> {
  // 向 Nacos 发送心跳
}

export async function getNacosLaneInstances(
  serviceName: string,
  targetLaneId: string
): Promise<ServiceInstanceInfo[]> {
  // 从 Nacos 获取指定泳道的服务实例
}
```

### 类型定义

```typescript
// 服务实例信息
interface ServiceInstanceInfo {
  ip: string;
  port: number;
  serviceName: string;
  clusterName: string;
  ephemeral: boolean;
  metadata: {
    laneId: string;
    [key: string]: string;
  };
  status: "UP" | "DOWN" | "UNKNOWN";
  lastHeartbeat: number | string;
  version?: string;
  healthy?: boolean;
}

// 泳道信息
interface LaneInfo {
  id: string;
  instances: ServiceInstanceInfo[];
}

// 泳道管理器配置
interface LaneManagerConfig {
  // Nacos 服务器配置
  nacosServerAddr: string;
  nacosServerPort: string;
  nacosUrl: string;
  nacosNamespace: string;
  nacosGroupName: string;

  // 服务配置
  serviceName: string;
  currentLaneId: string;
  host: string;
  port: number | null;

  // 泳道配置
  targetLaneHeaderKey: string; // 小写形式
  isLaneEnabled: boolean;

  // 超时配置
  proxyTimeout: number;
  registrationTimeout: number;
  heartbeatInterval: number; // 心跳间隔，单位毫秒
  instanceTtl: number; // 实例过期时间，单位毫秒

  // 元数据
  metadata: Record<string, any>;
}
```

### 导出函数

```typescript
// 创建服务器中间件
function createServerMiddleware(): (event: H3Event) => Promise<void>;

// 注册服务实例
function registerServiceInstance(port: number): Promise<boolean>;

// 注销服务实例
function deregisterServiceInstance(port: number): Promise<boolean>;

// 获取指定泳道的服务实例
function getNacosLaneInstances(serviceName: string, targetLaneId: string): Promise<ServiceInstanceInfo[]>;

// 获取服务器端口
function getServerPort(): number;

// 创建日志管理器
function createLogger(options?: LoggerOptions): ConsolaInstance;

// 获取配置
function getConfig(): LaneManagerConfig;

// 更新配置端口
function updateConfigPort(port: number): void;
```

### 工作流程

1. **服务注册流程**：
   - 应用启动时，Nitro 插件自动执行
   - 获取服务器端口和配置信息
   - 向 Nacos 发送注册请求
   - 启动心跳定时器
   - 设置进程退出时的注销逻辑

2. **心跳维持流程**：
   - 服务注册成功后，自动启动心跳定时器
   - 定期向 Nacos 发送心跳请求
   - 心跳间隔由 `NACOS_HEARTBEAT_INTERVAL` 环境变量指定，默认为 6000 毫秒（6 秒）
   - 如果心跳失败，会记录错误日志但不会停止心跳

3. **跨泳道请求转发流程**：
   - 服务器中间件拦截所有请求
   - 检查请求头中是否包含目标泳道 ID
   - 如果目标泳道 ID 与当前泳道 ID 不同，则进行转发
   - 从 Nacos 获取目标泳道的服务实例
   - 使用负载均衡策略选择一个实例
   - 将请求转发到目标实例
   - 将目标实例的响应返回给客户端

4. **优雅下线流程**：
   - 监听进程退出事件（SIGINT、SIGTERM、beforeExit）
   - 监听 Nitro 关闭事件
   - 在这些事件发生时，向 Nacos 发送注销请求
   - 确保服务实例被正确移除

### 请求转发示例

当请求头中包含 `X-Target-Lane` 且值与当前服务的泳道 ID 不同时，模块会自动将请求转发到目标泳道的服务实例。

例如，向当前服务发送请求，但指定目标泳道为 `test-lane`：

```bash
curl -H "X-Target-Lane: test-lane" http://localhost:3000/api/some-endpoint
```

模块会：

1. 检测到这是一个跨泳道请求
2. 从 Nacos 获取 `test-lane` 泳道的服务实例
3. 将请求转发到目标实例
4. 将目标实例的响应返回给客户端

### 优雅下线

应用关闭时，模块会自动向 Nacos 发送注销请求，确保服务实例被正确移除。

## 高级配置

### 编写自定义 Nitro 插件

Nitro 插件是 Nuxt 3 中一种强大的扩展机制，允许您在服务器启动时执行代码、添加中间件、注册钩子等。Multi-Lane Manager 使用 Nitro 插件来实现服务注册和健康检查功能。

> 💡 **提示**：Nitro 插件与 Nuxt 插件不同。Nitro 插件在服务器端运行，而 Nuxt 插件可以在客户端和服务器端运行。Nitro 插件更适合处理服务器端的任务，如服务注册、数据库连接等。

#### Nitro 插件基础

Nitro 插件是一个导出默认函数的 JavaScript/TypeScript 文件，该函数接收 `nitroApp` 对象作为参数：

```typescript
// my-nitro-plugin.ts
export default (nitroApp) => {
  // 插件代码
}
```

#### 插件生命周期

Nitro 插件在服务器启动过程中被加载和执行，具体时机如下：

1. **加载阶段**：模块代码被加载到内存中
2. **初始化阶段**：插件默认导出函数被执行
3. **运行阶段**：服务器运行期间，插件注册的钩子会在相应事件发生时被调用
4. **关闭阶段**：服务器关闭时，插件可以执行清理操作

下图展示了 Nitro 插件的生命周期：

```ascii
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│                 │     │                 │     │                 │     │                 │
│   加载阶段      │────▶│   初始化阶段    │────▶│    运行阶段     │────▶│    关闭阶段     │
│                 │     │                 │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘     └─────────────────┘
       │                       │                       │                       │
       ▼                       ▼                       ▼                       ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ 模块代码被加载  │     │ 插件默认函数    │     │ 钩子函数被调用  │     │ 清理资源       │
│ 到内存中        │     │ 被执行          │     │ (request等)     │     │ 注销服务       │
└─────────────────┘     └─────────────────┘     └─────────────────┘     └─────────────────┘
```

#### 注册 Nitro 插件

在 Nuxt 模块中注册 Nitro 插件的方法：

```typescript
// 在 Nuxt 模块的 setup 函数中
nuxt.hook('nitro:config', (nitroConfig) => {
  // 确保 plugins 数组存在
  nitroConfig.plugins = nitroConfig.plugins || [];

  // 添加插件
  nitroConfig.plugins.push(resolve('./runtime/my-nitro-plugin'));
});
```

#### 常用钩子

Nitro 插件可以使用以下常用钩子：

- **`request`**：处理每个请求
- **`close`**：服务器关闭时执行清理操作
- **`error`**：处理服务器错误

```typescript
// 注册请求钩子
nitroApp.hooks.hook('request', async (event) => {
  // 处理请求
});

// 注册关闭钩子
nitroApp.hooks.hook('close', async () => {
  // 执行清理操作
});

// 注册错误钩子
nitroApp.hooks.hook('error', async (error, event) => {
  // 处理错误
});
```

#### 示例：服务注册插件

以下是 Multi-Lane Manager 中服务注册插件的简化版本：

```typescript
// nitro-plugin.ts
import { getConfig, getGlobalState } from '../utils/config';
import { registerServiceInstance, deregisterServiceInstance } from '../utils/nacos';
import { getServerPort } from './server-utils';

export default (nitroApp) => {
  // 获取配置
  const config = getConfig();
  const globalState = getGlobalState();

  // 立即注册服务
  (async () => {
    try {
      // 获取服务器端口
      const port = getServerPort();

      // 注册服务实例
      const success = await registerServiceInstance(port);

      if (success) {
        // 设置服务器关闭时的注销逻辑
        const gracefulShutdown = async () => {
          await deregisterServiceInstance(port);
        };

        // 监听 Nitro 关闭事件
        nitroApp.hooks.hook('close', async () => {
          await gracefulShutdown();
        });

        // 监听进程退出事件
        process.on('SIGINT', async () => {
          await gracefulShutdown();
          process.exit(0);
        });

        process.on('SIGTERM', async () => {
          await gracefulShutdown();
          process.exit(0);
        });
      }
    } catch (error) {
      console.error('服务注册错误:', error);
    }
  })();

  // 添加健康检查路由
  nitroApp.hooks.hook('request', async (event) => {
    if (event.path === '/api/lane-manager/health') {
      // 返回健康状态信息
      event.node.res.end(JSON.stringify({
        status: 'ok',
        serviceName: config.serviceName,
        laneId: config.currentLaneId,
        timestamp: new Date().toISOString()
      }));
    }
  });
};
```

#### 最佳实践

1. **模块化设计**：将插件代码分解为多个专门的函数，提高可维护性
2. **错误处理**：使用 try/catch 捕获异常，避免插件错误导致服务器崩溃
3. **资源清理**：在服务器关闭时释放资源，如关闭连接、取消定时器等
4. **日志记录**：使用日志系统记录插件的运行状态和错误信息
5. **类型安全**：使用 TypeScript 类型定义，提高代码质量和开发体验

#### 调试 Nitro 插件

调试 Nitro 插件可以使用以下方法：

**日志输出**：在插件中添加详细的日志输出，记录插件的执行流程和状态

```typescript
logger.info('Nitro 插件初始化');
logger.debug('配置:', config);
```

**环境变量**：使用环境变量控制插件的行为，如启用/禁用功能、设置日志级别等

```typescript
if (process.env.DEBUG_NITRO_PLUGIN === 'true') {
  logger.level = 'debug';
}
```

**健康检查端点**：添加健康检查端点，返回插件的状态信息

```typescript
nitroApp.hooks.hook('request', (event) => {
  if (event.path === '/api/plugin-status') {
    event.node.res.end(JSON.stringify({
      status: 'running',
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      // 其他状态信息
    }));
  }
});
```

**错误监控**：捕获并记录插件中的错误，便于排查问题

```typescript
try {
  // 插件代码
} catch (error) {
  logger.error('插件错误:', error);
  // 可以将错误发送到监控系统
}
```

### 模块配置选项

在 `nuxt.config.ts` 中可以配置以下选项：

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['multi-lane-manager/nuxt'],

  multiLaneManager: {
    // 是否启用泳道功能
    isLaneEnabled: true,

    // 当前泳道 ID
    currentLaneId: 'dev-lane',

    // 服务名称
    serviceName: 'your-service-name',

    // Nacos 服务器地址
    nacosServerAddr: 'localhost',

    // Nacos 服务器端口
    nacosServerPort: '8848',

    // Nacos 命名空间
    nacosNamespace: 'public',

    // Nacos 分组名称
    nacosGroupName: 'DEFAULT_GROUP',

    // 主机名
    host: 'localhost',

    // 目标泳道请求头键名
    targetLaneHeaderKey: 'x-target-lane',

    // 代理请求超时时间（毫秒）
    proxyTimeout: 15000,

    // 注册请求超时时间（毫秒）
    registrationTimeout: 5000,

    // 心跳间隔（毫秒）
    heartbeatInterval: 6000,

    // 实例过期时间（毫秒）
    instanceTtl: 10000
  }
## 多泳道部署示例

### 部署多个泳道实例

```bash
# 启动 dev-lane 泳道实例
NITRO_PORT=3001 LANE_ENABLE=true LANE_ID=dev-lane SERVICE_NAME=your-service npm run dev

# 启动 test-lane 泳道实例
NITRO_PORT=3002 LANE_ENABLE=true LANE_ID=test-lane SERVICE_NAME=your-service npm run dev

### 测试跨泳道请求

```bash
# 向 dev-lane 发送请求，但目标泳道为 test-lane
curl -H "X-Lane-ID: test-lane" http://localhost:3001/api/some-endpoint

# 向 test-lane 发送请求，但目标泳道为 dev-lane
curl -H "X-Lane-ID: dev-lane" http://localhost:3002/api/some-endpoint

# 不指定泳道ID的请求（将尝试路由到 baseline 泳道）
curl http://localhost:3001/api/some-endpoint
```

### baseline 泳道

多泳道管理器引入了 "baseline" 泳道的概念，作为默认的基准泳道：

1. **默认泳道ID**：如果应用启用了泳道功能但没有设置泳道ID，则默认使用 "baseline" 作为泳道ID
2. **智能路由**：当收到一个没有指定泳道ID的请求时：
   - 首先查询 Nacos 是否有 "baseline" 泳道的实例
   - 如果有，则将请求路由到 "baseline" 泳道的实例
   - 如果没有，则在当前实例处理请求

这种设计有以下优势：

- 提供了一个稳定的基准环境（baseline）
- 未指定泳道的请求默认使用基准环境，确保一致的用户体验
- 当基准环境不可用时，自动降级到当前实例处理，提高系统可用性

## 故障排除

### 常见问题

1. **服务注册失败**
   - 检查 Nacos 服务器是否正常运行
   - 检查环境变量是否正确设置
   - 检查网络连接是否正常

2. **心跳发送失败**
   - 检查 Nacos 服务器是否正常运行
   - 检查网络连接是否正常
   - 检查服务实例是否已注册

3. **跨泳道请求转发失败**
   - 检查目标泳道的服务实例是否存在
   - 检查目标泳道的服务实例是否健康
   - 检查网络连接是否正常

4. **实例故障转移**
   - 系统会自动检测实例故障并进行故障转移
   - 故障实例会被加入黑名单，避免重复请求
   - 黑名单实例会在30秒后自动恢复检测
   - 可通过日志查看故障转移过程

### 故障转移机制

multi-lane-manager 内置了完善的故障转移机制来处理发版时的实例不可用问题：

#### 故障检测

系统会自动检测以下类型的故障：

- **连接错误**：`ECONNREFUSED`、`ENOTFOUND`、`ETIMEDOUT`
- **HTTP错误**：502 Bad Gateway、503 Service Unavailable、504 Gateway Timeout
- **请求超时**：`ECONNABORTED`

#### 故障转移流程

1. **实例排序**：按心跳时间对实例进行排序，最近心跳的实例优先
2. **主实例请求**：首先尝试请求选定的目标实例
3. **故障检测**：如果请求失败且符合故障转移条件，记录故障
4. **实例选择**：从同泳道的其他健康实例中选择备用实例
5. **重试请求**：自动转发到备用实例
6. **黑名单管理**：连续故障的实例会被加入黑名单

#### 配置参数

```typescript
const FAILURE_CONFIG = {
  MAX_RETRY_ATTEMPTS: 2,           // 最大重试次数
  FAILURE_THRESHOLD: 3,            // 故障阈值（连续失败次数）
  BLACKLIST_DURATION: 30000,      // 黑名单持续时间（30秒）
  CONNECTION_TIMEOUT: 5000,       // 连接超时时间（5秒）
  RETRY_DELAY: 1000,              // 重试延迟（1秒）
};
```

#### 最佳实践

1. **优雅下线**：在发版时确保旧实例能够优雅地从Nacos注销
2. **健康检查**：配置合适的健康检查端点
3. **监控告警**：监控故障转移频率，及时发现问题
4. **日志分析**：通过日志分析故障原因和转移效果

### 心跳时间排序机制

为了提高服务可用性，multi-lane-manager 实现了基于心跳时间的实例排序机制：

#### 工作原理

1. **心跳时间戳记录**：每次发送心跳时，在元数据中记录时间戳

   ```typescript
   metadata: {
     lastHeartbeat: "2024-01-15T10:30:00.000Z",  // ISO格式时间戳
     heartbeatTimestamp: "1705312200000",         // 毫秒时间戳
     laneId: "prod-lane"
   }
   ```

2. **实例排序**：查询实例时按心跳时间降序排列（最近心跳的在前）
3. **优先选择**：负载均衡时优先选择最近心跳的实例
4. **故障转移**：故障转移时也优先选择最近心跳的备用实例

#### 优势

- **提高可用性**：优先选择最活跃的实例，减少请求失败率
- **快速故障检测**：心跳时间较老的实例可能即将下线
- **平滑发版**：新实例的心跳时间更新，会被优先选择
- **自动恢复**：实例恢复后心跳时间更新，重新获得优先级

#### 配置选项

```typescript
// 获取实例时启用心跳时间排序（默认启用）
const instances = await getNacosLaneInstances(serviceName, laneId, true);

// 禁用心跳时间排序
const instances = await getNacosLaneInstances(serviceName, laneId, false);
```

#### 调试信息

启用调试模式时，可以查看实例的心跳时间排序结果：

```log
📊 实例心跳时间排序结果:
  1. 192.168.1.10:3000 - 心跳时间: 2024-01-15T10:30:00.000Z
  2. 192.168.1.11:3000 - 心跳时间: 2024-01-15T10:29:55.000Z
  3. 192.168.1.12:3000 - 心跳时间: 2024-01-15T10:29:50.000Z
```

### 日志级别

模块提供了详细的日志系统，可以通过环境变量 `LOG_LEVEL` 或 `LANE_LOG_LEVEL` 控制日志输出级别：

```env
# 设置日志级别
LOG_LEVEL=info  # 可选值: silent, fatal, error, warn, info, success, debug, trace, verbose
```

支持的日志级别（从低到高）：

- `silent`：不输出任何日志
- `fatal`：只输出致命错误
- `error`：输出错误信息
- `warn`：输出警告和错误信息
- `info`：输出重要信息、警告和错误（默认级别）
- `success`：输出成功信息和 info 级别以上的日志
- `debug`：输出调试信息和 info 级别以上的日志
- `trace`：输出跟踪信息和 debug 级别以上的日志
- `verbose`：输出所有详细日志

日志格式示例：

```log
[泳道管理] [INFO] 服务器中间件初始化: 启用状态=true, 当前泳道ID=dev-lane
[泳道管理] [DEBUG] 从环境变量获取服务器端口: 3000
[泳道管理] [ERROR] 服务注册错误: 连接超时
```

在开发环境中，建议使用 `debug` 或 `trace` 级别以获取更详细的信息；在生产环境中，建议使用 `info` 或 `warn` 级别以减少日志量。

## API 参考

### 类型定义

```typescript
// 服务实例信息
interface ServiceInstanceInfo {
  ip: string;
  port: number;
  serviceName: string;
  clusterName: string;
  ephemeral: boolean;
  metadata: {
    laneId: string;
    [key: string]: string;
  };
  status: "UP" | "DOWN" | "UNKNOWN";
  lastHeartbeat: number | string;
  version?: string;
  healthy?: boolean;
}

// 泳道信息
interface LaneInfo {
  id: string;
  instances: ServiceInstanceInfo[];
}

// 泳道管理器配置
interface LaneManagerConfig {
  // Nacos 服务器配置
  nacosServerAddr: string;
  nacosServerPort: string;
  nacosUrl: string;
  nacosNamespace: string;
  nacosGroupName: string;

  // 服务配置
  serviceName: string;
  currentLaneId: string;
  host: string;
  port: number | null;

  // 泳道配置
  targetLaneHeaderKey: string; // 小写形式
  isLaneEnabled: boolean;

  // 超时配置
  proxyTimeout: number;
  registrationTimeout: number;
  heartbeatInterval: number; // 心跳间隔，单位毫秒
  instanceTtl: number; // 实例过期时间，单位毫秒

  // 元数据
  metadata: Record<string, any>;
}

// 日志选项
interface LoggerOptions {
  prefix?: string;
  level?: number | string;
  timestamps?: boolean;
}
```

### 导出函数

```typescript
// 创建服务器中间件
function createServerMiddleware(): (event: H3Event) => Promise<void>;

// 注册服务实例
function registerServiceInstance(port: number): Promise<boolean>;

// 注销服务实例
function deregisterServiceInstance(port: number): Promise<boolean>;

// 获取指定泳道的服务实例
function getNacosLaneInstances(serviceName: string, targetLaneId: string): Promise<ServiceInstanceInfo[]>;

// 获取服务器端口
function getServerPort(): number;

// 创建日志管理器
function createLogger(options?: LoggerOptions): ConsolaInstance;

// 获取配置
function getConfig(): LaneManagerConfig;

// 更新配置端口
function updateConfigPort(port: number): void;
```

### 模块结构

```text
packages/multi-lane-manager/
├── src/
│   ├── index.ts                # 主入口文件
│   ├── types.ts                # 类型定义
│   ├── module.ts               # Nuxt 模块定义
│   ├── runtime/
│   │   ├── nitro-plugin.ts     # Nitro 插件（服务注册和健康检查）
│   │   ├── server-middleware.ts # 服务器中间件（请求转发）
│   │   └── server-utils.ts     # 服务器工具函数
│   └── utils/
│       ├── config.ts           # 配置管理
│       ├── logger.ts           # 日志管理
│       ├── nacos.ts            # Nacos 服务管理
│       └── proxy.ts            # 请求转发
└── README.md                   # 文档
```

### 核心文件说明

#### 1. `module.ts`

Nuxt 模块定义文件，负责注册 Nitro 插件和服务器中间件。

```typescript
// module.ts
export default defineNuxtModule({
  meta: {
    name: "multi-lane-manager",
    configKey: "multiLaneManager",
  },
  setup(_options, nuxt) {
    // 添加 Nitro 插件
    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.plugins = nitroConfig.plugins || [];
      nitroConfig.plugins.push(resolve('./runtime/nitro-plugin'));
    });

    // 添加服务器中间件
    addServerHandler({
      handler: resolve('./runtime/server-middleware'),
      middleware: true,
    });
  },
});
```

#### 2. `runtime/nitro-plugin.ts`

Nitro 插件文件，负责服务注册、心跳维持和健康检查。

```typescript
// nitro-plugin.ts
export default (nitroApp) => {
  // 立即注册服务
  (async () => {
    try {
      const port = getServerPort();
      await registerServiceInstance(port);
      // 设置优雅下线
    } catch (error) {
      // 错误处理
    }
  })();

  // 添加健康检查路由
  nitroApp.hooks.hook('request', (event) => {
    if (event.path === '/api/lane-manager/health') {
      // 返回健康状态
    }
  });
};
```

#### 3. `runtime/server-middleware.ts`

服务器中间件文件，负责跨泳道请求转发。

```typescript
// server-middleware.ts
import { createServerMiddleware } from './server-utils';

// 导出中间件函数
export default createServerMiddleware();
```

#### 4. `utils/nacos.ts`

Nacos 服务管理文件，负责服务注册、注销、心跳维持和服务发现。

```typescript
// nacos.ts
export async function registerServiceInstance(port: number): Promise<boolean> {
  // 向 Nacos 注册服务实例
}

export async function deregisterServiceInstance(port: number): Promise<boolean> {
  // 从 Nacos 注销服务实例
}

export async function sendHeartbeat(port: number): Promise<boolean> {
  // 向 Nacos 发送心跳
}

export async function getNacosLaneInstances(
  serviceName: string,
  targetLaneId: string
): Promise<ServiceInstanceInfo[]> {
  // 从 Nacos 获取指定泳道的服务实例
}
```

## 许可证

ISC
