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 接口
|
|||
|
|
|||
|
**关键点:网关域负责"谁来处理",数据域负责"怎么处理"!**
|