支持"给一个单号拉出完整报告"。
流程图:全链路 Trace 流程
flowchart TD
A[代理商发起查价请求] --> B[API 网关
生成 trace_id]
B --> C[记录网关层 span
请求参数/认证/限流]
C --> D{缓存命中?}
D -->|是| E[返回缓存结果
记录 cache_hit span]
D -->|否| F[查价引擎分发]
F --> G[并行查询 N 个供应商]
G --> H[供应商适配器
每个供应商独立 span]
H --> I{供应商响应?}
I -->|成功| J[记录供应商返回数据]
I -->|超时| K[记录超时 span
触发熔断检查]
I -->|错误| L[记录错误详情]
J --> M[结果聚合排序]
K --> M
L --> M
M --> N[返回聚合结果]
N --> O{代理商试单?}
O -->|是| P[试单 span
记录试单请求]
P --> Q{试单结果?}
Q -->|成功| R[创建订单 span]
Q -->|失败| S[记录失败原因]
R --> T[订单确认 span]
S --> U[Trace 完成
全链路可追溯]
T --> U
U --> V[30 天内存 PG
之后归档 ClickHouse]
class D,I,O,Q decision
class E,U done
class L,S error
class A,B,C,F,G,H,J,K,M,N,P,R,T,V process
classDef process fill:#1a2744,stroke:#58a6ff,stroke-width:1px,color:#c9d1d9
classDef decision fill:#3a2a1a,stroke:#f0883e,stroke-width:2px,color:#f0883e
classDef done fill:#1a3a2a,stroke:#3fb950,stroke-width:1px,color:#3fb950
classDef error fill:#3a1a1a,stroke:#f85149,stroke-width:2px,color:#f85149
classDef warning fill:#3a2a1a,stroke:#d29922,stroke-width:1px,color:#d29922
classDef skip fill:#21262d,stroke:#484f58,color:#8b949e
数据模型
CREATE TABLE trace_events (
id BIGSERIAL PRIMARY KEY,
trace_id VARCHAR(64) NOT NULL, -- 链路追踪 ID
span_id VARCHAR(64) NOT NULL, -- 当前环节 ID
parent_span_id VARCHAR(64), -- 父环节 ID
event_type VARCHAR(64) NOT NULL, -- search/cache_hit/supplier_query/trial/book/confirm/settle
service VARCHAR(32) NOT NULL, -- api_gateway/query_engine/supplier_adapter/...
related_type VARCHAR(32), -- order/supplier/agent/hotel
related_id VARCHAR(64),
request_data JSONB,
response_data JSONB,
duration_ms INT,
status VARCHAR(16) NOT NULL, -- success/error/timeout
error_detail TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_trace_trace_id ON trace_events(trace_id);
CREATE INDEX idx_trace_related ON trace_events(related_type, related_id);
CREATE INDEX idx_trace_created ON trace_events(created_at);
热数据存 PG(30天),冷数据归档到 ClickHouse。
API 接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/traces/{trace_id} | 按 Trace ID 查询 |
| GET | /api/traces/by-order/{order_id} | 按订单号查询 |
| GET | /api/traces/by-hotel/{hotel_id} | 按酒店 ID 查询 |
业务逻辑
每个请求进入 API 网关时生成 trace_id,在服务间调用链中透传。每个服务处理完请求后写入一条 trace_events 记录,包含 span_id(当前环节)和 parent_span_id(上游环节),形成树状调用链。查询时通过 related_type + related_id 可快速定位某个订单/酒店的所有链路事件。PG 存储最近 30 天热数据,超过 30 天的数据通过定时任务归档到 ClickHouse,查询 API 自动路由到对应存储。
hotel-distribution-platform/
├── cmd/
│ ├── api/ # API 服务入口
│ ├── admin/ # 管理后台后端入口
│ ├── worker/ # 异步任务 worker
│ └── migrate/ # 数据库迁移工具
├── internal/
│ ├── config/ # 配置管理
│ ├── middleware/ # Gin 中间件 (鉴权/限流/日志)
│ ├── handler/ # HTTP handlers
│ │ ├── hotel/
│ │ ├── pricing/
│ │ ├── order/
│ │ ├── matching/
│ │ ├── settlement/
│ │ └── admin/
│ ├── service/ # 业务逻辑层
│ │ ├── hotel.go
│ │ ├── matching.go
│ │ ├── pricing_engine.go
│ │ ├── order.go
│ │ ├── inventory.go
│ │ ├── settlement.go
│ │ ├── risk.go
│ │ └── agent.go
│ ├── repository/ # 数据访问层
│ │ ├── postgres/
│ │ └── redis/
│ ├── model/ # 数据模型
│ ├── supplier/ # 供应商适配器
│ │ ├── adapter.go # 统一接口
│ │ ├── hotelbeds/
│ │ ├── expedia/
│ │ └── mock/
│ ├── task/ # 异步任务定义
│ └── pkg/ # 内部工具包
│ ├── cache/
│ ├── httputil/
│ ├── money/
│ └── validation/
├── api/ # OpenAPI/Swagger 定义
├── migrations/ # SQL 迁移文件
├── deployments/ # Docker/Compose 文件
│ ├── docker-compose.yml
│ └── Dockerfile
├── scripts/ # 运维脚本
├── docs/ # 文档
├── web/ # Vue 3 管理后台前端
│ ├── src/
│ │ ├── views/
│ │ ├── components/
│ │ ├── api/
│ │ ├── store/
│ │ └── router/
│ └── package.json
├── go.mod
├── go.sum
├── Makefile
└── README.md
// internal/supplier/adapter.go
// SupplierAdapter 供应商统一适配接口
type SupplierAdapter interface {
// 基本信息
Name() string
Code() string
// 搜索酒店
SearchHotels(ctx context.Context, req *SearchHotelsRequest) (*SearchHotelsResponse, error)
// 查价
SearchRates(ctx context.Context, req *SearchRatesRequest) (*SearchRatesResponse, error)
// 预订
CreateBooking(ctx context.Context, req *CreateBookingRequest) (*CreateBookingResponse, error)
// 取消预订
CancelBooking(ctx context.Context, req *CancelBookingRequest) (*CancelBookingResponse, error)
// 查询订单
GetBooking(ctx context.Context, bookingRef string) (*BookingDetail, error)
// 库存查询
CheckAvailability(ctx context.Context, req *CheckAvailabilityRequest) (*CheckAvailabilityResponse, error)
// 健康检查
HealthCheck(ctx context.Context) error
}
// 请求/响应结构体定义...
# config/config.yaml
server:
port: 8080
mode: development # development / production
read_timeout: 30s
write_timeout: 60s
database:
host: localhost
port: 5432
user: hotel_platform
password: ${DB_PASSWORD}
dbname: hotel_platform
max_open_conns: 50
max_idle_conns: 10
redis:
host: localhost
port: 6379
password: ${REDIS_PASSWORD}
db: 0
pool_size: 20
pricing:
cache_ttl: 300s # 查价缓存 5 分钟
local_cache_ttl: 60s # 本地缓存 1 分钟
supplier_timeout: 3s # 单供应商查询超时
max_concurrent: 10 # 最大并发查价数
default_currency: CNY
inventory:
hold_ttl: 1800s # 库存预占 30 分钟
cleanup_interval: 300s # 清理间隔 5 分钟
sync_interval: 600s # 库存同步间隔 10 分钟
risk:
credit_check_enabled: true
price_check_enabled: true
rate_limit_per_minute: 60 # 默认每分钟限流
log:
level: info
format: json
output: stdout
suppliers:
hotelbeds:
enabled: true
api_key: ${HOTELBEDS_API_KEY}
api_secret: ${HOTELBEDS_API_SECRET}
endpoint: https://api.hotelbeds.com
timeout: 5s
priority: 10
expedia:
enabled: false
api_key: ${EXPEDIA_API_KEY}
endpoint: https://api.expediapartners.com
timeout: 5s
priority: 5
文档结束
本文档为 B2B2B 酒店分销平台系统架构的完整设计,涵盖 12 个模块的详细设计、技术选型、成本估算和开发路线图。
适用于 Demo 驱动融资场景,后续可根据投资人反馈和实际业务需求迭代优化。