# Consul Deep Dive

> **模块类型**: Service Mesh  
> **模块标识**: `consul`  
> **分析日期**: 2026-04-12  
> **FlyEnv 版本**: 4.13.2

---

## Overview

Consul 是 FlyEnv 集成的一个分布式服务网格解决方案，提供服务发现、服务配置和服务分段功能。在 FlyEnv 中，Consul 作为后台服务运行，通过 agent 模式启动，支持 Web UI 进行可视化管理。

相关文档链接:
- [Base Module](./base.md) - 继承的基类，包含通用服务生命周期管理
- [Nginx](./nginx.md) - 常与 Consul 配合使用的服务发现消费者
- [Service Manager](../components/ServiceManager/index.vue) - 通用服务管理组件

---

## Architecture

### Component Hierarchy Diagram

```
Renderer Process
├── Index.vue (Consul Main Page)
│   ├── Service (Tab 0: Service Control)
│   ├── Manager (Tab 1: Version Management)
│   ├── Config.vue (Tab 2: Config Editor)
│   └── Logs.vue (Tab 3: Log Viewer)
├── aside.vue (Sidebar Control)
│   └── AsideSetup (shared logic)
└── setup.ts (Data Directory State)

Main Process
└── ForkManager
    └── Fork Process
        └── BaseManager
            └── Consul (src/fork/module/Consul/index.ts)
```

### Data Flow Sequence

```
1. User Toggle Switch (aside.vue)
   │
   ▼
2. AsideSetup.switchChange()
   │ IPC: app-fork:consul
   ▼
3. Main Process → ForkManager
   │
   ▼
4. Fork Process (BaseManager.exec())
   │
   ▼
5. Consul Module
   ├── _stopServer() - Stop existing instance
   └── _startServer() - Start new instance
       ├── initConfig() - Generate JSON config
       └── serviceStartExec() - Execute binary
```

### Module Registration

Consul 模块通过 `Module.ts` 注册到 FlyEnv 应用框架：

| Property | Value | Description |
|----------|-------|-------------|
| `moduleType` | `webServer` | 模块分类 |
| `typeFlag` | `consul` | 唯一标识 |
| `label` | `Consul` | 显示名称 |
| `asideIndex` | `3` | 侧边栏排序 |
| `isService` | `true` | 可作为服务启动/停止 |
| `isTray` | `true` | 在托盘菜单显示 |

Sources: src/render/components/Consul/Module.ts:4-14

---

## Data Model

### TypeScript Types

#### Core Module Types

```typescript
// AppModuleEnum definition
enum AppModuleEnum {
  consul = 'consul',
  // ... other modules
}

// Module configuration type
type AppModuleItem = {
  moduleType?: AllAppModuleType
  typeFlag: AllAppModule
  label?: string | LabelFn
  icon?: any
  aside: any
  asideIndex: number
  index: any
  isService?: boolean
  isTray?: boolean
}
```

Sources: src/render/core/type.ts:37-86,97-133

#### Consul Configuration Structure

Consul 使用 JSON 格式配置文件，默认配置结构：

```typescript
interface ConsulConfig {
  server: boolean        // 以服务器模式运行
  bootstrap: boolean     // 引导模式（单节点）
  client_addr: string    // 客户端接口绑定地址
  ui: boolean           // 启用 Web UI
}

// Default configuration generated by initConfig()
{
  "server": true,
  "bootstrap": true,
  "client_addr": "127.0.0.1",
  "ui": true
}
```

Sources: src/fork/module/Consul/index.ts:50-60

#### State Management

**ConsulSetup** - 数据目录持久化状态：

```typescript
export const ConsulSetup: {
  dir: Record<string, string>  // key: bin path, value: data dir
  init: () => void
  save: () => void
} = reactive({
  dir: {},
  init() { /* Load from localForage */ },
  save() { /* Persist to localForage */ }
})
```

Sources: src/render/components/Consul/setup.ts:4-26

---

## Core Components

### Fork Module (src/fork/module/Consul/index.ts)

Consul 类继承自 Base 类，实现特定于 Consul 的服务管理逻辑。

| Method | Parameters | Returns | Description |
|--------|-----------|---------|-------------|
| `init()` | - | `void` | 初始化 PID 文件路径 |
| `initConfig()` | `version: SoftInstalled` | `ForkPromise<string>` | 生成默认 JSON 配置 |
| `_startServer()` | `version: SoftInstalled, DATA_DIR?: string` | `ForkPromise<void>` | 启动 Consul agent |
| `fetchAllOnlineVersion()` | - | `ForkPromise<OnlineVersionItem[]>` | 获取可下载版本 |
| `allInstalledVersions()` | `setup: any` | `ForkPromise<SoftInstalled[]>` | 扫描本地版本 |
| `brewinfo()` | - | `ForkPromise<any>` | 获取 Homebrew 信息 |
| `portinfo()` | - | `ForkPromise<any>` | 获取 MacPorts 信息 |

Sources: src/fork/module/Consul/index.ts:27-244

### Renderer Components

#### Index.vue

主页面组件，提供 4 个标签页：

| Tab Index | Component | Purpose |
|-----------|-----------|---------|
| 0 | Service | 服务启动/停止控制，数据目录选择 |
| 1 | Manager | 版本管理（安装/切换版本） |
| 2 | Config | JSON 配置文件编辑器 |
| 3 | Logs | 日志文件查看器 |

**Data Directory Binding**:
- 默认路径: `{BaseDir}/consul/consul-{majorVersion}-data`
- 支持自定义路径 via `ConsulSetup.dir`
- 使用 `chooseFolder()` 打开目录选择器

Sources: src/render/components/Consul/Index.vue:1-99

#### aside.vue

侧边栏控制组件，提供服务开关和导航功能。

**Key Features**:
- 显示 Consul 运行状态 (via `serviceRunning` computed)
- 切换服务状态 (via `switchChange()`)
- 注册 `startExtParam` 回调提供数据目录参数

**Service Integration**:
```typescript
AppServiceModule.consul = {
  groupDo,       // 分组启动/停止
  switchChange,  // 切换服务状态
  serviceRunning,
  serviceFetching,
  serviceDisabled,
  showItem
}
```

Sources: src/render/components/Consul/aside.vue:1-77

#### Config.vue

配置文件编辑器，使用通用 `Conf` 组件。

| Property | Value |
|----------|-------|
| `type-flag` | `consul` |
| `file-ext` | `conf` (for editor syntax) |
| `file` | `{BaseDir}/consul/consul-{version}.json` |
| `default-file` | `{BaseDir}/consul/consul-{version}.default` |
| `show-commond` | `false` |

Sources: src/render/components/Consul/Config.vue:1-56

#### Logs.vue

日志查看组件，显示 Consul 运行日志。

| Property | Path |
|----------|------|
| `log-file` | `{BaseDir}/consul/consul.log` |

Sources: src/render/components/Consul/Logs.vue:1-20

---

## Lifecycle Management

### Service Startup Flow

```
startService() [Base Class]
    │
    ├── Version validation
    ├── _linkVersion() [Homebrew]
    ├── _stopServer() [Terminate existing]
    └── _startServer() [Consul-specific]
            │
            ├── initConfig() - Create default JSON if missing
            ├── Prepare paths:
            │   ├── baseDir: {BaseDir}/consul
            │   ├── dbPath: {baseDir}/consul-{version}-data
            │   ├── logPath: {baseDir}/consul.log
            │   └── ip: getPrimaryLocalIPAddress()
            │
            └── Execute:
                Windows → serviceStartExecCMD()
                Linux/macOS → serviceStartExec(root=true)
```

### Start Command Construction

```bash
consul agent \
  -config-file="{iniFile}" \
  -data-dir="{dbPath}" \
  -log-file="{logPath}" \
  -bind="{ip}" \
  -pid-file="{pidPath}"
```

Sources: src/fork/module/Consul/index.ts:71-133

### Service Shutdown Flow

继承 Base 类的 `_stopServer()` 方法：

1. **PID Collection**:
   - 读取 `{BaseDir}/pid/consul.pid`
   - 搜索进程名匹配（注意：Consul 未在 `dis` 映射中定义特定进程名）

2. **Process Termination**:
   - Windows: `ProcessKill('-INT', pids)`
   - Linux/macOS: `ProcessKill('-INT', pids)` (default signal)

3. **Cleanup**:
   - 删除 PID 文件
   - 发送日志事件

Sources: src/fork/module/Base/index.ts:123-250

### Configuration Initialization

`initConfig()` 方法在首次启动时创建默认配置：

| Step | Action |
|------|--------|
| 1 | 检查配置文件是否存在 |
| 2 | 创建 `{BaseDir}/consul` 目录（如需要） |
| 3 | 生成默认 JSON 配置 |
| 4 | 同时创建 `.default` 备份文件 |
| 5 | 返回配置文件路径 |

Sources: src/fork/module/Consul/index.ts:37-69

---

## Configuration

### File Locations

| File Type | Path Pattern | Description |
|-----------|--------------|-------------|
| Config | `{BaseDir}/consul/consul-{major}.json` | 主配置文件 |
| Default | `{BaseDir}/consul/consul-{major}.default` | 默认配置备份 |
| Data | `{BaseDir}/consul/consul-{major}-data` | 数据目录（可自定义） |
| Log | `{BaseDir}/consul/consul.log` | 运行日志 |
| PID | `{BaseDir}/consul/consul.pid` | 进程 ID 文件 |

### Default Configuration

```json
{
  "server": true,
  "bootstrap": true,
  "client_addr": "127.0.0.1",
  "ui": true
}
```

**配置说明**:
- `server: true` - 以服务器模式运行（非客户端模式）
- `bootstrap: true` - 启用引导模式（适用于单节点开发环境）
- `client_addr` - HTTP API 和 UI 监听地址
- `ui: true` - 启用内置 Web UI

Sources: src/fork/module/Consul/index.ts:50-62

---

## API/IPC Interface

### IPC Command Protocol

Consul 模块通过 `app-fork:consul` 频道通信。

| Command | Parameters | Action | Returns |
|---------|-----------|--------|---------|
| `initConfig` | `version: SoftInstalled` | 初始化配置文件 | `string` (file path) |
| `startService` | `version: SoftInstalled, DATA_DIR?: string` | 启动服务 | `{APP-Service-Start-PID: string}` |
| `stopService` | `version: SoftInstalled` | 停止服务 | `{APP-Service-Stop-PID: string[]}` |
| `fetchAllOnlineVersion` | - | 获取在线版本 | `OnlineVersionItem[]` |
| `allInstalledVersions` | `setup: any` | 扫描本地版本 | `SoftInstalled[]` |
| `brewinfo` | - | Homebrew 信息 | `any` |
| `portinfo` | - | MacPorts 信息 | `any` |

Sources: src/fork/module/Base/index.ts:34-43, src/fork/module/Consul/index.ts

### IPC Usage Examples

**Initialize Config** (Config.vue):
```typescript
IPC.send(
  'app-fork:consul',
  'initConfig',
  JSON.parse(JSON.stringify(currentVersion.value))
).then((key: string) => {
  IPC.off(key)
  conf?.value?.update()
})
```

Sources: src/render/components/Consul/Config.vue:44-55

---

## Platform Differences

| Feature | macOS | Windows | Linux |
|---------|-------|---------|-------|
| Binary Name | `consul` | `consul.exe` | `consul` |
| Execution | `serviceStartExec(root: false)` | `serviceStartExecCMD()` | `serviceStartExec(root: true)` |
| Install Path | `{AppDir}/consul/{version}/consul` | `{AppDir}/consul/{version}/consul.exe` | `{AppDir}/consul/{version}/consul` |
| Package Format | `.zip` | `.zip` | `.zip` |
| Version Source | Homebrew, MacPorts, Manual | Manual | Manual |

**Notes**:
- Linux 需要 root 权限启动 (`root: true`)
- Windows 使用 `serviceStartExecCMD` 而非 `serviceStartExec`
- 所有平台使用相同的 ZIP 解压逻辑

Sources: src/fork/module/Consul/index.ts:93-131,135-162

---

## Version Management

### Online Versions

```typescript
fetchAllOnlineVersion() {
  // Fetches from https://api.one-env.com/api/version/fetch
  // Platform-specific parameters:
  // - macOS: os=mac, arch=x86|arm
  // - Windows: os=win, arch=x86
  // - Linux: os=linux, arch=x86|arm
}
```

### Local Version Detection

**Binary Version Parsing**:
- Command: `"{bin}" version`
- Regex: `/(v)(\d+(\.\d+){1,4})(.*?)/g`
- Example: `v1.17.0` → version `1.17.0`

Sources: src/fork/module/Consul/index.ts:135-203

---

## UI Components

### Tab Navigation (Index.vue)

```
┌─────────────────────────────────────────────┐
│ [Service] [Version Manager] [Config] [Log]  │
├─────────────────────────────────────────────┤
│                                             │
│  Content Area                               │
│                                             │
└─────────────────────────────────────────────┘
```

### Service Tab Layout

```
┌─────────────────────────────────────────────┐
│ Data Dir: /path/to/data  [Edit Button]      │
├─────────────────────────────────────────────┤
│                                             │
│  [Start/Stop Button]  [Status Indicator]    │
│                                             │
└─────────────────────────────────────────────┘
```

### Sidebar Item (aside.vue)

```
┌─────────────────────────────────────────────┐
│ [Consul Icon]  Consul              [Switch] │
└─────────────────────────────────────────────┘
```

---

## Integration Points

### BrewStore Module

Consul 与其他服务共享版本管理状态：

```typescript
const brewStore = BrewStore()
const currentVersion = computed(() => brewStore.currentVersion('consul'))
const module = brewStore.module('consul')
```

### AppServiceModule Registration

用于分组操作（一键启动/停止所有服务）：

```typescript
AppServiceModule.consul = {
  groupDo,       // (isRunning: boolean) => Promise[]
  switchChange,  // () => void
  serviceRunning,
  serviceFetching,
  serviceDisabled,
  showItem
}
```

Sources: src/render/components/Consul/aside.vue:69-76

---

## Troubleshooting

### Common Issues

| Issue | Possible Cause | Solution |
|-------|---------------|----------|
| Config not created | Directory permission | Check `{BaseDir}/consul` writable |
| Service won't start | Port conflict | Check 8300-8302, 8500 ports |
| Data dir not found | Custom path invalid | Reset via UI or clear localForage |
| Version not detected | Binary not executable | Check file permissions |

### Debug Commands

Check Consul status manually:
```bash
# Check version
consul version

# Validate config
consul validate /path/to/consul.json

# Check members
consul members

# View logs
tail -f ~/Library/Application\ Support/FlyEnv/consul/consul.log
```

---

## Sources Summary

| File | Lines | Purpose |
|------|-------|---------|
| `src/fork/module/Consul/index.ts` | 1-244 | 后端服务管理逻辑 |
| `src/fork/module/Base/index.ts` | 1-447 | 基类，服务生命周期 |
| `src/render/components/Consul/Module.ts` | 1-15 | 模块注册定义 |
| `src/render/components/Consul/Index.vue` | 1-99 | 主页面组件 |
| `src/render/components/Consul/aside.vue` | 1-77 | 侧边栏控制 |
| `src/render/components/Consul/Config.vue` | 1-56 | 配置编辑器 |
| `src/render/components/Consul/Logs.vue` | 1-20 | 日志查看器 |
| `src/render/components/Consul/setup.ts` | 1-26 | 数据目录状态 |
| `src/render/core/type.ts` | 1-174 | 类型定义 |
| `src/render/core/Module.ts` | 1-159 | 模块工具函数 |
| `src/render/core/ASide.ts` | 1-122 | 侧边栏共享逻辑 |

---

*文档遵循 DeepWiki 技术分析标准*
