故障排除.md 27 KB

故障排除

本文档引用的文件

  • docs/app-troubleshooting.md
  • server/src/app.ts
  • server/src/config/index.ts
  • server/src/middleware/errorHandler.ts
  • server/src/services/logger.service.ts
  • server/src/modules/tts/tts.service.ts
  • server/src/modules/player/player.service.ts
  • server/src/services/storage.service.ts
  • server/src/services/oss.service.ts
  • server/src/services/redis.service.ts
  • server/src/services/websocket.service.ts
  • server/src/middleware/performance.ts
  • server/prisma/schema.prisma

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排除指南
  9. 结论
  10. 附录

简介

本故障排除文档面向AI有声书生成平台的运维与开发团队,聚焦以下典型问题:

  • TTS服务异常(提供商切换、额度限制、实时模式禁用)
  • 音频生成失败(文件系统状态、失败标记、僵尸任务)
  • 播放器问题(章节合并、播放进度、音频URL)
  • 数据库连接错误(Prisma/MySQL配置、索引与字段)
  • 存储与CDN问题(OSS/本地存储、签名URL、连接测试)
  • 缓存问题(Redis连接、键操作、过期策略)
  • WebSocket推送(生成完成事件、广播与客户端管理)
  • 日志与错误处理(Winston日志、HTTP请求日志、自定义错误类)
  • 性能问题(响应时间、慢请求阈值、指标聚合)
  • 网络与第三方服务(阿里云OSS、DashScope/Minimax TTS)
  • 系统资源与部署(健康检查、优雅关闭、静态资源)

项目结构

后端采用Koa框架,模块化组织TTS、播放器、书籍生成、队列、鉴权、支付等业务;前端基于uni-app,提供App/H5/小程序多端运行。

graph TB
subgraph "服务端"
A["应用入口<br/>server/src/app.ts"]
B["配置中心<br/>server/src/config/index.ts"]
C["错误处理中间件<br/>server/src/middleware/errorHandler.ts"]
D["日志服务<br/>server/src/services/logger.service.ts"]
E["TTS服务<br/>server/src/modules/tts/tts.service.ts"]
F["播放器服务<br/>server/src/modules/player/player.service.ts"]
G["存储服务<br/>server/src/services/storage.service.ts"]
H["OSS服务<br/>server/src/services/oss.service.ts"]
I["Redis服务<br/>server/src/services/redis.service.ts"]
J["WebSocket服务<br/>server/src/services/websocket.service.ts"]
K["性能监控中间件<br/>server/src/middleware/performance.ts"]
L["数据库Schema<br/>server/prisma/schema.prisma"]
end
A --> B
A --> C
A --> D
A --> E
A --> F
A --> G
G --> H
A --> I
A --> J
A --> K
A --> L

图示来源

  • server/src/app.ts:133-194
  • server/src/config/index.ts:69-117
  • server/src/middleware/errorHandler.ts:3-67
  • server/src/services/logger.service.ts:68-114
  • server/src/modules/tts/tts.service.ts:201-280
  • server/src/modules/player/player.service.ts:147-234
  • server/src/services/storage.service.ts:43-49
  • server/src/services/oss.service.ts:38-57
  • server/src/services/redis.service.ts:43-45
  • server/src/services/websocket.service.ts:102-136
  • server/src/middleware/performance.ts:29-76
  • server/prisma/schema.prisma:10-472

章节来源

  • server/src/app.ts:57-131

核心组件

  • 应用入口与中间件链:健康检查、CORS、体解析、静态资源、性能监控、HTTP/Winston日志、安全中间件、Sentry错误上报、路由注册。
  • 配置中心:加载.env,统一管理模型、TTS提供商、JWT、上传目录、Redis/OSS等。
  • 错误处理与自定义错误类:统一错误响应、开发环境堆栈返回、400/401/403/404/429等。
  • 日志服务:控制台、错误文件、综合文件、HTTP请求文件,支持请求耗时统计。
  • TTS服务:提供商工厂(Minimax/Aliyun/Mock)、文本分段、并发生成、合并与上传、LRC歌词生成、状态查询、预览音频。
  • 播放器服务:播放进度持久化、章节合并音频、最近播放记录。
  • 存储服务:OSS/本地无缝切换、上传/下载/删除/签名URL、连接测试。
  • 缓存服务:Redis连接、GET/SET/JSON/HASH/计数器、批量删除、过期、存在性检查。
  • WebSocket服务:客户端注册/广播/事件推送(生成完成)。
  • 性能监控:慢请求阈值、端点维度统计、错误率计算。
  • 数据库Schema:用户、书籍、章节、播放记录、订单、订阅等实体与索引。

章节来源

  • server/src/app.ts:133-194
  • server/src/config/index.ts:69-117
  • server/src/middleware/errorHandler.ts:27-67
  • server/src/services/logger.service.ts:68-114
  • server/src/modules/tts/tts.service.ts:160-190
  • server/src/modules/player/player.service.ts:147-234
  • server/src/services/storage.service.ts:43-49
  • server/src/services/redis.service.ts:43-45
  • server/src/services/websocket.service.ts:102-136
  • server/src/middleware/performance.ts:29-76
  • server/prisma/schema.prisma:10-472

架构总览

系统由Koa应用承载,通过中间件链处理请求,路由分发至各模块控制器;TTS服务负责音频合成与上传,播放器服务负责章节合并与播放进度;存储层支持OSS与本地;缓存层为Redis;日志与性能监控贯穿全链路;数据库使用Prisma/MySQL。

graph TB
Client["客户端/浏览器/App"]
Koa["Koa应用<br/>server/src/app.ts"]
MW1["错误处理<br/>errorHandler.ts"]
MW2["性能监控<br/>performance.ts"]
MW3["HTTP日志<br/>logger.service.ts"]
Routers["路由注册<br/>/api/*"]
TTS["TTS服务<br/>tts.service.ts"]
Player["播放器服务<br/>player.service.ts"]
Store["存储服务<br/>storage.service.ts"]
OSS["OSS服务<br/>oss.service.ts"]
Redis["Redis服务<br/>redis.service.ts"]
WS["WebSocket服务<br/>websocket.service.ts"]
DB["数据库<br/>Prisma/MySQL"]
Client --> Koa
Koa --> MW1
Koa --> MW2
Koa --> MW3
Koa --> Routers
Routers --> TTS
Routers --> Player
TTS --> Store
Store --> OSS
Player --> DB
TTS --> DB
Koa --> Redis
Koa --> WS
Koa --> DB

图示来源

  • server/src/app.ts:57-131
  • server/src/middleware/errorHandler.ts:3-24
  • server/src/middleware/performance.ts:29-76
  • server/src/services/logger.service.ts:75-102
  • server/src/modules/tts/tts.service.ts:201-280
  • server/src/modules/player/player.service.ts:147-234
  • server/src/services/storage.service.ts:43-49
  • server/src/services/oss.service.ts:38-57
  • server/src/services/redis.service.ts:43-45
  • server/src/services/websocket.service.ts:102-136

详细组件分析

TTS服务与音频生成

  • 提供商选择优先级:Minimax → 阿里云HTTP → Mock;若指定提供商则按优先级尝试。
  • 文本分段:限制每段最大字符数,按段落与句子切分,超长强制截断。
  • 并发策略:Minimax异步轮询较长,限制并发;其他并发2。
  • 云端URL降级:下载云端音频失败时回退到本地文件合并上传。
  • 状态查询:基于文件系统检查失败标记与输出文件,空目录超时判定为僵尸任务。
  • LRC歌词:按字速估算时间戳生成。
  • 预览音频:短文本快速生成,Mock模式生成占位文件。

    sequenceDiagram
    participant C as "客户端"
    participant T as "TTS服务"
    participant P as "提供商(阿里云/Minimax/Mock)"
    participant M as "音频合并器"
    participant S as "存储服务"
    participant W as "WebSocket"
    C->>T : "提交生成请求"
    T->>T : "选择提供商/分段/并发"
    loop "按批生成"
    T->>P : "合成音频片段"
    P-->>T : "本地文件/云端URL"
    end
    alt "存在云端URL"
    T->>T : "下载云端音频"
    T->>S : "上传到OSS/本地"
    else "仅本地文件"
    T->>M : "合并音频"
    T->>S : "上传到OSS/本地"
    end
    T->>T : "生成LRC歌词/更新章节/记录"
    T->>W : "推送生成完成事件"
    T-->>C : "返回音频URL/状态"
    

图示来源

  • server/src/modules/tts/tts.service.ts:285-542
  • server/src/modules/tts/tts.service.ts:547-597
  • server/src/services/storage.service.ts:43-49
  • server/src/services/websocket.service.ts:70-76

章节来源

  • server/src/modules/tts/tts.service.ts:201-280
  • server/src/modules/tts/tts.service.ts:547-597

播放器服务与章节合并

  • 合并逻辑:仅对章(level=1)进行合并,收集其下所有节(level=2)的小节(level=3)音频,按序合并并更新章节URL。
  • 进度管理:upsert播放进度,支持更新与删除。
  • 最近播放:关联书籍封面与标题,计算进度百分比。

    flowchart TD
    Start(["开始"]) --> CheckLevel["检查章节级别(level=1?)"]
    CheckLevel --> |否| ReturnUrl["返回原音频URL"]
    CheckLevel --> |是| ListSections["列出子节(level=2)"]
    ListSections --> HasSections{"是否有子节?"}
    HasSections --> |否| ReturnNull["返回null"]
    HasSections --> |是| ListSubs["列出小节(level=3)音频"]
    ListSubs --> HasAudios{"是否有音频?"}
    HasAudios --> |否| ReturnNull
    HasAudios --> |是| Merge["合并音频并写入uploads"]
    Merge --> Update["更新章节audioUrl"]
    Update --> Done(["结束"])
    

图示来源

  • server/src/modules/player/player.service.ts:147-234

章节来源

  • server/src/modules/player/player.service.ts:147-234

存储与OSS服务

  • 存储类型:OSS或本地,可通过环境变量切换。
  • 上传/下载/删除/签名URL:统一接口,OSS支持签名URL与批量删除。
  • 连接测试:本地创建/删除测试文件,OSS获取Bucket信息。

    classDiagram
    class StorageService {
    -storageType
    +uploadAudio()
    +uploadVideo()
    +uploadCover()
    +uploadFile()
    +uploadBuffer()
    +deleteFile()
    +deleteDirectory()
    +downloadFile()
    +getSignedUrl()
    +testConnection()
    }
    class OSSService {
    -client
    -bucket
    -cdnDomain
    +uploadFile()
    +uploadBuffer()
    +uploadAudio()
    +uploadVideo()
    +uploadCover()
    +deleteFile()
    +deleteDirectory()
    +getSignedUrl()
    +downloadFile()
    +getFileUrl()
    +testConnection()
    }
    StorageService --> OSSService : "OSS模式委托"
    

图示来源

  • server/src/services/storage.service.ts:13-278
  • server/src/services/oss.service.ts:13-256

章节来源

  • server/src/services/storage.service.ts:43-49
  • server/src/services/oss.service.ts:38-57

错误处理与日志

  • 自定义错误类:AppError、UnauthorizedError、ForbiddenError、NotFoundError、BadRequestError、QuotaExceededError。
  • HTTP错误中间件:捕获异常、记录错误、返回统一格式、开发环境附加堆栈。
  • Winston日志:控制台、错误文件、综合文件、HTTP文件,记录请求耗时与用户代理。

    sequenceDiagram
    participant Client as "客户端"
    participant App as "Koa应用"
    participant MW as "错误处理中间件"
    participant Log as "Winston日志"
    Client->>App : "请求"
    App->>MW : "进入中间件链"
    MW-->>App : "抛出错误"
    App->>Log : "记录错误与堆栈"
    App-->>Client : "统一错误响应"
    

图示来源

  • server/src/middleware/errorHandler.ts:3-24
  • server/src/services/logger.service.ts:75-102

章节来源

  • server/src/middleware/errorHandler.ts:27-67
  • server/src/services/logger.service.ts:68-114

性能监控与指标

  • 慢请求阈值:默认1秒;记录端点维度的平均/最大耗时与错误数。
  • 指标路由:返回总请求数、平均响应时间、慢请求数、错误数、端点明细与错误率。

    flowchart TD
    Req["请求到达"] --> Start["记录开始时间"]
    Start --> Next["执行后续中间件/路由"]
    Next --> Ok{"是否成功?"}
    Ok --> |是| Calc["计算耗时并更新指标"]
    Ok --> |否| Err["错误计数+端点错误计数"]
    Calc --> Slow{"是否慢请求?"}
    Slow --> |是| Warn["记录慢请求警告"]
    Slow --> |否| Resp["设置响应头X-Response-Time"]
    Err --> Throw["抛出错误"]
    Resp --> End["返回响应"]
    Throw --> End
    

图示来源

  • server/src/middleware/performance.ts:29-76
  • server/src/middleware/performance.ts:99-110

章节来源

  • server/src/middleware/performance.ts:29-76

数据库与实体关系

  • 用户、书籍、章节、播放记录、订单、订阅、Token用量、播放列表等。
  • 关键索引:用户phone/openid、订单userId/status/orderNo、播放记录userId/chapterId唯一、书籍userId/status等。

    erDiagram
    USER {
    int id PK
    string phone UK
    string openid UK
    string nickname
    string avatar
    int memberLevel
    datetime memberExpireAt
    int dailyUsage
    string lastUsageDate
    int usedAudioMinutes
    datetime subscriptionResetDate
    datetime createdAt
    datetime updatedAt
    }
    BOOK {
    int id PK
    int userId
    string title
    string subtitle
    text description
    string coverUrl
    string targetAudience
    string style
    string bookScale
    int totalChapters
    int estimatedWords
    int progress
    boolean isPublished
    longtext outlineJson
    text foreword
    text afterword
    text errorMsg
    string failedStage
    string genStage
    string status
    text bookAnalysis
    datetime createdAt
    datetime updatedAt
    }
    BOOKCHAPTER {
    int id PK
    int bookId FK
    int parentId
    int level
    int number
    string title
    longtext content
    int wordCount
    text contentError
    datetime generatedAt
    string audioUrl
    int audioDuration
    string videoUrl
    int videoDuration
    boolean isPublic
    string genStage
    longtext lrcLyrics
    string status
    datetime createdAt
    datetime updatedAt
    }
    PLAYRECORD {
    int id PK
    int userId FK
    int chapterId FK
    float progress
    float duration
    datetime createdAt
    datetime updatedAt
    }
    ORDER {
    int id PK
    int userId
    string orderNo UK
    int planId
    string productType
    decimal amount
    string status
    string paymentMethod
    string paymentId
    datetime paidAt
    datetime createdAt
    datetime updatedAt
    }
    SUBSCRIPTIONPLAN {
    int id PK
    string name
    int level
    decimal priceMonthly
    decimal priceYearly
    text description
    text features
    boolean isRecommended
    boolean isActive
    int sortOrder
    int dailyGenerations
    int perGenerationLimit
    int monthlyTokens
    int monthlyMinutes
    int yearlyTokens
    int voiceOptions
    string audioQuality
    boolean apiAccess
    boolean batchProcessing
    boolean teamManagement
    boolean overageEnabled
    decimal overagePrice
    datetime createdAt
    datetime updatedAt
    }
    SUBSCRIPTION {
    int id PK
    int userId
    int planId FK
    datetime startDate
    datetime endDate
    string status
    boolean autoRenew
    datetime createdAt
    datetime updatedAt
    }
    TOKENBALANCE {
    int id PK
    int userId UK
    int totalTokens
    int usedTokens
    datetime resetDate
    datetime createdAt
    datetime updatedAt
    }
    TOKENUSAGE {
    int id PK
    int userId
    string type
    int amount
    int contentLength
    int orderId
    text description
    datetime createdAt
    }
    AUDIORECORD {
    int id PK
    int userId
    string audioId UK
    string title
    longtext text
    int wordCount
    string voiceId
    string voiceParams
    string audioUrl
    int audioDuration
    int audioSize
    string status
    text errorMsg
    int bookId
    datetime createdAt
    datetime updatedAt
    }
    USER ||--o{ BOOK : "拥有"
    BOOK ||--o{ BOOKCHAPTER : "包含"
    USER ||--o{ PLAYRECORD : "播放"
    BOOKCHAPTER ||--o{ PLAYRECORD : "被播放"
    USER ||--o{ ORDER : "下单"
    SUBSCRIPTIONPLAN ||--o{ SUBSCRIPTION : "被订阅"
    USER ||--o{ SUBSCRIPTION : "订阅"
    USER ||--o{ TOKENBALANCE : "拥有"
    USER ||--o{ TOKENUSAGE : "产生"
    ORDER ||--o{ TOKENUSAGE : "关联"
    AUDIORECORD }o--|| BOOKCHAPTER : "属于章节"
    

图示来源

  • server/prisma/schema.prisma:10-472

章节来源

  • server/prisma/schema.prisma:10-472

依赖关系分析

  • 应用启动顺序:Sentry初始化 → 数据库连接 → Redis连接测试 → 存储连接测试 → 订阅套餐初始化 → WebSocket初始化 → 启动监听 → 书籍生成队列初始化与中断任务恢复。
  • 关键耦合点:TTS服务依赖存储服务与WebSocket;播放器服务依赖数据库与合并器;存储服务依赖OSS或本地文件系统;Redis提供缓存能力;日志与性能中间件贯穿全链路。

    graph LR
    App["server/src/app.ts"] --> Sentry["Sentry初始化"]
    App --> DB["connectDatabase()"]
    App --> Redis["redisService.testConnection()"]
    App --> Storage["storageService.testConnection()"]
    App --> WS["initWebSocket()"]
    App --> Queue["initBookGenerationQueue()"]
    TTS["tts.service.ts"] --> Storage
    TTS --> WS
    Player["player.service.ts"] --> DB
    

图示来源

  • server/src/app.ts:133-194
  • server/src/modules/tts/tts.service.ts:201-280
  • server/src/modules/player/player.service.ts:147-234

章节来源

  • server/src/app.ts:133-194

性能考虑

  • 慢请求阈值:1秒;超过阈值记录警告并更新指标。
  • 并发策略:TTS对不同提供商采用不同并发,避免阻塞。
  • 日志级别:生产环境降低控制台冗余,保留HTTP/错误文件。
  • 静态资源:/uploads与/public/videos静态托管,减少IO压力。
  • 缓存:Redis提供键值缓存与Hash,支持批量删除与过期控制。

章节来源

  • server/src/middleware/performance.ts:29-76
  • server/src/services/logger.service.ts:18-72
  • server/src/app.ts:85-89
  • server/src/services/redis.service.ts:135-149

故障排除指南

一、TTS服务异常

  • 现象
    • 生成失败、状态为failed、失败标记文件存在。
    • 额度限制触发,提供商切换。
    • 实时模式禁用,使用HTTP分段模式。
  • 诊断步骤
    • 查看TTS调试日志与文件系统状态:检查失败标记与输出文件。
    • 确认提供商API Key配置与可用性。
    • 检查文本分段是否超限,确认LRC歌词生成。
  • 解决方案
    • 切换到备用提供商或等待额度恢复。
    • 调整文本长度或分段策略。
    • 检查网络与第三方服务可用性。

章节来源

  • server/src/modules/tts/tts.service.ts:518-542
  • server/src/modules/tts/tts.service.ts:547-597
  • server/src/modules/tts/tts.service.ts:91-96

二、音频生成失败

  • 现象
    • 输出文件缺失、失败标记存在、僵尸任务判定。
  • 诊断步骤
    • 检查上传目录是否存在、文件数量与最后修改时间。
    • 查看数据库中AudioRecord状态与错误信息。
  • 解决方案
    • 清理僵尸任务并重试生成。
    • 检查磁盘空间与权限。

章节来源

  • server/src/modules/tts/tts.service.ts:547-597

三、播放器问题

  • 现象
    • 章节合并失败、播放进度丢失、音频URL为空。
  • 诊断步骤
    • 检查章节级别与子项是否存在。
    • 确认小节音频URL是否有效。
    • 查询播放记录是否存在。
  • 解决方案
    • 手动触发章节合并或修复子项。
    • 恢复播放记录或重新生成。

章节来源

  • server/src/modules/player/player.service.ts:147-234
  • server/src/modules/player/player.service.ts:101-122

四、数据库连接错误

  • 现象
    • 启动时报数据库连接失败、迁移异常。
  • 诊断步骤
    • 检查DATABASE_URL配置与数据库可达性。
    • 核对Prisma Schema中的表与索引。
  • 解决方案
    • 修正连接字符串与凭据。
    • 执行Prisma迁移或同步。

章节来源

  • server/src/app.ts:138-140
  • server/prisma/schema.prisma:5-8

五、存储与CDN问题

  • 现象
    • 上传失败、下载异常、签名URL不可用。
  • 诊断步骤
    • 测试存储连接(本地/oss)。
    • 检查OSS Bucket与凭证配置。
  • 解决方案
    • 切换存储模式或修复OSS配置。
    • 生成签名URL并验证CDN域名。

章节来源

  • server/src/services/storage.service.ts:252-272
  • server/src/services/oss.service.ts:241-250

六、缓存问题(Redis)

  • 现象
    • 缓存不可用、键操作失败、批量删除异常。
  • 诊断步骤
    • 检查Redis连接状态与重试策略。
    • 验证键存在性、过期与Hash字段。
  • 解决方案
    • 重启Redis或调整重连策略。
    • 使用批量删除清理缓存。

章节来源

  • server/src/services/redis.service.ts:13-38
  • server/src/services/redis.service.ts:135-149

七、WebSocket推送问题

  • 现象
    • 生成完成后未收到推送、客户端未连接。
  • 诊断步骤
    • 检查WebSocket初始化与升级请求。
    • 确认客户端clientId与连接状态。
  • 解决方案
    • 重新连接并确保事件广播。

章节来源

  • server/src/services/websocket.service.ts:102-136

八、日志与错误处理

  • 现象
    • 错误未被捕获、堆栈未输出、HTTP日志缺失。
  • 诊断步骤
    • 检查错误处理中间件与Winston配置。
    • 查看error.log与http.log。
  • 解决方案
    • 确保中间件顺序正确,开启开发环境堆栈。

章节来源

  • server/src/middleware/errorHandler.ts:3-24
  • server/src/services/logger.service.ts:75-102

九、性能问题排查

  • 现象
    • 响应时间长、慢请求增多、错误率上升。
  • 诊断步骤
    • 通过/api/metrics查看指标。
    • 分析慢请求端点与错误分布。
  • 解决方案
    • 优化慢端点、调整并发、增加缓存。

章节来源

  • server/src/middleware/performance.ts:99-110

十、网络与第三方服务

  • 现象
    • TTS提供商不可用、OSS上传超时。
  • 诊断步骤
    • 检查网络连通性与超时配置。
    • 验证API Key与配额。
  • 解决方案
    • 切换提供商或提升配额。

章节来源

  • server/src/config/index.ts:84-93
  • server/src/services/oss.service.ts:38-57

十一、系统资源不足

  • 现象
    • 磁盘空间不足、内存占用高、CPU飙升。
  • 诊断步骤
    • 检查上传目录大小与文件句柄。
    • 监控进程内存/CPU使用。
  • 解决方案
    • 清理历史文件与缓存,扩容资源。

章节来源

  • server/src/app.ts:160-166

十二、App端问题(参考)

  • 现象
    • App白屏、正则不兼容、平台名大小写不一致、H5特有API不支持、JSON循环引用、CSS gap不兼容。
  • 诊断步骤
    • 检查marked版本、平台判断函数、API条件编译。
  • 解决方案
    • 降级包版本、修正平台判断、使用条件编译与替代API。

章节来源

  • docs/app-troubleshooting.md:3-28
  • docs/app-troubleshooting.md:62-91
  • docs/app-troubleshooting.md:93-136
  • docs/app-troubleshooting.md:139-166
  • docs/app-troubleshooting.md:168-201

结论

本故障排除文档围绕TTS生成、播放器、存储、缓存、日志、性能与第三方服务等关键环节提供了系统化的诊断与解决路径。建议在生产环境中:

  • 启用Sentry与Winston日志,定期巡检慢请求与错误率。
  • 配置多提供商与额度监控,实现自动切换。
  • 使用Redis缓存热点数据,合理设置过期策略。
  • 定期清理上传目录与OSS历史文件,保障磁盘空间。
  • 建立健康检查与优雅关闭流程,确保服务稳定。

附录

  • 常用命令与路径
    • 启动服务:node server/src/app.ts
    • 日志目录:server/logs
    • 上传目录:server/uploads
    • 健康检查:GET /health
    • 指标查询:GET /api/metrics
  • 环境变量
    • DATABASE_URL、DASHSCOPE_APIKEY、OSS*、REDIS_*、STORAGE_TYPE、NODE_ENV、PORT等