415 lines
16 KiB
Markdown
415 lines
16 KiB
Markdown
# 网关域架构与跨域调用实现详解
|
||
|
||
## 🌐 网关域的职责与架构
|
||
|
||
### 网关域的核心职责
|
||
|
||
```
|
||
网关域 (Gateway Domain) = API网关 + 路由管理 + 协议转换
|
||
```
|
||
|
||
**主要功能:**
|
||
|
||
1. **统一入口** - 所有外部请求的唯一入口点
|
||
2. **路由分发** - 根据路径将请求分发到对应的域服务
|
||
3. **协议转换** - HTTP ↔ gRPC 转换
|
||
4. **横切关注点** - 认证、限流、监控、日志
|
||
5. **服务发现** - 动态发现后端服务
|
||
|
||
### 网关域架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Gateway Domain │
|
||
│ ┌─────────────────────────────────────────────────────────┐│
|
||
│ │ Gateway Service ││
|
||
│ │ ││
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
|
||
│ │ │ HTTP │ │ Router │ │ gRPC │ ││
|
||
│ │ │ Handlers │ │ Engine │ │ Clients │ ││
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││
|
||
│ │ ││
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
|
||
│ │ │ Auth │ │ Rate Limit │ │ Monitor │ ││
|
||
│ │ │ Middleware │ │ Middleware │ │ Middleware │ ││
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││
|
||
│ └─────────────────────────────────────────────────────────┘│
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||
│ User Domain │ │ Data Domain │ │ Billing Domain │
|
||
│ (User Service) │ │ (Data Service) │ │(Billing Service)│
|
||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||
```
|
||
|
||
## 🏗️ 网关域的目录结构
|
||
|
||
```
|
||
domains/gateway-domain/
|
||
└── gateway-service/
|
||
├── cmd/
|
||
│ └── server/
|
||
│ └── main.go # 网关服务启动入口
|
||
│
|
||
├── api/
|
||
│ └── http/
|
||
│ └── gateway.api # 网关API定义
|
||
│
|
||
├── internal/
|
||
│ ├── application/ # 应用层
|
||
│ │ └── service/
|
||
│ │ └── gateway_orchestrator.go # 🔥 核心协调器
|
||
│ │
|
||
│ ├── domain/ # 领域层
|
||
│ │ ├── entity/
|
||
│ │ │ ├── route.go # 路由实体
|
||
│ │ │ └── service_endpoint.go # 服务端点
|
||
│ │ └── service/
|
||
│ │ ├── router_service.go # 路由服务
|
||
│ │ └── discovery_service.go # 服务发现
|
||
│ │
|
||
│ ├── infrastructure/ # 基础设施层
|
||
│ │ ├── client/ # gRPC客户端
|
||
│ │ │ ├── user_client.go
|
||
│ │ │ ├── data_client.go
|
||
│ │ │ ├── security_client.go
|
||
│ │ │ ├── billing_client.go
|
||
│ │ │ └── product_client.go
|
||
│ │ ├── discovery/ # 服务发现
|
||
│ │ │ └── etcd_discovery.go
|
||
│ │ └── config/
|
||
│ │ └── service_config.go # 服务配置
|
||
│ │
|
||
│ └── interfaces/ # 接口适配器层
|
||
│ ├── http/ # HTTP处理器
|
||
│ │ ├── data_handler.go # 数据服务API处理
|
||
│ │ ├── user_handler.go # 用户服务API处理
|
||
│ │ └── billing_handler.go # 计费服务API处理
|
||
│ ├── middleware/ # 中间件
|
||
│ │ ├── auth_middleware.go # 认证中间件
|
||
│ │ ├── rate_limit_middleware.go # 限流中间件
|
||
│ │ ├── audit_middleware.go # 审计中间件
|
||
│ │ └── cors_middleware.go # CORS中间件
|
||
│ └── router/
|
||
│ └── gateway_router.go # 路由配置
|
||
│
|
||
├── configs/
|
||
│ ├── gateway.yaml # 网关配置
|
||
│ └── routes.yaml # 路由配置
|
||
│
|
||
└── deployments/
|
||
├── Dockerfile
|
||
└── k8s/
|
||
```
|
||
|
||
## 🎯 核心实现:跨域调用 Logic 在哪里
|
||
|
||
### 1. 网关层的协调逻辑 (Gateway Orchestrator)
|
||
|
||
```go
|
||
// domains/gateway-domain/gateway-service/internal/application/service/gateway_orchestrator.go
|
||
|
||
type GatewayOrchestrator struct {
|
||
// gRPC客户端 - 调用各个域服务
|
||
userClient user.UserServiceClient
|
||
dataClient data.DataServiceClient
|
||
securityClient security.SecurityServiceClient
|
||
billingClient billing.BillingServiceClient
|
||
productClient product.ProductServiceClient
|
||
auditClient audit.AuditServiceClient
|
||
|
||
// 网关自身的服务
|
||
routerService *RouterService
|
||
discoveryService *DiscoveryService
|
||
}
|
||
|
||
// 🔥 这里实现跨域调用的核心逻辑
|
||
func (g *GatewayOrchestrator) ProcessAPIRequest(ctx context.Context, req *APIRequest) (*APIResponse, error) {
|
||
// 1. 解析路由 - 确定目标域
|
||
route, err := g.routerService.ResolveRoute(req.Path)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 根据不同的业务场景,实现不同的协调逻辑
|
||
switch route.Domain {
|
||
case "data":
|
||
return g.handleDataDomainRequest(ctx, req)
|
||
case "user":
|
||
return g.handleUserDomainRequest(ctx, req)
|
||
case "billing":
|
||
return g.handleBillingDomainRequest(ctx, req)
|
||
default:
|
||
return nil, errors.New("unknown domain")
|
||
}
|
||
}
|
||
|
||
// 🔥 数据域请求的协调逻辑 (你之前问的API调用流程)
|
||
func (g *GatewayOrchestrator) handleDataDomainRequest(ctx context.Context, req *APIRequest) (*APIResponse, error) {
|
||
// 注意:这里只做最基础的协调,复杂的业务逻辑在Data Domain内部
|
||
|
||
// 1. 前置验证 (网关层职责)
|
||
if err := g.validateBasicRequest(req); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 认证检查 (网关层职责)
|
||
userInfo, err := g.authenticateUser(ctx, req.Headers.Authorization)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 3. 调用数据域服务 (核心业务逻辑在数据域内部)
|
||
dataReq := &data.ProcessAPIRequestRequest{
|
||
UserId: userInfo.UserId,
|
||
EnterpriseId: userInfo.EnterpriseId,
|
||
ApiPath: req.Path,
|
||
Parameters: req.Parameters,
|
||
ClientIp: req.ClientIP,
|
||
}
|
||
|
||
// 🚨 重点:复杂的跨域协调逻辑在数据域的DataOrchestrator中实现
|
||
dataResp, err := g.dataClient.ProcessAPIRequest(ctx, dataReq)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 4. 响应转换 (网关层职责)
|
||
return g.convertToHTTPResponse(dataResp), nil
|
||
}
|
||
|
||
// 简单的认证逻辑 (复杂认证在User Domain)
|
||
func (g *GatewayOrchestrator) authenticateUser(ctx context.Context, authHeader string) (*UserInfo, error) {
|
||
// 调用用户域进行认证
|
||
authReq := &user.AuthenticateRequest{
|
||
Token: authHeader,
|
||
}
|
||
|
||
authResp, err := g.userClient.Authenticate(ctx, authReq)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &UserInfo{
|
||
UserId: authResp.UserId,
|
||
EnterpriseId: authResp.EnterpriseId,
|
||
}, nil
|
||
}
|
||
```
|
||
|
||
### 2. 数据域的协调逻辑 (Data Orchestrator)
|
||
|
||
```go
|
||
// domains/data-domain/data-service/internal/application/service/data_orchestrator.go
|
||
|
||
type DataOrchestrator struct {
|
||
// 数据域内部的业务服务
|
||
riskService *RiskAssessmentService // 原FLXG
|
||
creditService *CreditCheckService // 原JRZQ
|
||
companyService *CompanyInfoService // 原QYGL
|
||
queryService *DataQueryService // 原IVYZ
|
||
|
||
// 其他域的gRPC客户端
|
||
securityClient SecurityServiceClient // 安全域
|
||
userClient UserServiceClient // 用户域
|
||
productClient ProductServiceClient // 产品域
|
||
billingClient BillingServiceClient // 计费域
|
||
auditClient AuditServiceClient // 审计域
|
||
}
|
||
|
||
// 🔥 这里实现你问的那个复杂API调用流程的核心协调逻辑
|
||
func (d *DataOrchestrator) ProcessAPIRequest(ctx context.Context, req *ProcessAPIRequestRequest) (*ProcessAPIResponseResponse, error) {
|
||
|
||
// === 第一阶段:安全验证 ===
|
||
|
||
// 1. IP白名单验证 (调用安全域)
|
||
whitelistReq := &security.CheckWhitelistRequest{
|
||
EnterpriseId: req.EnterpriseId,
|
||
ClientIp: req.ClientIp,
|
||
}
|
||
if _, err := d.securityClient.CheckWhitelist(ctx, whitelistReq); err != nil {
|
||
return nil, fmt.Errorf("IP白名单验证失败: %w", err)
|
||
}
|
||
|
||
// 2. 企业ID验证 (调用用户域)
|
||
enterpriseReq := &user.ValidateEnterpriseRequest{
|
||
UserId: req.UserId,
|
||
EnterpriseId: req.EnterpriseId,
|
||
}
|
||
enterpriseResp, err := d.userClient.ValidateEnterprise(ctx, enterpriseReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("企业验证失败: %w", err)
|
||
}
|
||
|
||
// 3. 密钥解密 (调用安全域)
|
||
decryptReq := &security.DecryptSecretRequest{
|
||
EnterpriseId: req.EnterpriseId,
|
||
EncryptedKey: enterpriseResp.EncryptedSecretKey,
|
||
}
|
||
decryptResp, err := d.securityClient.DecryptSecret(ctx, decryptReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("密钥解密失败: %w", err)
|
||
}
|
||
|
||
// === 第二阶段:权限与产品验证 ===
|
||
|
||
// 4. 产品权限检查 (调用产品域)
|
||
productReq := &product.CheckProductAccessRequest{
|
||
UserId: req.UserId,
|
||
ApiPath: req.ApiPath,
|
||
SecretKey: decryptResp.SecretKey,
|
||
}
|
||
productResp, err := d.productClient.CheckProductAccess(ctx, productReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("产品权限检查失败: %w", err)
|
||
}
|
||
|
||
// 5. 余额检查 (调用计费域)
|
||
balanceReq := &billing.CheckBalanceRequest{
|
||
UserId: req.UserId,
|
||
ProductCode: productResp.ProductCode,
|
||
ApiPath: req.ApiPath,
|
||
}
|
||
balanceResp, err := d.billingClient.CheckBalance(ctx, balanceReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("余额检查失败: %w", err)
|
||
}
|
||
|
||
// === 第三阶段:业务处理 ===
|
||
|
||
// 6. 根据API路径选择对应的业务服务 (数据域内部逻辑)
|
||
var businessResult *BusinessResult
|
||
switch {
|
||
case strings.Contains(req.ApiPath, "risk-assessment"):
|
||
businessResult, err = d.riskService.ProcessRequest(ctx, req.Parameters)
|
||
case strings.Contains(req.ApiPath, "credit-check"):
|
||
businessResult, err = d.creditService.ProcessRequest(ctx, req.Parameters)
|
||
case strings.Contains(req.ApiPath, "company-info"):
|
||
businessResult, err = d.companyService.ProcessRequest(ctx, req.Parameters)
|
||
case strings.Contains(req.ApiPath, "data-query"):
|
||
businessResult, err = d.queryService.ProcessRequest(ctx, req.Parameters)
|
||
default:
|
||
return nil, errors.New("不支持的API路径")
|
||
}
|
||
|
||
if err != nil {
|
||
return nil, fmt.Errorf("业务处理失败: %w", err)
|
||
}
|
||
|
||
// === 第四阶段:计费与审计 ===
|
||
|
||
// 7. 计费扣款 (调用计费域)
|
||
chargeReq := &billing.ChargeRequest{
|
||
UserId: req.UserId,
|
||
ProductCode: productResp.ProductCode,
|
||
ApiPath: req.ApiPath,
|
||
Amount: balanceResp.RequiredAmount,
|
||
RequestId: generateRequestId(),
|
||
}
|
||
chargeResp, err := d.billingClient.Charge(ctx, chargeReq)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("计费失败: %w", err)
|
||
}
|
||
|
||
// 8. 记录审计日志 (调用审计域)
|
||
auditReq := &audit.RecordAPICallRequest{
|
||
UserId: req.UserId,
|
||
EnterpriseId: req.EnterpriseId,
|
||
ApiPath: req.ApiPath,
|
||
ClientIp: req.ClientIp,
|
||
RequestId: chargeResp.TransactionId,
|
||
Result: "success",
|
||
ResponseTime: time.Since(startTime).Milliseconds(),
|
||
}
|
||
go d.auditClient.RecordAPICall(context.Background(), auditReq) // 异步记录
|
||
|
||
// 9. 返回最终结果
|
||
return &ProcessAPIResponseResponse{
|
||
Success: true,
|
||
Data: businessResult.Data,
|
||
TransactionId: chargeResp.TransactionId,
|
||
RemainingBalance: chargeResp.RemainingBalance,
|
||
}, nil
|
||
}
|
||
```
|
||
|
||
### 3. HTTP 处理器 (接口适配器层)
|
||
|
||
```go
|
||
// domains/gateway-domain/gateway-service/internal/interfaces/http/data_handler.go
|
||
|
||
type DataHandler struct {
|
||
orchestrator *GatewayOrchestrator
|
||
}
|
||
|
||
// HTTP入口点
|
||
func (h *DataHandler) HandleDataAPI(c *gin.Context) {
|
||
// 1. HTTP请求转换
|
||
req := &APIRequest{
|
||
Path: c.Request.URL.Path,
|
||
Method: c.Request.Method,
|
||
Parameters: extractParameters(c),
|
||
Headers: extractHeaders(c),
|
||
ClientIP: c.ClientIP(),
|
||
}
|
||
|
||
// 2. 调用网关协调器
|
||
resp, err := h.orchestrator.ProcessAPIRequest(c.Request.Context(), req)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
// 3. HTTP响应
|
||
c.JSON(http.StatusOK, resp)
|
||
}
|
||
```
|
||
|
||
## 🌊 完整的调用流程
|
||
|
||
```
|
||
1. 客户端 HTTP请求
|
||
↓
|
||
2. 网关域 (Gateway Domain)
|
||
├── HTTP Handler (接口适配器层)
|
||
├── Gateway Orchestrator (应用层)
|
||
│ ├── 基础验证
|
||
│ ├── 用户认证 → User Domain
|
||
│ └── 路由到目标域
|
||
└── 调用 Data Domain
|
||
↓
|
||
3. 数据域 (Data Domain)
|
||
└── Data Orchestrator (应用层) 🔥 核心协调逻辑
|
||
├── 安全验证 → Security Domain
|
||
├── 企业验证 → User Domain
|
||
├── 权限检查 → Product Domain
|
||
├── 余额检查 → Billing Domain
|
||
├── 业务处理 (内部服务)
|
||
├── 计费扣款 → Billing Domain
|
||
└── 审计记录 → Audit Domain
|
||
```
|
||
|
||
## 🎯 总结:Logic 实现的分层
|
||
|
||
### 1. **网关域的职责** (简单协调)
|
||
|
||
- HTTP 协议处理
|
||
- 路由分发
|
||
- 基础认证
|
||
- 中间件处理 (限流、CORS 等)
|
||
|
||
### 2. **数据域的职责** (复杂协调) 🔥
|
||
|
||
- **这里是你问的那个复杂 API 调用流程的主要实现位置**
|
||
- 跨域服务协调
|
||
- 业务流程编排
|
||
- 事务一致性保证
|
||
|
||
### 3. **其他域的职责** (专业服务)
|
||
|
||
- 各自领域的专业逻辑
|
||
- 对外提供 gRPC 接口
|
||
|
||
**关键点:网关域负责"谁来处理",数据域负责"怎么处理"!**
|