进阶项目:分布式订单处理系统
本项目实现一个基于 Temporal 的分布式订单处理系统,包含订单创建、支付处理、库存管理、订单状态追踪等完整功能。
5.1 项目概述
系统架构
┌─────────────────────────────────────────────────────────────────────────┐
│ Order Processing System │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Starter │───▶│ Worker │───▶│ Temporal │ │
│ │ (Client) │ │ (Order) │ │ Server │ │
│ └──────────────┘ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Worker Processes │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Order │ │ Payment │ │ Inventory │ │ │
│ │ │ Worker │ │ Worker │ │ Worker │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘项目结构
distributed-order/
├── cmd/
│ ├── worker/
│ │ ├── main.go
│ │ ├── order.go
│ │ ├── payment.go
│ │ └── inventory.go
│ ├── starter/
│ │ └── main.go
│ └── admin/
│ └── main.go
├── internal/
│ ├── workflow/
│ │ ├── order.go
│ │ ├── saga.go
│ │ └── batch.go
│ ├── activity/
│ │ ├── order.go
│ │ ├── payment.go
│ │ ├── inventory.go
│ │ └── notification.go
│ ├── types/
│ │ └── order.go
│ └── client/
│ └── client.go
├── config.yaml
└── go.mod5.2 核心类型定义
go
// internal/types/order.go
package types
import (
"time"
)
type OrderStatus string
const (
OrderStatusPending OrderStatus = "pending"
OrderStatusValidated OrderStatus = "validated"
OrderStatusPaid OrderStatus = "paid"
OrderStatusReserved OrderStatus = "reserved"
OrderStatusShipped OrderStatus = "shipped"
OrderStatusCompleted OrderStatus = "completed"
OrderStatusCancelled OrderStatus = "cancelled"
OrderStatusFailed OrderStatus = "failed"
)
// Order 订单
type Order struct {
ID string `json:"id"`
CustomerID string `json:"customer_id"`
Items []OrderItem `json:"items"`
TotalAmount float64 `json:"total_amount"`
Status OrderStatus `json:"status"`
PaymentID string `json:"payment_id,omitempty"`
ShippingID string `json:"shipping_id,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// OrderItem 订单商品
type OrderItem struct {
ProductID string `json:"product_id"`
ProductName string `json:"product_name"`
Quantity int `json:"quantity"`
Price float64 `json:"price"`
Subtotal float64 `json:"subtotal"`
}
// Payment 支付信息
type Payment struct {
ID string `json:"id"`
OrderID string `json:"order_id"`
Amount float64 `json:"amount"`
Method string `json:"method"`
Status string `json:"status"`
TransactionID string `json:"transaction_id"`
PaidAt time.Time `json:"paid_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// Inventory 库存信息
type Inventory struct {
ProductID string `json:"product_id"`
Available int `json:"available"`
Reserved int `json:"reserved"`
}
// BatchOrder 批量订单
type BatchOrder struct {
BatchID string `json:"batch_id"`
Orders []Order `json:"orders"`
Status string `json:"status"`
Processed int `json:"processed"`
Failed int `json:"failed"`
CreatedAt time.Time `json:"created_at"`
}5.3 订单工作流
go
// internal/workflow/order.go
package workflow
import (
"fmt"
"time"
"go.temporal.io/sdk/workflow"
"distributed-order/internal/types"
)
// OrderProcessingWorkflow 订单处理工作流
func OrderProcessingWorkflow(ctx workflow.Context, order types.Order) (string, error) {
logger := workflow.GetLogger(ctx)
logger.Info("开始处理订单", "orderID", order.ID, "amount", order.TotalAmount)
// 记录开始时间
startTime := workflow.Now(ctx)
// 活动选项
ao := workflow.ActivityOptions{
StartToCloseTimeout: 5 * time.Minute,
RetryPolicy: &temporal.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumAttempts: 3,
},
}
ctx = workflow.WithActivityOptions(ctx, ao)
// 步骤 1: 验证订单
logger.Info("验证订单")
if err := workflow.ExecuteActivity(ctx, ValidateOrderActivity, order).Get(ctx, nil); err != nil {
return handleFailure(ctx, order, "validation", err)
}
// 步骤 2: 预留库存(并行)
logger.Info("预留库存")
inventoryResults := make(map[string]bool)
for _, item := range order.Items {
future := workflow.ExecuteActivity(ctx, ReserveInventoryActivity, types.Inventory{
ProductID: item.ProductID,
Available: item.Quantity,
})
// 等待完成
var result types.Inventory
if err := future.Get(ctx, &result); err != nil {
return handleFailure(ctx, order, "inventory", err)
}
inventoryResults[item.ProductID] = result.Available >= 0
}
// 检查库存预留结果
for productID, success := range inventoryResults {
if !success {
// 释放已预留的库存
releaseReservedInventory(ctx, order.Items)
return handleFailure(ctx, order, "inventory", fmt.Errorf("商品 %s 库存不足", productID))
}
}
// 步骤 3: 处理支付
logger.Info("处理支付")
var payment types.Payment
err := workflow.ExecuteActivity(ctx, ProcessPaymentActivity, types.Payment{
OrderID: order.ID,
Amount: order.TotalAmount,
Method: "credit_card",
}).Get(ctx, &payment)
if err != nil || payment.Status != "success" {
// 释放库存
releaseReservedInventory(ctx, order.Items)
return handleFailure(ctx, order, "payment", err)
}
// 步骤 4: 发货
logger.Info("发货")
err = workflow.ExecuteActivity(ctx, ShipOrderActivity, order.ID).Get(ctx, nil)
if err != nil {
// 退款
workflow.ExecuteActivity(ctx, RefundPaymentActivity, payment.TransactionID)
// 释放库存
releaseReservedInventory(ctx, order.Items)
return handleFailure(ctx, order, "shipping", err)
}
// 步骤 5: 发送通知
logger.Info("发送通知")
workflow.ExecuteActivity(ctx, SendOrderNotificationActivity, types.Notification{
CustomerID: order.CustomerID,
Type: "order_completed",
OrderID: order.ID,
Message: "您的订单已发货",
}).Get(ctx, nil)
// 计算耗时
duration := workflow.Now(ctx).Sub(startTime)
logger.Info("订单处理完成",
"orderID", order.ID,
"duration", duration.String())
return "completed", nil
}
// handleFailure 处理失败
func handleFailure(ctx workflow.Context, order types.Order, stage string, err error) (string, error) {
logger := workflow.GetLogger(ctx)
logger.Error("订单处理失败",
"orderID", order.ID,
"stage", stage,
"error", err)
// 发送失败通知
workflow.ExecuteActivity(ctx, SendOrderNotificationActivity, types.Notification{
CustomerID: order.CustomerID,
Type: "order_failed",
OrderID: order.ID,
Message: fmt.Sprintf("订单处理失败: %s", err),
})
return "", fmt.Errorf("订单在 %s 阶段失败: %w", stage, err)
}
// releaseReservedInventory 释放预留库存
func releaseReservedInventory(ctx workflow.Context, items []types.OrderItem) {
for _, item := range items {
workflow.ExecuteActivity(ctx, ReleaseInventoryActivity, types.Inventory{
ProductID: item.ProductID,
Available: -item.Quantity,
})
}
}5.4 Saga 工作流
go
// internal/workflow/saga.go
package workflow
import (
"fmt"
"time"
"go.temporal.io/sdk/workflow"
"distributed-order/internal/types"
)
// OrderSagaWorkflow 订单 Saga 工作流
func OrderSagaWorkflow(ctx workflow.Context, order types.Order) (string, error) {
logger := workflow.GetLogger(ctx)
logger.Info("开始 Saga 订单处理", "orderID", order.ID)
// 定义补偿活动
compensations := []func(){}
// 活动选项
ao := workflow.ActivityOptions{
StartToCloseTimeout: 5 * time.Minute,
RetryPolicy: &temporal.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumAttempts: 3,
},
}
ctx = workflow.WithActivityOptions(ctx, ao)
// 步骤 1: 创建订单
logger.Info("创建订单")
var orderID string
err := workflow.ExecuteActivity(ctx, CreateOrderActivity, order).Get(ctx, &orderID)
if err != nil {
return "", err
}
order.ID = orderID
compensations = append(compensations, func() {
workflow.ExecuteActivity(ctx, CancelOrderActivity, orderID)
})
// 步骤 2: 预留库存
logger.Info("预留库存")
err = workflow.ExecuteActivity(ctx, ReserveInventoryBatchActivity, order.Items).Get(ctx, nil)
if err != nil {
executeCompensations(ctx, compensations)
return "", err
}
compensations = append(compensations, func() {
workflow.ExecuteActivity(ctx, ReleaseInventoryBatchActivity, order.Items)
})
// 步骤 3: 处理支付
logger.Info("处理支付")
var paymentID string
err = workflow.ExecuteActivity(ctx, ProcessPaymentActivity, types.Payment{
OrderID: orderID,
Amount: order.TotalAmount,
Method: "credit_card",
}).Get(ctx, &paymentID)
if err != nil {
executeCompensations(ctx, compensations)
return "", err
}
compensations = append(compensations, func() {
workflow.ExecuteActivity(ctx, RefundPaymentActivity, paymentID)
})
// 步骤 4: 发货
logger.Info("发货")
err = workflow.ExecuteActivity(ctx, ShipOrderActivity, orderID).Get(ctx, nil)
if err != nil {
executeCompensations(ctx, compensations)
return "", err
}
// 步骤 5: 发送通知
logger.Info("发送通知")
workflow.ExecuteActivity(ctx, SendOrderNotificationActivity, types.Notification{
CustomerID: order.CustomerID,
Type: "order_completed",
OrderID: orderID,
Message: "订单处理完成",
})
logger.Info("Saga 订单处理完成", "orderID", orderID)
return orderID, nil
}
// executeCompensations 执行补偿
func executeCompensations(ctx workflow.Context, compensations []func()) {
logger := workflow.GetLogger(ctx)
logger.Info("执行补偿")
// 逆向执行补偿
for i := len(compensations) - 1; i >= 0; i-- {
compensations[i]()
}
}5.5 批量处理工作流
go
// internal/workflow/batch.go
package workflow
import (
"fmt"
"time"
"go.temporal.io/sdk/workflow"
"distributed-order/internal/types"
)
// BatchOrderProcessingWorkflow 批量订单处理工作流
func BatchOrderProcessingWorkflow(ctx workflow.Context, batch types.BatchOrder) (*types.BatchOrder, error) {
logger := workflow.GetLogger(ctx)
logger.Info("开始批量订单处理", "batchID", batch.BatchID, "count", len(batch.Orders))
// 活动选项
ao := workflow.ActivityOptions{
StartToCloseTimeout: 30 * time.Minute,
RetryPolicy: &temporal.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumAttempts: 2,
},
}
ctx = workflow.WithActivityOptions(ctx, ao)
// 使用信号处理每个订单
orderChannel := workflow.NewSignalChannel(ctx, "order-channel")
resultChannel := workflow.NewChannel(ctx)
// 启动订单处理协程
workflow.Go(ctx, func(ctx workflow.Context) {
processed := 0
failed := 0
for _, order := range batch.Orders {
// 处理订单
var result string
err := workflow.ExecuteActivity(ctx, ProcessSingleOrderActivity, order).Get(ctx, &result)
if err != nil {
logger.Error("订单处理失败", "orderID", order.ID, "error", err)
failed++
} else {
processed++
}
// 发送进度更新
resultChannel.Send(ctx, BatchProgress{
Processed: processed,
Failed: failed,
Total: len(batch.Orders),
})
}
// 关闭结果通道
resultChannel.Close()
})
// 收集结果
processed := 0
failed := 0
for resultChannel.Receive(ctx, nil) {
// 可以在这里更新进度
processed++
if processed%10 == 0 {
logger.Info("批量处理进度", "processed", processed, "total", len(batch.Orders))
}
}
batch.Status = "completed"
batch.Processed = processed
batch.Failed = failed
logger.Info("批量订单处理完成",
"batchID", batch.BatchID,
"processed", processed,
"failed", failed)
return &batch, nil
}
// BatchProgress 批量进度
type BatchProgress struct {
Processed int
Failed int
Total int
}5.6 活动实现
go
// internal/activity/order.go
package activity
import (
"context"
"fmt"
"log"
"time"
"go.temporal.io/sdk/activity"
"distributed-order/internal/types"
)
// ValidateOrderActivity 验证订单活动
func ValidateOrderActivity(ctx context.Context, order types.Order) error {
logger := activity.GetLogger(ctx)
logger.Info("验证订单", "orderID", order.ID)
// 验证逻辑
if order.ID == "" {
return fmt.Errorf("订单ID不能为空")
}
if order.CustomerID == "" {
return fmt.Errorf("客户ID不能为空")
}
if len(order.Items) == 0 {
return fmt.Errorf("订单商品不能为空")
}
// 验证商品数量和价格
for _, item := range order.Items {
if item.Quantity <= 0 {
return fmt.Errorf("商品 %s 数量必须大于0", item.ProductID)
}
if item.Price <= 0 {
return fmt.Errorf("商品 %s 价格必须大于0", item.ProductID)
}
}
logger.Info("订单验证通过", "orderID", order.ID)
return nil
}
// CreateOrderActivity 创建订单活动
func CreateOrderActivity(ctx context.Context, order types.Order) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("创建订单", "orderID", order.ID)
// 模拟创建订单
time.Sleep(100 * time.Millisecond)
// 生成订单ID
orderID := fmt.Sprintf("ORD-%d", time.Now().UnixNano())
logger.Info("订单创建成功", "orderID", orderID)
return orderID, nil
}
// CancelOrderActivity 取消订单活动
func CancelOrderActivity(ctx context.Context, orderID string) error {
logger := activity.GetLogger(ctx)
logger.Info("取消订单", "orderID", orderID)
// 模拟取消订单
time.Sleep(50 * time.Millisecond)
return nil
}
// ProcessSingleOrderActivity 处理单个订单活动
func ProcessSingleOrderActivity(ctx context.Context, order types.Order) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("处理订单", "orderID", order.ID)
// 验证订单
if err := ValidateOrderActivity(ctx, order); err != nil {
return "", err
}
// 预留库存
for _, item := range order.Items {
_, err := ReserveInventoryActivity(ctx, types.Inventory{
ProductID: item.ProductID,
Available: item.Quantity,
})
if err != nil {
return "", err
}
}
// 处理支付
_, err := ProcessPaymentActivity(ctx, types.Payment{
OrderID: order.ID,
Amount: order.TotalAmount,
Method: "credit_card",
})
if err != nil {
return "", err
}
logger.Info("订单处理完成", "orderID", order.ID)
return "completed", nil
}go
// internal/activity/payment.go
package activity
import (
"context"
"fmt"
"log"
"time"
"go.temporal.io/sdk/activity"
"distributed-order/internal/types"
)
// ProcessPaymentActivity 处理支付活动
func ProcessPaymentActivity(ctx context.Context, payment types.Payment) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("处理支付", "orderID", payment.OrderID, "amount", payment.Amount)
// 模拟支付处理
time.Sleep(200 * time.Millisecond)
// 生成支付ID
paymentID := fmt.Sprintf("PAY-%d", time.Now().UnixNano())
logger.Info("支付处理成功", "paymentID", paymentID)
return paymentID, nil
}
// RefundPaymentActivity 退款活动
func RefundPaymentActivity(ctx context.Context, paymentID string) error {
logger := activity.GetLogger(ctx)
logger.Info("退款", "paymentID", paymentID)
// 模拟退款
time.Sleep(150 * time.Millisecond)
logger.Info("退款成功", "paymentID", paymentID)
return nil
}go
// internal/activity/inventory.go
package activity
import (
"context"
"fmt"
"log"
"time"
"go.temporal.io/sdk/activity"
"distributed-order/internal/types"
)
// ReserveInventoryActivity 预留库存活动
func ReserveInventoryActivity(ctx context.Context, inv types.Inventory) (*types.Inventory, error) {
logger := activity.GetLogger(ctx)
logger.Info("预留库存", "productID", inv.ProductID, "quantity", inv.Available)
// 模拟库存预留
time.Sleep(100 * time.Millisecond)
// 假设库存充足
result := &types.Inventory{
ProductID: inv.ProductID,
Available: 100 - inv.Available,
Reserved: inv.Available,
}
logger.Info("库存预留成功", "productID", inv.ProductID)
return result, nil
}
// ReleaseInventoryActivity 释放库存活动
func ReleaseInventoryActivity(ctx context.Context, inv types.Inventory) error {
logger := activity.GetLogger(ctx)
logger.Info("释放库存", "productID", inv.ProductID, "quantity", inv.Available)
// 模拟释放库存
time.Sleep(50 * time.Millisecond)
return nil
}
// ReserveInventoryBatchActivity 批量预留库存活动
func ReserveInventoryBatchActivity(ctx context.Context, items []types.OrderItem) error {
logger := activity.GetLogger(ctx)
logger.Info("批量预留库存", "count", len(items))
for _, item := range items {
_, err := ReserveInventoryActivity(ctx, types.Inventory{
ProductID: item.ProductID,
Available: item.Quantity,
})
if err != nil {
return err
}
}
logger.Info("批量预留库存完成")
return nil
}
// ReleaseInventoryBatchActivity 批量释放库存活动
func ReleaseInventoryBatchActivity(ctx context.Context, items []types.OrderItem) error {
logger := activity.GetLogger(ctx)
logger.Info("批量释放库存", "count", len(items))
for _, item := range items {
ReleaseInventoryActivity(ctx, types.Inventory{
ProductID: item.ProductID,
Available: -item.Quantity,
})
}
return nil
}go
// internal/activity/notification.go
package activity
import (
"context"
"fmt"
"log"
"go.temporal.io/sdk/activity"
"distributed-order/internal/types"
)
// Notification 通知
type Notification struct {
CustomerID string
Type string
OrderID string
Message string
}
// SendOrderNotificationActivity 发送订单通知活动
func SendOrderNotificationActivity(ctx context.Context, notif Notification) error {
logger := activity.GetLogger(ctx)
logger.Info("发送通知", "customerID", notif.CustomerID, "type", notif.Type)
// 模拟发送通知
// 实际应调用邮件/短信服务
fmt.Printf("通知: 客户 %s, 类型 %s, 消息 %s\n",
notif.CustomerID, notif.Type, notif.Message)
logger.Info("通知发送成功", "customerID", notif.CustomerID)
return nil
}5.7 客户端封装
go
// internal/client/client.go
package client
import (
"context"
"fmt"
"time"
"go.temporal.io/sdk/client"
"distributed-order/internal/types"
)
// OrderClient 订单客户端
type OrderClient struct {
c client.Client
}
// NewOrderClient 创建订单客户端
func NewOrderClient(opts client.Options) (*OrderClient, error) {
c, err := client.Dial(opts)
if err != nil {
return nil, err
}
return &OrderClient{c: c}, nil
}
// CreateOrder 创建订单
func (oc *OrderClient) CreateOrder(ctx context.Context, order types.Order) (string, error) {
workflowID := fmt.Sprintf("order-%s", order.ID)
we, err := oc.c.ExecuteWorkflow(
ctx,
client.StartWorkflowOptions{
ID: workflowID,
TaskQueue: "order-task-queue",
},
workflow.OrderProcessingWorkflow,
order,
)
if err != nil {
return "", err
}
return we.GetID(), nil
}
// CreateOrderWithSaga 使用 Saga 创建订单
func (oc *OrderClient) CreateOrderWithSaga(ctx context.Context, order types.Order) (string, error) {
workflowID := fmt.Sprintf("saga-%s", order.ID)
we, err := oc.c.ExecuteWorkflow(
ctx,
client.StartWorkflowOptions{
ID: workflowID,
TaskQueue: "order-task-queue",
},
workflow.OrderSagaWorkflow,
order,
)
if err != nil {
return "", err
}
return we.GetID(), nil
}
// ProcessBatch 批量处理订单
func (oc *OrderClient) ProcessBatch(ctx context.Context, orders []types.Order) (string, error) {
batch := types.BatchOrder{
BatchID: fmt.Sprintf("batch-%d", time.Now().Unix()),
Orders: orders,
Status: "processing",
CreatedAt: time.Now(),
}
we, err := oc.c.ExecuteWorkflow(
ctx,
client.StartWorkflowOptions{
ID: batch.BatchID,
TaskQueue: "batch-task-queue",
},
workflow.BatchOrderProcessingWorkflow,
batch,
)
if err != nil {
return "", err
}
return we.GetID(), nil
}
// GetOrderStatus 获取订单状态
func (oc *OrderClient) GetOrderStatus(ctx context.Context, workflowID string) (string, error) {
we := oc.c.GetWorkflow(ctx, workflowID, "")
var result string
err := we.Get(ctx, &result)
if err != nil {
return "", err
}
return result, nil
}
// CancelOrder 取消订单
func (oc *OrderClient) CancelOrder(ctx context.Context, workflowID string) error {
return oc.c.CancelWorkflow(ctx, workflowID, "")
}
// SignalOrder 发送信号
func (oc *OrderClient) SignalOrder(ctx context.Context, workflowID, signalName string, data interface{}) error {
return oc.c.SignalWorkflow(ctx, workflowID "", signalName, data)
}
// Close 关闭客户端
func (oc *OrderClient) Close() error {
return oc.c.Close()
}5.8 Worker 配置
go
// cmd/worker/main.go
package main
import (
"log"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
"distributed-order/internal/activity"
"distributed-order/internal/workflow"
)
func main() {
// 创建客户端
c, err := client.Dial(client.Options{
HostPort: "localhost:7233",
})
if err != nil {
log.Fatalln("无法创建客户端", err)
}
defer c.Close()
// 创建订单 Worker
orderWorker := worker.New(c, "order-task-queue", worker.Options{
MaxConcurrentWorkflowTaskExecutionSize: 100,
MaxConcurrentActivityExecutionSize: 50,
})
orderWorker.RegisterWorkflow(workflow.OrderProcessingWorkflow)
orderWorker.RegisterWorkflow(workflow.OrderSagaWorkflow)
// 注册订单活动
orderWorker.RegisterActivity(activity.ValidateOrderActivity)
orderWorker.RegisterActivity(activity.CreateOrderActivity)
orderWorker.RegisterActivity(activity.CancelOrderActivity)
orderWorker.RegisterActivity(activity.ProcessSingleOrderActivity)
orderWorker.RegisterActivity(activity.ProcessPaymentActivity)
orderWorker.RegisterActivity(activity.RefundPaymentActivity)
orderWorker.RegisterActivity(activity.ReserveInventoryActivity)
orderWorker.RegisterActivity(activity.ReleaseInventoryActivity)
orderWorker.RegisterActivity(activity.ReserveInventoryBatchActivity)
orderWorker.RegisterActivity(activity.ReleaseInventoryBatchActivity)
orderWorker.RegisterActivity(activity.ShipOrderActivity)
orderWorker.RegisterActivity(activity.SendOrderNotificationActivity)
// 创建批量处理 Worker
batchWorker := worker.New(c, "batch-task-queue", worker.Options{
MaxConcurrentWorkflowTaskExecutionSize: 10,
MaxConcurrentActivityExecutionSize: 20,
})
batchWorker.RegisterWorkflow(workflow.BatchOrderProcessingWorkflow)
// 启动 Workers
log.Println("启动 Workers...")
if err := orderWorker.Start(); err != nil {
log.Fatalln("无法启动订单 Worker", err)
}
if err := batchWorker.Start(); err != nil {
log.Fatalln("无法启动批量 Worker", err)
}
log.Println("Workers 已启动")
select {}
}5.9 运行项目
启动服务
bash
# 启动 Temporal
temporal server start-dev
# 启动 Worker
go run cmd/worker/main.go启动客户端
go
// cmd/starter/main.go
package main
import (
"context"
"log"
"time"
"distributed-order/internal/client"
"distributed-order/internal/types"
)
func main() {
// 创建客户端
oc, err := client.NewOrderClient(client.Options{
HostPort: "localhost:7233",
})
if err != nil {
log.Fatalln("无法创建客户端", err)
}
defer oc.Close()
// 创建订单
order := types.Order{
ID: "ORD-001",
CustomerID: "CUST-001",
TotalAmount: 299.99,
Items: []types.OrderItem{
{ProductID: "PROD-001", ProductName: "商品1", Quantity: 2, Price: 99.99},
{ProductID: "PROD-002", ProductName: "商品2", Quantity: 1, Price: 100.00},
},
CreatedAt: time.Now(),
}
// 启动工作流
workflowID, err := oc.CreateOrder(context.Background(), order)
if err != nil {
log.Fatalln("无法启动工作流", err)
}
log.Printf("工作流已启动: %s", workflowID)
}5.10 扩展练习
- 添加支付回调:实现异步支付回调处理
- 添加订单查询:实现订单状态查询功能
- 添加定时任务:实现定时清理过期订单
- 添加监控告警:集成 Prometheus 监控
- 添加分布式追踪:集成 OpenTelemetry