feat(aia): Complete AIA V2.0 with universal streaming capabilities

Major Changes:
- Add StreamingService with OpenAI Compatible format
- Upgrade Chat component V2 with Ant Design X integration
- Implement AIA module with 12 intelligent agents
- Update API routes to unified /api/v1 prefix
- Update system documentation

Backend (~1300 lines):
- common/streaming: OpenAI Compatible adapter
- modules/aia: 12 agents, conversation service, streaming integration
- Update route versions (RVW, PKB to v1)

Frontend (~3500 lines):
- modules/aia: AgentHub + ChatWorkspace (100% prototype restoration)
- shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook
- Update API endpoints to v1

Documentation:
- AIA module status guide
- Universal capabilities catalog
- System overview updates
- All module documentation sync

Tested: Stream response verified, authentication working
Status: AIA V2.0 core completed (85%)
This commit is contained in:
2026-01-14 19:15:01 +08:00
parent 3d35e9c58b
commit 1b53ab9d52
386 changed files with 52096 additions and 65238 deletions

View File

@@ -1,67 +1,56 @@
# 云原生部署架构指南
> **文档版本:** V1.0
> **创建日期:** 2025-11-16
> **适用对象:** 后端开发、架构师、运维
# 鈭穃<EFBFBD><EFBFBD><EFBFBD>蝵脫沲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
> **<2A><><EFBFBD><EFB99D>𧋦嚗?* V1.0
> **<EFBFBD>𥕦遣<EFBFBD><EFBFBD>嚗?* 2025-11-16
> **<EFBFBD><EFBFBD>鍂撖寡情嚗?* <20>𡒊垢撘<E59EA2><E69298><EFBFBD><E3BBAB><EFBFBD><E6B2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝏?
> **蝏湔擪<E6B994><E693AA><EFBFBD>** <20><EFBFBD><E59786><EFBFBD>
> **状态:** ✅ 已完成
> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
---
## <20><> <20><>﹝霂湔<E99C82>
本文档提供 **AI临床研究平台** 部署到阿里云 Serverless 架构的完整指南。
> **⭐ 重要更新2025-11-16**
> 平台基础设施的详细实施计划和代码实现已迁移到:
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>靘?**AI銝游<E98A9D><E6B8B8>𠉛弦撟喳蝱** <20>函蔡<E587BD>圈燵<E59C88><EFBFBD> Serverless <20><EFBFBD><E59786><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B994>𨰜<EFBFBD>?
> **潃?<3F><EFBFBD><E6BBA9>湔鰵嚗?025-11-16嚗?*嚗?
> 撟喳蝱<EFBFBD><EFBFBD>霈暹鴌<EFBFBD><EFBFBD>祕蝏<EFBFBD><EFBFBD><EFBFBD>質恣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>摰䂿緵撌脰<EFBFBD>蝘餃<EFBFBD>嚗?
> **[撟喳蝱<E596B3><EFBFBD>霈暹鴌閫<E9B48C><E996AB>](./04-撟喳蝱<E596B3><EFBFBD>霈暹鴌閫<E9B48C><E996AB>.md)**
>
> 本文档聚焦于:
> - 云原生架构总体设计
> - 阿里云服务选型和配置
> - Docker容器化和部署流程
> - 成本估算和监控告警
**文档定位**
- 本文档03**云原生部署架构总览** - 侧重云服务和部署流程
- 04文档**平台基础设施规划** - 侧重代码实现和开发指南
**阅读时间**20 分钟
**实施时间**:参见 [平台基础设施规划](./04-平台基础设施规划.md) 的2.5天实施计划
> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?> - 鈭穃<E988AD><E7A983><EFBFBD><EFBFBD><E6B2B2><EFBFBD><EFBFBD>霈曇恣
> - <EFBFBD><EFBFBD>鈭烐<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝵?> - Docker摰孵膥<E5ADB5><EFBFBD><E7A18B>函蔡瘚<E894A1><E7989A>
> - <EFBFBD>鞉𧋦隡啁<EFBFBD><EFBFBD>𣬚<EFBFBD><EFBFBD><EFBFBD>霅?
**<2A><>﹝摰帋<E691B0>**嚗?- <20><EFBFBD><EFBFBD><E78DA2>03嚗㚁<E59A97>**鈭穃<E988AD><E7A983><EFBFBD>蝵脫沲<E884AB><E6B2B2><EFBFBD><EFBFBD>** - 靘折<E99D98>鈭烐<E988AD><E78390><EFBFBD><E288AA>函蔡瘚<E894A1><E7989A>
- 04<30><34>﹝嚗?*撟喳蝱<E596B3><EFBFBD>霈暹鴌閫<E9B48C><E996AB>** - 靘折<E99D98><EFBFBD><E99A9E>摰䂿緵<E482BF><E7B7B5><EFBFBD><EFBFBD><EFBFBD><E78390>?
**<2A><><EFBFBD>園𡢿**嚗?0 <20><><EFBFBD>
**摰墧鴌<EFBFBD>園𡢿**嚗𡁜<E59A97>閫?[撟喳蝱<EFBFBD><EFBFBD>霈暹鴌閫<EFBFBD><EFBFBD>](./04-撟喳蝱<E596B3><EFBFBD>霈暹鴌閫<E9B48C><E996AB>.md) <20>?.5憭拙<EFBFBD><EFBFBD>質恣<EFBFBD>?
---
## 🏗️ 架构详解
## <EFBFBD><EFBFBD>儭?<3F><EFBFBD>霂西圾
### 1. Serverless 摨𠉛鍂撘閙<E69298> (SAE)
#### **产品特性**
#### **鈭批<EFBFBD><EFBFBD><EFBFBD>?*
| 特性 | 说明 | 优势 |
| <EFBFBD><EFBFBD>?| 霂湔<E99C82> | 隡睃飵 |
|------|------|------|
| **自动扩缩容** | 根据流量自动调整实例数0-100 | 高峰期不宕机,低谷期省成本 |
| **按需付费** | ¥0.000110592/请求次 + 实例费 | 初期月费约 ¥200-500 |
| **容器化部署** | 支持 Docker 镜像 | 环境一致性,快速回滚 |
| **<EFBFBD>芸𢆡<EFBFBD>拍憬摰?* | <20>寞旿瘚<E697BF><E7989A><EFBFBD>芸𢆡靚<F0A286A1>㟲摰硺<E691B0><E7A1BA><EFBFBD>0-100嚗?| 擃睃陸<E79D83><EFBFBD>摰閙㦤嚗䔶<E59A97>靚瑟<E99D9A><E7919F><EFBFBD><EFBFBD><EFBFBD>?|
| **<EFBFBD><EFBFBD>隞䁅晶** | 0.000110592/霂瑟<EFBFBD>甈?+ 摰硺<E691B0>韐?| <20><EFBFBD><E884B2><EFBFBD>晶蝥?瞼200-500 |
| **摰孵膥<EFBFBD><EFBFBD>蝵?* | <20><EFBFBD> Docker <20>𨅯<EFBFBD> | <20><EFBFBD><EFBFBD><E98A9D><EFBFBD><EFBFBD>敹恍<E695B9><EFBFBD>皛?|
| **<EFBFBD><EFBFBD>蔭韐蠘蝸<EFBFBD><EFBFBD>﹛** | <20>芸𢆡<E88AB8><F0A286A1><EFBFBD><EFBFBD><E7989A> | <20>𣳇<EFBFBD><F0A3B387>閧𡠺韐凋僭 SLB |
| **健康检查** | 自动重启异常实例 | 提高可用性 |
| **<EFBFBD>亙熒璉<EFBFBD><EFBFBD>?* | <20>芸𢆡<E88AB8>滚鍳撘<E98DB3>虜摰硺<E691B0> | <20><EFBFBD><E99EBE>舐鍂<E88890>?|
#### **摰硺<E691B0><EFBFBD><EFBFBD>㗇𥋘**
| <20>嗆挾 | 閫<>聢 | vCPU | <20><><EFBFBD> | <20><><EFBFBD>箸艶 |
|------|------|------|------|---------|
| **开发/测试** | 0.5C1G | 0.5| 1GB | 日请求 < 1000 |
| **初期** | 1C2G | 1| 2GB | 日请求 1000-5000 |
| **成长期** | 2C4G | 2| 4GB | 日请求 5000-20000 |
| **成熟期** | 4C8G | 4| 8GB | 日请求 > 20000 |
| **<EFBFBD><EFBFBD>?瘚贝<E7989A>** | 0.5C1G | 0.5<EFBFBD>?| 1GB | <EFBFBD>亥窈瘙?< 1000 |
| **<EFBFBD><EFBFBD>** | 1C2G | 1<EFBFBD>?| 2GB | <EFBFBD>亥窈瘙?1000-5000 |
| **<EFBFBD>鞾鵭<EFBFBD>?* | 2C4G | 2<EFBFBD>?| 4GB | <EFBFBD>亥窈瘙?5000-20000 |
| **<EFBFBD><EFBFBD><EFBFBD>?* | 4C8G | 4<EFBFBD>?| 8GB | <EFBFBD>亥窈瘙?> 20000 |
**建议配置**
```yaml
**撱箄悅<EFBFBD>滨蔭**嚗?```yaml
# SAE 摨𠉛鍂<F0A0899B>滨蔭
摰硺<EFBFBD><EFBFBD>聢: 1C2G
最小实例数: 1 # 避免冷启动
最大实例数: 10
CPU 触发扩容阈值: 70%
内存触发扩容阈值: 80%
<EFBFBD><EFBFBD>撠誩<EFBFBD>靘𧢲㺭: 1 # <20><EFBFBD><E8B8B9>瑕鍳<E79195>?<3F><>憭批<E686AD>靘𧢲㺭: 10
CPU 閫血<E996AB><E8A180>拙捆<E68B99><E68D86><EFBFBD>? 70%
<EFBFBD><EFBFBD><EFBFBD>閫血<EFBFBD><EFBFBD>拙捆<EFBFBD><EFBFBD><EFBFBD>? 80%
```
---
@@ -72,10 +61,10 @@ CPU 触发扩容阈值: 70%
| <20>嗆挾 | 閫<>聢 | vCPU | <20><><EFBFBD> | <20><>憭扯<E686AD><E689AF>交㺭 | <20><>晶 |
|------|------|------|------|-----------|------|
| **开发/测试** | 基础版 1C1G | 1| 1GB | 100 | ¥120 |
| **初期** | 通用版 2C4G | 2| 4GB | 400 | ¥300 |
| **成长期** | 通用版 4C8G | 4| 8GB | 800 | ¥600 |
| **成熟期** | 独享版 8C16G | 8| 16GB | 1600 | ¥1200 |
| **<EFBFBD><EFBFBD>?瘚贝<E7989A>** | <EFBFBD><EFBFBD><EFBFBD>?1C1G | 1<EFBFBD>?| 1GB | 100 | 120 |
| **<EFBFBD><EFBFBD>** | <EFBFBD>𡁶鍂<EFBFBD>?2C4G | 2<EFBFBD>?| 4GB | 400 | 300 |
| **<EFBFBD>鞾鵭<EFBFBD>?* | <20>𡁶鍂<F0A181B6>?4C8G | 4<EFBFBD>?| 8GB | 800 | 600 |
| **<EFBFBD><EFBFBD><EFBFBD>?* | <20>砌澈<E7A08C>?8C16G | 8<EFBFBD>?| 16GB | 1600 | 1200 |
#### **<2A>喲睸<E596B2>滨蔭**
@@ -92,14 +81,12 @@ FROM pg_stat_activity
GROUP BY datname;
```
**连接池计算公式**
```
**餈墧𦻖瘙㰘恣蝞堒<EFBFBD>撘?*嚗?```
瘥誩<EFBFBD>靘贝<EFBFBD><EFBFBD>交㺭 = RDS<44><53>憭扯<E686AD><E689AF>交㺭 / SAE<41><45>憭批<E686AD>靘𧢲㺭 <20> 0.8嚗<EFBFBD><EFBFBD><EFBFBD>函頂<EFBFBD><EFBFBD>
示例:
RDS: 400连接
SAE: 最多10实例
每实例: 400 / 10 × 0.8 = 32连接
蝷箔<EFBFBD>嚗?RDS: 400餈墧𦻖
SAE: <20><>憭?0摰硺<E691B0>
瘥誩<EFBFBD>靘? 400 / 10 <20> 0.8 = 32餈墧𦻖
```
---
@@ -112,9 +99,7 @@ SAE: 最多10实例
Bucket<EFBFBD>滨妍: aiclinical-prod
<EFBFBD><EFBFBD>: <20>𦒘<EFBFBD>1嚗<31>㜺撌痹<E6928C>oss-cn-hangzhou
摮睃<EFBFBD>蝐餃<EFBFBD>: <20><><EFBFBD>摮睃<E691AE>
访问权限: 私有Private
版本控制: 开启
跨域设置: 允许前端域名
霈輸䔮<EFBFBD><EFBFBD><EFBFBD>: 蝘<><E89D98>嚗㇊rivate嚗?<3F><>𧋦<EFBFBD><EFBFBD>: 撘<><E69298>?頝典<E9A09D>霈曄蔭: <20><><EFBFBD>滨垢<E6BBA8><EFBFBD>
```
#### **<2A><EFBFBD>蝏𤘪<E89D8F><EFBFBD><E996AB>**
@@ -122,13 +107,11 @@ Bucket名称: aiclinical-prod
```
aiclinical-prod/
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> asl/
│ ├── pdfs/ # PDF文件
│ ├── excel/ # Excel文件
│ └── exports/ # 导出文件
<EFBFBD>? <20><EFBFBD><E98EBF><EFBFBD> pdfs/ # PDF<EFBFBD><EFBFBD>
<EFBFBD>? <20><EFBFBD><E98EBF><EFBFBD> excel/ # Excel<EFBFBD><EFBFBD>
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD> exports/ # 撖澆枂<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> avatars/ # <20><EFBFBD>憭游<E686AD>
├── documents/ # 知识库文档
└── temp/ # 临时文件1天后自动删除
```
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> documents/ # <EFBFBD><EFBFBD>摨𤘪<EFBFBD>獢?<3F><EFBFBD><E5A999><EFBFBD> temp/ # 銝湔𧒄<E6B994><F0A79284>辣嚗?憭拙<E686AD><E68B99>芸𢆡<E88AB8>𣳇膄嚗?```
#### **<2A>笔𦶢<E7AC94><EFBFBD>蝞∠<E89D9E>**
@@ -160,20 +143,17 @@ aiclinical-prod/
---
## 💻 存储抽象层设计(核心)
## <EFBFBD>凃 摮睃<E691AE><E79D83>質情撅<E68385>挽霈∴<E99C88><E288B4><EFBFBD>嚗?
### <20>亙藁摰帋<E691B0>
**<2A><>辣**嚗䫤backend/src/common/storage/StorageAdapter.ts`
```typescript
/**
* 存储抽象层接口
*
* 摮睃<EFBFBD><EFBFBD>質情撅<EFBFBD>𦻖<EFBFBD>? *
* @description
* - 支持本地文件系统 + 阿里云 OSS 无缝切换
* - 通过环境变量控制实现类
*
* - <EFBFBD><EFBFBD><EFBFBD>砍𧑐<EFBFBD><EFBFBD>辣蝟餌<EFBFBD> + <20><EFBFBD>鈭?OSS <20><EFBFBD><E588A0><EFBFBD>
* - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>摰䂿緵蝐? *
* @example
* const storage = StorageFactory.create()
* const url = await storage.upload('files/doc.pdf', buffer)
@@ -181,7 +161,7 @@ aiclinical-prod/
export interface StorageAdapter {
/**
* 銝𠹺<E98A9D><F0A0B9BA><EFBFBD>
* @param key 存储键(路径),如 'asl/pdfs/xxx.pdf'
* @param key 摮睃<EFBFBD><EFBFBD><EFBFBD>頝臬<EFBFBD>嚗㚁<EFBFBD>憒?'asl/pdfs/xxx.pdf'
* @param buffer <20><><EFBFBD><E8BEA3>
* @returns 霈輸䔮URL
*/
@@ -189,21 +169,18 @@ export interface StorageAdapter {
/**
* 銝贝蝸<E8B49D><E89DB8>
* @param key 存储键
* @returns 文件内容
* @param key 摮睃<EFBFBD><EFBFBD>? * @returns <20><><EFBFBD><E8BEA3>
*/
download(key: string): Promise<Buffer>
/**
* <20>𣳇膄<F0A3B387><E88684>
* @param key 存储键
*/
* @param key 摮睃<EFBFBD><EFBFBD>? */
delete(key: string): Promise<void>
/**
* <20><EFBFBD>霈輸䔮URL
* @param key 存储键
* @returns 完整访问URL
* @param key 摮睃<EFBFBD><EFBFBD>? * @returns 摰峕㟲霈輸䔮URL
*/
getUrl(key: string): string
@@ -228,11 +205,9 @@ import path from 'path'
import { StorageAdapter } from './StorageAdapter.js'
/**
* 本地文件系统存储适配器
*
* <20>砍𧑐<E7A08D><F0A79190>辣蝟餌<E89D9F>摮睃<E691AE><E79D83><EFBFBD><EFBFBD><EFBFBD>? *
* @description
* - 用于本地开发环境
* - 文件存储在 ./uploads 目录
* - <20><EFBFBD><E585B6>砍𧑐撘<F0A79190><E69298>𤑳㴓憓? * - <20><>辣摮睃<E691AE><E79D83>?./uploads <20><EFBFBD>
* - <20><EFBFBD> HTTP 霈輸䔮嚗冴ttp://localhost:3001/uploads/xxx
*/
export class LocalAdapter implements StorageAdapter {
@@ -258,8 +233,7 @@ export class LocalAdapter implements StorageAdapter {
async upload(key: string, buffer: Buffer): Promise<string> {
const filePath = path.join(this.uploadDir, key)
// 确保父目录存在
await fs.mkdir(path.dirname(filePath), { recursive: true })
// 蝖桐<EFBFBD><EFBFBD>嗥𤌍敶訫<EFBFBD><EFBFBD>? await fs.mkdir(path.dirname(filePath), { recursive: true })
// <20><EFBFBD><E59D94><EFBFBD>
await fs.writeFile(filePath, buffer)
@@ -309,8 +283,7 @@ import OSS from 'ali-oss'
import { StorageAdapter } from './StorageAdapter.js'
/**
* 阿里云 OSS 存储适配器
*
* <EFBFBD><EFBFBD>鈭?OSS 摮睃<E691AE><E79D83><EFBFBD><EFBFBD><EFBFBD>? *
* @description
* - <20><EFBFBD><E585B6>煺漣<E785BA><EFBFBD>
* - <20><>辣摮睃<E691AE><E79D83>券燵<E588B8><EFBFBD> OSS
@@ -326,7 +299,7 @@ export class OSSAdapter implements StorageAdapter {
this.bucket = process.env.OSS_BUCKET!
if (!this.region || !this.bucket) {
throw new Error('OSS配置缺失OSS_REGION OSS_BUCKET 未设置')
throw new Error('OSS<EFBFBD>滨蔭蝻箏仃嚗鐾SS_REGION <EFBFBD>?OSS_BUCKET <EFBFBD>芾挽蝵?)
}
this.client = new OSS({
@@ -334,8 +307,7 @@ export class OSSAdapter implements StorageAdapter {
accessKeyId: process.env.OSS_ACCESS_KEY_ID!,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,
bucket: this.bucket,
// 使用内网endpointSAE访问OSS免流量费
internal: process.env.NODE_ENV === 'production',
// 雿輻鍂<EFBFBD><EFBFBD><EFBFBD>endpoint嚗𠄎AE霈輸䔮OSS<EFBFBD>齿<EFBFBD><EFBFBD>讛晶嚗? internal: process.env.NODE_ENV === 'production',
})
}
@@ -364,8 +336,7 @@ export class OSSAdapter implements StorageAdapter {
await this.client.delete(key)
} catch (error) {
console.error('OSS<EFBFBD>𣳇:', error)
// 文件不存在时不抛出错误
}
// <EFBFBD><EFBFBD>辣銝滚<EFBFBD><EFBFBD>冽𧒄銝齿<EFBFBD><EFBFBD><EFBFBD>霂? }
}
getUrl(key: string): string {
@@ -374,7 +345,7 @@ export class OSSAdapter implements StorageAdapter {
}
async uploadMany(files: Array<{ key: string; buffer: Buffer }>): Promise<string[]> {
// 并行上传最多10个并发
// 撟嗉<EFBFBD>銝𠹺<EFBFBD><EFBFBD><EFBFBD>憭?0銝芸僎<E88AB8>𡢅<EFBFBD>
const chunks = []
for (let i = 0; i < files.length; i += 10) {
chunks.push(files.slice(i, i + 10))
@@ -393,8 +364,7 @@ export class OSSAdapter implements StorageAdapter {
/**
* <20><><EFBFBD>蝑曉<E89D91>URL嚗<4C><EFBFBD>嗉挪<E59789><EFBFBD>
* @param key 存储键
* @param expires 过期时间默认1小时
* @param key 摮睃<EFBFBD><EFBFBD>? * @param expires 餈<><E9A488><EFBFBD>園𡢿嚗<F0A1A2BF><E59A97>嚗㚁<E59A97>暺䁅恕1撠𤩺𧒄
*/
async getSignedUrl(key: string, expires: number = 3600): Promise<string> {
return this.client.signatureUrl(key, { expires })
@@ -404,8 +374,7 @@ export class OSSAdapter implements StorageAdapter {
---
### StorageFactory 工厂类
### StorageFactory 撌亙<EFBFBD>蝐?
**<2A><>辣**嚗䫤backend/src/common/storage/StorageFactory.ts`
```typescript
@@ -414,12 +383,11 @@ import { LocalAdapter } from './LocalAdapter.js'
import { OSSAdapter } from './OSSAdapter.js'
/**
* 存储工厂类
*
* 摮睃<EFBFBD>撌亙<EFBFBD>蝐? *
* @description
* - <20>寞旿<E5AF9E><EFBFBD><E887AC><EFBFBD><E3979B>芸𢆡<E88AB8>㗇𥋘摮睃<E691AE>摰䂿緵
* - STORAGE_TYPE=local LocalAdapter
* - STORAGE_TYPE=oss OSSAdapter
* - STORAGE_TYPE=local <EFBFBD>?LocalAdapter
* - STORAGE_TYPE=oss <EFBFBD>?OSSAdapter
*/
export class StorageFactory {
private static instance: StorageAdapter | null = null
@@ -436,7 +404,7 @@ export class StorageFactory {
switch (storageType) {
case 'oss':
console.log('📦 使用阿里云 OSS 存储')
console.log('<27>𣑐 雿輻鍂<E8BCBB><EFBFBD>鈭?OSS 摮睃<E691AE>')
this.instance = new OSSAdapter()
break
@@ -446,7 +414,7 @@ export class StorageFactory {
break
default:
throw new Error(`未知的存储类型: ${storageType}`)
throw new Error(`<EFBFBD>芰䰻<EFBFBD><EFBFBD><EFBFBD><EFBFBD>函掩<EFBFBD>? ${storageType}`)
}
return this.instance
@@ -489,11 +457,9 @@ export async function uploadPdf(req, res) {
// 霂餃<E99C82><E9A483><EFBFBD><EFBFBD><E8BEA3>
const buffer = await file.toBuffer()
// 生成存储键
const key = `asl/pdfs/${Date.now()}-${file.filename}`
// <EFBFBD><EFBFBD><EFBFBD>摮睃<EFBFBD><EFBFBD>? const key = `asl/pdfs/${Date.now()}-${file.filename}`
// ✅ 上传到存储自动根据环境选择Local或OSS
const url = await storage.upload(key, buffer)
// <EFBFBD>?銝𠹺<E98A9D><F0A0B9BA><EFBFBD><E595A3><EFBFBD><E58981>芸𢆡<E88AB8>寞旿<E5AF9E><EFBFBD><E887AC>㗇𥋘Local<61>𤈛SS嚗? const url = await storage.upload(key, buffer)
// 靽嘥<E99DBD><E598A5>唳㺭<E594B3><EFBFBD>
await prisma.aslLiterature.update({
@@ -517,14 +483,12 @@ export async function uploadPdf(req, res) {
}
/**
* Excel上传(不需要存储,直接解析)
*/
* Excel銝𠹺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>湔𦻖閫<EFBFBD><EFBFBD>嚗? */
export async function importExcel(req, res) {
const file = await req.file()
const buffer = await file.toBuffer()
// ✅ 直接从内存解析,不落盘
const workbook = xlsx.read(buffer, { type: 'buffer' })
// <EFBFBD>?<3F>湔𦻖隞𤾸<E99A9E>摮䁅圾<E48185><EFBFBD>銝滩氜<E6BBA9>? const workbook = xlsx.read(buffer, { type: 'buffer' })
const data = xlsx.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]])
// <20><EFBFBD><E5AFA5><EFBFBD>
@@ -548,19 +512,16 @@ import { PrismaClient } from '@prisma/client'
// <20><EFBFBD><E887AC>斗鱏
const isProduction = process.env.NODE_ENV === 'production'
// 计算连接池大小
// 生产环境RDS 400连接 / SAE 10实例 × 0.8 = 32连接/实例
// 开发环境:本地 PostgreSQL5连接足够
// 霈∠<EFBFBD>餈墧𦻖瘙惩之撠?// <20>煺漣<E785BA><EFBFBD>嚗鑹DS 400餈墧𦻖 / SAE 10摰硺<E691B0> <20> 0.8 = 32餈墧𦻖/摰硺<E691B0>
// <EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD><EFBFBD>砍𧑐 PostgreSQL嚗?餈墧𦻖頞喳<E9A09E>
const connectionLimit = isProduction ? 32 : 5
/**
* Prisma 客户端配置
*/
* Prisma <EFBFBD>蝡舫<EFBFBD>蝵? */
export const prisma = new PrismaClient({
log: isProduction
? ['error', 'warn'] // <20>煺漣<E785BA><EFBFBD><E887AC>芾扇敶閖<E695B6>霂臬<E99C82>霅血<E99C85>
: ['query', 'error', 'warn'], // 开发环境记录所有查询
: ['query', 'error', 'warn'], // <EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD>扇敶閙<EFBFBD><EFBFBD>㗇䰻霂?
datasources: {
db: {
url: process.env.DATABASE_URL
@@ -569,16 +530,12 @@ export const prisma = new PrismaClient({
// <20>喲睸<E596B2>滨蔭嚗朞<E59A97><E69C9E><EFBFBD>
...(isProduction && {
// 仅在生产环境配置连接池限制
datasources: {
// <EFBFBD><EFBFBD>煺漣<EFBFBD><EFBFBD><EFBFBD>滨蔭餈墧𦻖瘙𣳇<EFBFBD><EFBFBD>? datasources: {
db: {
url: process.env.DATABASE_URL,
// 连接池配置
pool: {
timeout: 5, // 获取连接超时(秒)
maxsize: connectionLimit, // 最大连接数
min: 2, // 最小保持连接
}
// 餈墧𦻖瘙𣳇<EFBFBD>蝵? pool: {
timeout: 5, // <20><EFBFBD>餈墧𦻖頞<F0A6BB96>𧒄嚗<F0A79284><E59A97>嚗? maxsize: connectionLimit, // <20><>憭扯<E686AD><E689AF>交㺭
min: 2, // <EFBFBD><EFBFBD>撠譍<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? }
}
}
})
@@ -586,7 +543,7 @@ export const prisma = new PrismaClient({
// 隡㗛<E99AA1><E3979B>喲𡡒
process.on('SIGINT', async () => {
console.log('📦 正在关闭数据库连接...')
console.log('<EFBFBD>𣑐 甇<><EFBFBD>喲𡡒<E596B2>唳旿摨栞<E691A8><E6A09E>?..')
await prisma.$disconnect()
process.exit(0)
})
@@ -616,18 +573,16 @@ if (isProduction) {
console.error(`<EFBFBD>𩤃<EFBFBD> <20>唳旿摨栞<E691A8><E6A09E>交㺭餈<E3BAAD><E9A488>: ${connectionCount}/${maxConnections}`)
}
} catch (error) {
console.error('连接数监控失败:', error)
console.error('餈墧𦻖<EFBFBD><EFBFBD><EFBFBD>批仃韐?', error)
}
}, 60000) // 每60秒检查一次
}
}, 60000) // 瘥?0蝘埝<E89D98><E59F9D><EFBFBD>甈?}
```
---
## <20><> <20><EFBFBD><E887AC><EFBFBD>蝞∠<E89D9E>
### 本地开发环境
### <EFBFBD>砍𧑐撘<EFBFBD><EFBFBD>𤑳㴓憓?
**<2A><>辣**嚗䫤backend/.env.development`
```bash
@@ -638,15 +593,13 @@ NODE_ENV=development
STORAGE_TYPE=local
BASE_URL=http://localhost:3001
# 数据库
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/aiclinical_dev
# <EFBFBD>唳旿摨?DATABASE_URL=postgresql://postgres:postgres@localhost:5432/aiclinical_dev
# LLM<4C>滨蔭
LLM_API_KEY=sk-xxx
LLM_BASE_URL=https://api.deepseek.com
# 其他服务(本地无需配置)
OSS_REGION=
# <EFBFBD><EFBFBD><EFBFBD>滚𦛚嚗<EFBFBD>𧋦<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滨蔭嚗?OSS_REGION=
OSS_ACCESS_KEY_ID=
OSS_ACCESS_KEY_SECRET=
OSS_BUCKET=
@@ -656,8 +609,7 @@ OSS_BUCKET=
### <20>煺漣<E785BA><EFBFBD><E887AC>滨蔭
**在SAE控制台配置不要写入文件**
**<EFBFBD>沒AE<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝵殷<EFBFBD>銝滩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>辣**嚗?
```bash
# <20><EFBFBD>
NODE_ENV=production
@@ -665,12 +617,10 @@ NODE_ENV=production
# 摮睃<E691AE><E79D83>滨蔭
STORAGE_TYPE=oss
OSS_REGION=oss-cn-hangzhou
OSS_ACCESS_KEY_ID=LTAI5t***从RAM用户获取
OSS_ACCESS_KEY_SECRET=***
OSS_ACCESS_KEY_ID=LTAI5t***<EFBFBD><EFBFBD>RAM<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?OSS_ACCESS_KEY_SECRET=***
OSS_BUCKET=aiclinical-prod
# 数据库
DATABASE_URL=postgresql://aiclinical:***@rm-xxx.mysql.rds.aliyuncs.com:5432/aiclinical_prod
# <EFBFBD>唳旿摨?DATABASE_URL=postgresql://aiclinical:***@rm-xxx.mysql.rds.aliyuncs.com:5432/aiclinical_prod
# LLM<4C>滨蔭
LLM_API_KEY=sk-***
@@ -701,8 +651,7 @@ COPY prisma ./prisma/
# 摰㕑<E691B0>靘肽<E99D98><EFBFBD><E59A97><EFBFBD>查ev靘肽<E99D98>嚗𣬚鍂鈭擧<E988AD>撱綽<E692B1>
RUN npm ci
# 复制源代码
COPY . .
# 憭滚<EFBFBD>皞𣂷誨<EFBFBD>?COPY . .
# <20><><EFBFBD> Prisma Client
RUN npx prisma generate
@@ -719,17 +668,14 @@ WORKDIR /app
COPY package*.json ./
COPY prisma ./prisma/
# 仅安装生产依赖
RUN npm ci --only=production
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭找<EFBFBD>韏?RUN npm ci --only=production
# <20><><EFBFBD> Prisma Client
RUN npx prisma generate
# 从构建阶段复制编译后的代码
COPY --from=builder /app/dist ./dist
# 隞擧<EFBFBD>撱粹𧫴畾萄<EFBFBD><EFBFBD><EFBFBD>霂穃<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?COPY --from=builder /app/dist ./dist
# 复制静态文件如prompts
COPY prompts ./prompts
# 憭滚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞塚<EFBFBD><EFBFBD>rompts嚗?COPY prompts ./prompts
COPY config ./config
# <20>𥕦遣<F0A595A6>𡇙oot<6F><EFBFBD>
@@ -742,8 +688,7 @@ USER nodejs
# <20>湧蠧蝡臬藁
EXPOSE 3001
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
# <EFBFBD>亙熒璉<EFBFBD><EFBFBD>?HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD node -e "require('http').get('http://localhost:3001/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# <20>臬𢆡摨𠉛鍂
@@ -760,8 +705,7 @@ CMD ["node", "dist/index.js"]
version: '3.8'
services:
# PostgreSQL数据库
postgres:
# PostgreSQL<EFBFBD>唳旿摨? postgres:
image: postgres:15-alpine
container_name: aiclinical-postgres
environment:
@@ -810,10 +754,8 @@ volumes:
redis-data:
```
**使用方式**
```bash
# 启动所有服务
docker-compose up -d
**雿輻鍂<EFBFBD><EFBFBD>**嚗?```bash
# <20>臬𢆡<E887AC><F0A286A1><EFBFBD><EFBFBD><E39787>?docker-compose up -d
# <20><EFBFBD><E4BAA6><EFBFBD>
docker-compose logs -f backend
@@ -826,69 +768,55 @@ docker-compose down
## <20><> <20>函蔡瘚<E894A1><E7989A>
### Step 1: 准备阿里云服务
#### 1.1 开通云数据库 RDS
### Step 1: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭烐<EFBFBD><EFBFBD>?
#### 1.1 撘<><E69298><EFBFBD><E5B88B>唳旿摨?RDS
```bash
# 1. <20><EFBFBD><E9A483><EFBFBD>鈭烐綉<E78390>嗅蝱
# 2. <20>𦦵揣"鈭烐㺭<E78390><EFBFBD> RDS"
# 3. <20>𥕦遣摰硺<E691B0>
# - <20>唳旿摨梶掩<E6A2B6><EFBFBD>PostgreSQL 15
# - 规格2核4GB通用型
# - 存储空间20GBSSD
# - 网络VPC与SAE同区域
# 4. 设置白名单(添加 SAE 应用的 VPC网段
# 5. 创建数据库用户
# 6. 创建数据库aiclinical_prod
# - <EFBFBD>聢嚗?<3F>?GB嚗<42><E59A97>𡁶鍂<F0A181B6><EFBFBD>
# - 摮睃<EFBFBD>蝛粹𡢿嚗?0GB嚗𠄎SD嚗?# - 蝵𤑳<E89DB5>嚗间PC嚗<43><E59A97>SAE<41><45><EFBFBD><E8BAB9><EFBFBD>
# 4. 霈曄蔭<E69B84><EFBFBD><E8B3A2>𤏪<EFBFBD>瘛餃<E7989B> SAE 摨𠉛鍂<F0A0899B>?VPC蝵烐挾嚗?# 5. <20>𥕦遣<F0A595A6>唳旿摨梶鍂<E6A2B6>?# 6. <20>𥕦遣<F0A595A6>唳旿摨橒<E691A8>aiclinical_prod
```
#### 1.2 开通对象存储 OSS
#### 1.2 <EFBFBD><EFBFBD>𡁜笆鞊<EFBFBD><EFBFBD>?OSS
```bash
# 1. <20>𦦵揣"撖寡情摮睃<E691AE> OSS"
# 2. <20>𥕦遣 Bucket
# - Bucket<65>滨妍嚗惨iclinical-prod
# - 区域华东1杭州
# - 存储类型:标准存储
# - 访问权限:私有
# 3. 创建 RAM 用户用于API访问
# - 权限AliyunOSSFullAccess
# - 获取 AccessKeyId 和 AccessKeySecret
# - <EFBFBD><EFBFBD>嚗𡁜<EFBFBD>銝?嚗<>㜺撌痹<E6928C>
# - 摮睃<E691AE>蝐餃<E89D90>嚗𡁏<E59A97><F0A1818F><EFBFBD><EFBFBD><EFBFBD>?# - 霈輸䔮<E8BCB8><E494AE><EFBFBD>嚗𡁶<E59A97><F0A181B6>?# 3. <20>𥕦遣 RAM <20><EFBFBD><EFBFBD>鍂鈭垾PI霈輸䔮嚗?# - <20><><EFBFBD>嚗鋫liyunOSSFullAccess
# - <EFBFBD><EFBFBD> AccessKeyId <20>?AccessKeySecret
```
#### 1.3 开通容器镜像服务
#### 1.3 <EFBFBD><EFBFBD>𡁜捆<EFBFBD><EFBFBD><EFBFBD>𤩺<EFBFBD><EFBFBD>?
```bash
# 1. <20>𦦵揣"摰孵膥<E5ADB5>𨅯<EFBFBD><F0A885AF>滚𦛚 ACR"
# 2. <20>𥕦遣<F0A595A6><EFBFBD>蝛粹𡢿嚗惨iclinical
# 3. <20>𥕦遣<F0A595A6>𨅯<EFBFBD>隞枏<E99A9E>嚗颹ackend
# - 类型:私有
# - 地域华东1杭州
# - 蝐餃<EFBFBD>嚗𡁶<EFBFBD><EFBFBD>?# - <20><EFBFBD>嚗𡁜<E59A97>銝?嚗<>㜺撌痹<E6928C>
```
---
### Step 2: 构建和推送镜像
### Step 2: <EFBFBD><EFBFBD><EFBFBD>峕綫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
```bash
# 1. 登录阿里云容器镜像服务
docker login --username=<你的阿里云账号> registry.cn-hangzhou.aliyuncs.com
# 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭穃捆<EFBFBD><EFBFBD><EFBFBD>𤩺<EFBFBD><EFBFBD>?docker login --username=<雿删<E99BBF><E588A0><EFBFBD>鈭𤏸揭<F0A48FB8>? registry.cn-hangzhou.aliyuncs.com
# 2. <20><><EFBFBD>𨅯<EFBFBD>
cd backend
docker build -t aiclinical-backend:v1.0.0 .
# 3. 打标签
docker tag aiclinical-backend:v1.0.0 \
# 3. <EFBFBD>𤘪<EFBFBD>蝑?docker tag aiclinical-backend:v1.0.0 \
registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.0.0
# 4. 推送到阿里云
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.0.0
# 4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭?docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.0.0
```
**脚本自动化**
**<EFBFBD>𡁏𧋦<EFBFBD>芸𢆡<EFBFBD>?*嚗?
**<2A><>辣**嚗䫤backend/scripts/build-and-push.sh`
```bash
@@ -905,14 +833,14 @@ fi
echo "<EFBFBD><20><><EFBFBD>𨅯<EFBFBD>: $VERSION"
docker build -t aiclinical-backend:$VERSION .
echo "🏷️ 打标签"
echo "<EFBFBD>噡儭?<3F>𤘪<EFBFBD>蝑?
docker tag aiclinical-backend:$VERSION \
registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:$VERSION
echo "📤 推送到阿里云"
echo "<EFBFBD><20><EFBFBD><E588B8><EFBFBD><EFBFBD><EFBFBD>鈭?
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:$VERSION
echo "✅ 完成!"
echo "<EFBFBD>?摰峕<E691B0>嚗?
echo "<EFBFBD>𨅯<EFBFBD><EFBFBD><EFBFBD>: registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:$VERSION"
```
@@ -927,7 +855,7 @@ echo "镜像地址: registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:$VERSIO
摨𠉛鍂蝐餃<EFBFBD>: 摰孵膥<EFBFBD>𨅯<EFBFBD>
<EFBFBD>𨅯<EFBFBD><EFBFBD><EFBFBD>: registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.0.0
蝡臬藁: 3001
健康检查路径: /health
<EFBFBD>亙熒璉<EFBFBD><EFBFBD>亥楝敺? /health
```
#### 3.2 摰硺<E691B0><E7A1BA>滨蔭
@@ -942,7 +870,7 @@ CPU触发扩容: 70%
#### 3.3 <20><EFBFBD><E887AC><EFBFBD><E3979B>滨蔭
SAE 控制台配置环境变量(**重要!**
<EFBFBD>?SAE <EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝵桃㴓憓<EFBFBD><EFBFBD><EFBFBD>𧶏<EFBFBD>**<2A><EFBFBD>嚗?*嚗㚁<E59A97>
```bash
NODE_ENV=production
@@ -960,38 +888,31 @@ LOG_LEVEL=info
```yaml
VPC: <EFBFBD>㗇𥋘銝竃DS<EFBFBD><EFBFBD><EFBFBD><EFBFBD>PC
安全组: 允许3001端口入站
公网访问: 开启分配公网SLB
```
摰匧<EFBFBD>蝏? <20><>捂3001蝡臬藁<E887AC><EFBFBD>
<EFBFBD><EFBFBD>霈輸䔮: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SLB嚗?```
---
### Step 4: <20>函蔡摨𠉛鍂
```bash
# 1. SAE 控制台点击"部署应用"
# 1. <EFBFBD>?SAE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>函蔡摨𠉛鍂"
# 2. <20>㗇𥋘<E39787>𨅯<EFBFBD><F0A885AF><EFBFBD>𧋦
# 3. 蝖株恕<E6A0AA>滨蔭<E6BBA8>㰘秤
# 4. 点击"确定"开始部署
# 4. <EFBFBD>孵稬"蝖桀<E89D96>"撘<>憪钅<E686AA>蝵?
# 蝑匧<E89D91>3-5<><35><EFBFBD>嚗峕䰻<E5B395><EFBFBD>蝵脫𠯫敹?```
# 等待3-5分钟查看部署日志
```
**部署成功标志**
- ✅ 实例状态:运行中
- ✅ 健康检查:通过
- ✅ 访问 `http://<SAE公网地址>/health` 返回 200
**<2A>函蔡<E587BD>𣂼<EFBFBD><F0A382BC><EFBFBD><EFBFBD>**嚗?- <EFBFBD>?摰硺<E691B0><E7A1BA><EFBFBD><E59786><EFBFBD>餈鞱<E9A488>銝?- <20>?<3F>亙熒璉<E78692><E79289><EFBFBD><E4BC90><EFBFBD>
- <EFBFBD>?霈輸䔮 `http://<SAE<41><EFBFBD><E7A589><EFBFBD>>/health` 餈𥪜<E9A488> 200
---
### Step 5: 撉諹<E69289><E8ABB9>函蔡
```bash
# 1. 健康检查
curl http://<SAE公网地址>/health
# 1. <EFBFBD>亙熒璉<EFBFBD><EFBFBD>?curl http://<SAE<41><EFBFBD><E7A589><EFBFBD>>/health
# 预期响应:
{
# 憸<><E686B8><EFBFBD><EFBFBD>嚗?{
"status": "ok",
"database": "connected",
"timestamp": "2025-11-16T10:30:00.000Z"
@@ -1001,84 +922,70 @@ curl http://<SAE公网地址>/health
curl http://<SAE<41><EFBFBD><E7A589><EFBFBD>>/api/v1/health
# 3. <20><EFBFBD><E4BAA6><EFBFBD>
# 在 SAE 控制台 → 应用详情 → 实时日志
# <20>?SAE <20><EFBFBD><E689B9>?<3F>?摨𠉛鍂霂行<E99C82> <20>?摰墧𧒄<E5A2A7><EFBFBD>
```
---
## <20><> <20>鞉𧋦隡啁<E99AA1>
### 初期阶段100用户日活20
### <EFBFBD><EFBFBD><EFBFBD>嗆挾嚗?00<30><EFBFBD>嚗峕𠯫瘣?0嚗?
| <20>滚𦛚 | 閫<>聢 | <20><>晶 |
|------|------|------|
| SAE | 1C2G <20> 1摰硺<E691B0> | 瞼200 |
| RDS | 2C4G 通用版 | ¥300 |
| RDS | 2C4G <EFBFBD>𡁶鍂<EFBFBD>?| 300 |
| OSS | 100GB<47><42><EFBFBD>摮睃<E691AE> + 10GB瘚<42><E7989A> | 瞼15 |
| ACR | 蝘<><E89D98>隞枏<E99A9E> | 瞼0嚗<30><E59A97>韐寥<E99F90>摨佗<E691A8> |
| **合计** | | **¥515/月** |
### 成长期1000用户日活200
| **<EFBFBD><EFBFBD>** | | **瞼515/<EFBFBD>?* |
### <20>鞾鵭<E99EBE><E9B5AD><EFBFBD>1000<30><EFBFBD>嚗峕𠯫瘣?00嚗?
| <20>滚𦛚 | 閫<>聢 | <20><>晶 |
|------|------|------|
| SAE | 2C4G <20> 撟喳<E6929F>3摰硺<E691B0> | 瞼600 |
| RDS | 4C8G 通用版 | ¥600 |
| RDS | 4C8G <EFBFBD>𡁶鍂<EFBFBD>?| 600 |
| OSS | 500GB<47><42><EFBFBD>摮睃<E691AE> + 50GB瘚<42><E7989A> | 瞼70 |
| CDN | 100GB瘚<42><E7989A><EFBFBD><EFBFBD><EFBFBD> | 瞼20 |
| **合计** | | **¥1290/月** |
### 成熟期10000用户日活2000
| **<EFBFBD><EFBFBD>** | | **瞼1290/<EFBFBD>?* |
### <20><EFBFBD><E99E9F><EFBFBD><EFBFBD>10000<30><EFBFBD>嚗峕𠯫瘣?000嚗?
| <20>滚𦛚 | 閫<>聢 | <20><>晶 |
|------|------|------|
| SAE | 4C8G <20> 撟喳<E6929F>10摰硺<E691B0> | 瞼2000 |
| RDS | 8C16G 独享版 + 读写分离 | ¥2000 |
| RDS | 8C16G <EFBFBD>砌澈<EFBFBD>?+ 霂餃<E99C82><E9A483><EFBFBD> | 2000 |
| OSS | 2TB<54><42><EFBFBD>摮睃<E691AE> + 500GB瘚<42><E7989A> | 瞼300 |
| CDN | 1TB瘚<42><E7989A> | 瞼200 |
| Redis | 2GB标准版 | ¥200 |
| **合计** | | **¥4700/月** |
| Redis | 2GB<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?| 200 |
| **<EFBFBD><EFBFBD>** | | **瞼4700/<EFBFBD>?* |
---
## 🔍 监控与告警
### 应用性能监控ARMS
## <EFBFBD><EFBFBD> <20>烐綉銝𤾸<E98A9D>霅?
### 摨𠉛鍂<F0A0899B><EFBFBD><E689AF>烐綉嚗㇁RMS嚗?
```yaml
# SAE 控制台开通 ARMS
# <EFBFBD>?SAE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?ARMS
<EFBFBD>烐綉<EFBFBD><EFBFBD><EFBFBD>:
- RT嚗<EFBFBD><EFBFBD>摨娍𧒄<EFBFBD><EFBFBD>
- QPS(每秒请求数)
- 错误率
- JVM内存
- QPS<EFBFBD><EFBFBD>蝘坿窈瘙<EFBFBD>㺭嚗? - <20>躰秤<E8BAB0>? - JVM<56><4D><EFBFBD>
<EFBFBD>𡃏郎閫<EFBFBD><EFBFBD>:
- RT > 3
- 错误率 > 5%
- 可用率 < 99%
- RT > 3蝘? - <20>躰秤<E8BAB0>?> 5%
- <EFBFBD>舐鍂<EFBFBD>?< 99%
```
### 数据库监控
### <EFBFBD>唳旿摨梶<EFBFBD><EFBFBD>?
```yaml
# RDS 控制台 → 监控与报警
监控指标:
- CPU利用率
- 内存利用率
- 连接数
- IOPS
# RDS <EFBFBD><EFBFBD><EFBFBD>?<3F>?<3F>烐綉銝擧𥁒霅?<3F>烐綉<E78390><E7B689><EFBFBD>:
- CPU<EFBFBD>拍鍂<EFBFBD>? - <20><><EFBFBD><EFBFBD>拍鍂<E68B8D>? - 餈墧𦻖<E5A2A7>? - IOPS
<EFBFBD>𡃏郎閫<EFBFBD><EFBFBD>:
- CPU > 80%
- 连接数 > 32080%
- 磁盘使用率 > 80%
- 餈墧𦻖<EFBFBD>?> 320嚗?0%嚗? - 蝤<><E89DA4>雿輻鍂<E8BCBB>?> 80%
```
### <20>鞉𧋦<E99E89>𡃏郎
```bash
# 费用中心 → 费用预警
# 韐寧鍂銝剖<EFBFBD> <20>?韐寧鍂憸<E98D82>
霈曄蔭憸<EFBFBD><EFBFBD>:
- 瘥𤩺<E798A5><EFBFBD><E686B8>: 瞼1000
- 80%憸<>郎: 瞼800
@@ -1095,34 +1002,27 @@ curl http://<SAE公网地址>/api/v1/health
**<EFBFBD><EFBFBD>𠶖**嚗𡁜<E59A97><F0A1819C>典鍳<E585B8>典仃韐伐<E99F90><E4BC90><EFBFBD><E4BA99>曄內 `Connection refused`
**解决方案**
```bash
# 1. 检查 RDS 白名单
# 确保添加了 SAE 应用的 VPC网段
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**嚗?```bash
# 1. 璉<><E79289>?RDS <20><EFBFBD><E8B3A2>?# 蝖桐<E89D96>瘛餃<E7989B>鈭?SAE 摨𠉛鍂<F0A0899B>?VPC蝵烐挾
# 2. 检查 DATABASE_URL 格式
# 2. <EFBFBD><EFBFBD>?DATABASE_URL <EFBFBD><EFBFBD>
# 甇<><EFBFBD><EFBFBD>: postgresql://user:pass@host:port/db
# 3. 检查 RDS 实例状态
# 确保实例运行中
```
# 3. <EFBFBD><EFBFBD>?RDS 摰硺<E691B0><E7A1BA><EFBFBD>?# 蝖桐<E89D96>摰硺<E691B0>餈鞱<E9A488>銝?```
---
#### <20><EFBFBD>2嚗鐾SS 銝𠹺<E98A9D>憭梯揖
**症状**:文件上传返回 403 Forbidden
**<EFBFBD><EFBFBD>𠶖**嚗𡁏<E59A97>隞嗡<E99A9E>隡㰘<E99AA1><E3B098>?403 Forbidden
**解决方案**
```bash
# 1. 检查 RAM 用户权限
# 确保有 AliyunOSSFullAccess
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**嚗?```bash
# 1. 璉<><E79289>?RAM <20><EFBFBD><E586BD><EFBFBD><EFBFBD>
# 蝖桐<E89D96><E6A190>?AliyunOSSFullAccess
# 2. 检查 Bucket 权限
# 确保应用有写入权限
# 3. 检查环境变量
# OSS_ACCESS_KEY_ID 和 OSS_ACCESS_KEY_SECRET 是否正确
# 2. <EFBFBD><EFBFBD>?Bucket <EFBFBD><EFBFBD><EFBFBD>
# 蝖桐<EFBFBD>摨𠉛鍂<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
# 3. 璉<><E79289>亦㴓憓<E3B493><E68693><EFBFBD>?# OSS_ACCESS_KEY_ID <20>?OSS_ACCESS_KEY_SECRET <20>臬炏甇<E7828F>
```
---
@@ -1131,15 +1031,13 @@ curl http://<SAE公网地址>/api/v1/health
**<2A><>𠶖**嚗䫤Connection pool exhausted`
**解决方案**
```typescript
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**嚗?```typescript
// 1. 璉<><E79289><EFBFBD><E4BA99><EFBFBD><E6BBA9>交㺭
const result = await prisma.$queryRaw`
SELECT count(*) FROM pg_stat_activity
`
// 2. 调整连接池配置
// 减少每实例连接数,或增加 RDS 规格
// 2. <EFBFBD>㟲餈墧𦻖瘙𣳇<EFBFBD>蝵?// <20><EFBFBD>瘥誩<E798A5>靘贝<E99D98><E8B49D>交㺭嚗峕<E59A97>憓𧼮<E68693> RDS 閫<>
// 3. 璉<><E79289>交糓<E4BAA4><EFBFBD>餈墧𦻖瘜<F0A6BB96><E7989C>
// 蝖桐<E89D96><E6A190><EFBFBD><EFBFBD>㗇䰻霂<E99C82><EFBFBD><EFBFBD>喲𡡒
@@ -1149,7 +1047,7 @@ const result = await prisma.$queryRaw`
## <20><> <20>湔鰵<E6B994><EFBFBD>
| 日期 | 版本 | 变更内容 | 维护者 |
| <EFBFBD><EFBFBD> | <20><>𧋦 | <20>䀹凒<E480B9><E58792>捆 | 蝏湔擪<E6B994>?|
|------|------|---------|--------|
| 2025-11-16 | V1.0 | <20>𥕦遣<F0A595A6><E981A3>﹝嚗<EFB99D><E59A97>銋劐<E98A8B><E58A90><EFBFBD><E6AFBA>函蔡<E587BD><EFBFBD> | <20><EFBFBD><E59786><EFBFBD> |
@@ -1158,13 +1056,11 @@ const result = await prisma.$queryRaw`
## <20><> <20><EFBFBD><E8A9A8><EFBFBD>
- [<EFBFBD><EFBFBD>蝡舀芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霈曇恣-V2](../00-蝟餌<E89D9F><E9A48C><EFBFBD>霈曇恣/<2F><EFBFBD>蝡舀芋<E88880><EFBFBD><E5A092><EFBFBD>霈曇恣-V2.md) - <20><EFBFBD><E59786>餌熔
- [云原生开发规范](../04-开发规范/08-云原生开发规范.md) - DO/DON'T 检查清单
- [Schema隔离架构设计](./01-Schema隔离架构设计10个.md)
- [数据库连接配置](./02-数据库连接配置.md)
- [鈭穃<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𤏸<EFBFBD><EFBFBD><EFBFBD>(../04-撘<><E69298>𤏸<EFBFBD><F0A48FB8>?08-鈭穃<E988AD><E7A983><EFBFBD><E7AC94>𤏸<EFBFBD><F0A48FB8>?md) - DO/DON'T <EFBFBD><EFBFBD><EFBFBD><EFBFBD>?- [Schema<6D>𠉛氖<F0A0899B><EFBFBD>霈曇恣](./01-Schema<6D>𠉛氖<F0A0899B><EFBFBD>霈曇恣嚗?0銝迎<E98A9D>.md)
- [<EFBFBD>唳旿摨栞<EFBFBD><EFBFBD>仿<EFBFBD>蝵孫(./02-<2D>唳旿摨栞<E691A8><E6A09E>仿<EFBFBD>蝵?md)
---
**<EFBFBD><EFBFBD>﹝蝏湔擪<EFBFBD><EFBFBD><EFBFBD>** <20><EFBFBD><E59786><EFBFBD>
**<EFBFBD><EFBFBD><EFBFBD>擧凒<EFBFBD><EFBFBD>** 2025-11-16
**文档状态:** ✅ 已完成
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?