tianyuan-api-server/API调用流程域设计.md
2025-07-13 20:37:12 +08:00

450 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API 调用流程域设计分析
## 🎯 业务流程分析
根据你描述的场景,这是一个典型的**B2B 数据服务 API 调用流程**
```
用户企业 → 调用我们的产品API → 获取第三方大数据服务 → 计费扣款
```
## 🏗️ 涉及的业务域分析
这个流程总共涉及 **6 个核心域**
### 1. 🚪 **网关域 (Gateway Domain)**
- **职责**: 统一入口、基础路由、请求预处理
- **功能**:
- 接收所有外部请求
- 基础的请求验证
- 路由到具体的业务域
### 2. 🛡️ **安全域 (Security Domain)**
- **职责**: 认证授权、加密解密、白名单管理
- **功能**:
- IP 白名单验证
- 企业 ID 验证
- 密钥管理
- 请求参数解密
### 3. 👤 **用户域 (User Domain)**
- **职责**: 用户和企业信息管理
- **功能**:
- 企业认证信息验证
- 用户权限检查
- 企业密钥获取
### 4. 📦 **产品域 (Product Domain)**
- **职责**: 产品访问控制、权限管理
- **功能**:
- 产品访问权限验证
- API 限额检查
- 产品配置管理
### 5. 📊 **数据服务域 (Data Service Domain)**
- **职责**: 核心业务逻辑、第三方 API 调用
- **功能**:
- 参数处理和转换
- 调用上游数据公司 API
- 数据格式转换和响应
### 6. 💰 **计费域 (Billing Domain)**
- **职责**: 计费扣款、账单管理
- **功能**:
- 钱包余额检查
- 费用计算
- 扣款操作
- 计费记录
### 7. 📋 **审计域 (Audit Domain)**
- **职责**: 请求记录、日志管理
- **功能**:
- API 调用记录
- 操作日志
- 审计追踪
## 🔄 完整流程设计
### 架构图
```
┌─────────────┐
│ 客户端 │
└─────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 网关域 (Gateway) │
│ • 请求接收 • 基础验证 • 路由分发 • 响应聚合 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 数据服务域 (Data Service) │
│ [主要协调者] │
└─────────────────────────────────────────────────────────────┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐
│安全域 ││用户域 ││产品域 ││计费域 ││审计域 ││第三方 │
│Security││User ││Product ││Billing ││Audit ││API │
└────────┘└────────┘└────────┘└────────┘└────────┘└────────┘
```
### 详细流程设计
```go
// 完整的API调用流程
func (h *DataServiceHandler) ProcessAPIRequest(ctx context.Context, req *APIRequest) (*APIResponse, error) {
// 1. 审计域 - 开始记录
auditID := h.auditService.StartRequest(ctx, req)
defer h.auditService.EndRequest(ctx, auditID)
// 2. 安全域 - IP白名单验证
if err := h.securityService.ValidateIP(ctx, req.ClientIP); err != nil {
return nil, errors.Wrap(err, "IP not in whitelist")
}
// 3. 用户域 - 企业ID验证
enterprise, err := h.userService.GetEnterpriseByID(ctx, req.EnterpriseID)
if err != nil {
return nil, errors.Wrap(err, "invalid enterprise ID")
}
// 4. 安全域 - 获取密钥并解密参数
secretKey, err := h.securityService.GetEnterpriseSecret(ctx, req.EnterpriseID)
if err != nil {
return nil, errors.Wrap(err, "failed to get enterprise secret")
}
decryptedParams, err := h.securityService.DecryptParams(ctx, req.EncryptedParams, secretKey)
if err != nil {
return nil, errors.Wrap(err, "failed to decrypt parameters")
}
// 5. 产品域 - 产品权限验证
if err := h.productService.ValidateAccess(ctx, enterprise.ID, req.ProductCode); err != nil {
return nil, errors.Wrap(err, "no access to product")
}
// 6. 计费域 - 检查余额
cost, err := h.billingService.CalculateCost(ctx, req.ProductCode, decryptedParams)
if err != nil {
return nil, errors.Wrap(err, "failed to calculate cost")
}
if err := h.billingService.CheckBalance(ctx, enterprise.ID, cost); err != nil {
return nil, errors.Wrap(err, "insufficient balance")
}
// 7. 数据服务域 - 调用第三方API
upstreamResp, err := h.callUpstreamAPI(ctx, decryptedParams)
if err != nil {
return nil, errors.Wrap(err, "upstream API call failed")
}
// 8. 计费域 - 扣费
if err := h.billingService.ChargeAccount(ctx, enterprise.ID, cost, auditID); err != nil {
// 记录扣费失败,但不影响响应
h.logger.Error("charge failed", zap.Error(err), zap.String("audit_id", auditID))
}
// 9. 安全域 - 加密响应
encryptedResp, err := h.securityService.EncryptResponse(ctx, upstreamResp, secretKey)
if err != nil {
return nil, errors.Wrap(err, "failed to encrypt response")
}
return &APIResponse{
Data: encryptedResp,
RequestID: auditID,
}, nil
}
```
## 🚪 路由入口设计
### 1. 网关层路由配置
```yaml
# gateway.yaml
routes:
- path: /api/v1/data/*
service: data-service
middlewares:
- request-id # 生成请求ID
- rate-limit # 基础限流
- audit-start # 开始审计
timeout: 60s
- path: /api/v1/admin/*
service: admin-service
middlewares: [admin-auth, rate-limit]
- path: /api/v1/user/*
service: user-service
middlewares: [user-auth, rate-limit]
```
### 2. 网关中间件
```go
// 网关层的请求预处理中间件
func DataAPIMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 1. 生成请求ID
requestID := uuid.New().String()
c.Set("request_id", requestID)
c.Header("X-Request-ID", requestID)
// 2. 提取企业ID从Header或路径参数
enterpriseID := extractEnterpriseID(c)
if enterpriseID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "missing enterprise ID"})
c.Abort()
return
}
c.Set("enterprise_id", enterpriseID)
// 3. 提取客户端IP
clientIP := c.ClientIP()
c.Set("client_ip", clientIP)
// 4. 提取产品代码
productCode := c.Param("product_code")
c.Set("product_code", productCode)
c.Next()
}
}
func extractEnterpriseID(c *gin.Context) string {
// 优先从Header获取
if id := c.GetHeader("X-Enterprise-ID"); id != "" {
return id
}
// 从路径参数获取
return c.Param("enterprise_id")
}
```
### 3. 数据服务域作为主协调者
```go
// 数据服务域的HTTP处理器
type DataServiceHandler struct {
securityService *SecurityService
userService *UserService
productService *ProductService
billingService *BillingService
auditService *AuditService
upstreamClient *UpstreamAPIClient
logger *zap.Logger
}
// API端点定义
func (h *DataServiceHandler) RegisterRoutes(r *gin.RouterGroup) {
// 具体的数据产品API
r.POST("/financial-data", h.GetFinancialData)
r.POST("/credit-check", h.GetCreditCheck)
r.POST("/risk-assessment", h.GetRiskAssessment)
r.POST("/company-info", h.GetCompanyInfo)
}
// 具体业务处理器
func (h *DataServiceHandler) GetFinancialData(c *gin.Context) {
ctx := c.Request.Context()
// 构建请求对象
req := &APIRequest{
RequestID: c.GetString("request_id"),
EnterpriseID: c.GetString("enterprise_id"),
ProductCode: "FINANCIAL_DATA",
ClientIP: c.GetString("client_ip"),
EncryptedParams: c.PostForm("data"),
}
// 调用业务逻辑
resp, err := h.ProcessAPIRequest(ctx, req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": err.Error(),
"request_id": req.RequestID,
})
return
}
c.JSON(http.StatusOK, resp)
}
```
## 🔄 域间通信设计
### 1. 事件驱动架构
```go
// 定义领域事件
type APIRequestStarted struct {
RequestID string `json:"request_id"`
EnterpriseID string `json:"enterprise_id"`
ProductCode string `json:"product_code"`
ClientIP string `json:"client_ip"`
Timestamp time.Time `json:"timestamp"`
}
type APIRequestCompleted struct {
RequestID string `json:"request_id"`
EnterpriseID string `json:"enterprise_id"`
ProductCode string `json:"product_code"`
Success bool `json:"success"`
Cost float64 `json:"cost"`
Duration int64 `json:"duration_ms"`
Timestamp time.Time `json:"timestamp"`
}
type ChargeRequired struct {
RequestID string `json:"request_id"`
EnterpriseID string `json:"enterprise_id"`
Amount float64 `json:"amount"`
ProductCode string `json:"product_code"`
}
```
### 2. 异步处理
```go
// 异步计费处理
func (s *BillingService) HandleChargeRequired(event ChargeRequired) error {
// 异步处理计费,避免阻塞主流程
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := s.ProcessCharge(ctx, event); err != nil {
s.logger.Error("async charge failed",
zap.Error(err),
zap.String("request_id", event.RequestID))
// 发送补偿事件
s.eventBus.Publish(ChargeFailed{
RequestID: event.RequestID,
Error: err.Error(),
})
}
}()
return nil
}
```
## 📊 性能和可扩展性考虑
### 1. 缓存策略
```go
// 多级缓存策略
type CacheStrategy struct {
// L1: 本地缓存 (企业信息、产品配置)
localCache *cache.Cache
// L2: Redis缓存 (密钥、白名单)
redisCache *redis.Client
// L3: 数据库
db *gorm.DB
}
func (cs *CacheStrategy) GetEnterpriseSecret(enterpriseID string) (string, error) {
// L1缓存查找
if secret, found := cs.localCache.Get("secret:" + enterpriseID); found {
return secret.(string), nil
}
// L2缓存查找
if secret, err := cs.redisCache.Get(context.Background(), "secret:"+enterpriseID).Result(); err == nil {
cs.localCache.Set("secret:"+enterpriseID, secret, 5*time.Minute)
return secret, nil
}
// L3数据库查找
var enterprise Enterprise
if err := cs.db.Where("id = ?", enterpriseID).First(&enterprise).Error; err != nil {
return "", err
}
// 写入缓存
cs.redisCache.Set(context.Background(), "secret:"+enterpriseID, enterprise.SecretKey, time.Hour)
cs.localCache.Set("secret:"+enterpriseID, enterprise.SecretKey, 5*time.Minute)
return enterprise.SecretKey, nil
}
```
### 2. 熔断器模式
```go
// 上游API调用熔断器
func (s *DataService) callUpstreamAPI(ctx context.Context, params map[string]interface{}) (*UpstreamResponse, error) {
return s.circuitBreaker.Execute(func() (interface{}, error) {
client := &http.Client{Timeout: 30 * time.Second}
// 构建请求
reqBody, _ := json.Marshal(params)
req, _ := http.NewRequestWithContext(ctx, "POST", s.upstreamURL, bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+s.upstreamToken)
// 发送请求
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 解析响应
var upstreamResp UpstreamResponse
if err := json.NewDecoder(resp.Body).Decode(&upstreamResp); err != nil {
return nil, err
}
return &upstreamResp, nil
})
}
```
## 🎯 总结
### 涉及的域数量:**7 个域**
1. 网关域 - 统一入口
2. 安全域 - 认证加密
3. 用户域 - 企业验证
4. 产品域 - 权限控制
5. 数据服务域 - 核心业务
6. 计费域 - 扣费计算
7. 审计域 - 请求记录
### 路由入口设计:
- **主入口**: 网关域 (`/api/v1/data/`)
- **业务协调**: 数据服务域作为主要协调者
- **域间通信**: 通过 gRPC 调用和事件总线
### 设计优势:
1. **清晰的职责分离** - 每个域专注自己的业务
2. **高可扩展性** - 可以独立扩展任何一个域
3. **易于测试** - 每个域可以独立测试
4. **容错性强** - 单个域故障不影响整体
5. **性能优化** - 多级缓存和异步处理
这种设计既保证了业务逻辑的清晰性,又确保了系统的高性能和高可用性。