Files
go-trustlog/api/adapter/TCP_QUICK_START.md
ryan d313449c5c refactor: 重构trustlog-sdk目录结构到trustlog/go-trustlog
- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录
- 更新README中所有import路径从trustlog-sdk改为go-trustlog
- 更新cookiecutter配置文件中的项目名称
- 更新根目录.lefthook.yml以引用新位置的配置
- 添加go.sum文件到版本控制
- 删除过时的示例文件

这次重构与trustlog-server保持一致的目录结构,
为未来支持多语言SDK(Python、Java等)预留空间。
2025-12-22 13:37:57 +08:00

4.5 KiB
Raw Blame History

TCP 适配器快速开始指南

简介

TCP 适配器提供了一个无需 Pulsar 的 Watermill 消息发布/订阅实现,适用于内网直连场景。

快速开始

1. 启动消费端Subscriber

消费端作为 TCP 服务器,监听指定端口。

package main

import (
    "context"
    "log"
    
    "go.yandata.net/iod/iod/trustlog-sdk/api/adapter"
    "go.yandata.net/iod/iod/trustlog-sdk/api/logger"
)

func main() {
    // 使用 NopLogger 或自定义 logger
    log := logger.NewNopLogger()
    
    // 创建 Subscriber
    config := adapter.TCPSubscriberConfig{
        ListenAddr: "127.0.0.1:9090",
    }
    
    subscriber, err := adapter.NewTCPSubscriber(config, log)
    if err != nil {
        log.Fatal(err)
    }
    defer subscriber.Close()
    
    // 订阅 topic
    messages, err := subscriber.Subscribe(context.Background(), "my-topic")
    if err != nil {
        log.Fatal(err)
    }
    
    // 处理消息
    for msg := range messages {
        log.Println("收到消息:", string(msg.Payload))
        msg.Ack() // 确认消息
    }
}

2. 启动生产端Publisher

生产端作为 TCP 客户端,连接到消费端。

package main

import (
    "time"
    
    "github.com/ThreeDotsLabs/watermill/message"
    "go.yandata.net/iod/iod/trustlog-sdk/api/adapter"
    "go.yandata.net/iod/iod/trustlog-sdk/api/logger"
)

func main() {
    log := logger.NewNopLogger()
    
    // 创建 Publisher
    config := adapter.TCPPublisherConfig{
        ServerAddr:     "127.0.0.1:9090",
        ConnectTimeout: 5 * time.Second,
        AckTimeout:     10 * time.Second,
    }
    
    publisher, err := adapter.NewTCPPublisher(config, log)
    if err != nil {
        log.Fatal(err)
    }
    defer publisher.Close()
    
    // 发送消息
    msg := message.NewMessage("msg-001", []byte("Hello, World!"))
    
    err = publisher.Publish("my-topic", msg)
    if err != nil {
        log.Fatal(err)
    }
    
    log.Println("消息发送成功")
}

特性演示

并发发送多条消息

// 准备 10 条消息
messages := make([]*message.Message, 10)
for i := 0; i < 10; i++ {
    payload := []byte(fmt.Sprintf("Message #%d", i))
    messages[i] = message.NewMessage(fmt.Sprintf("msg-%d", i), payload)
}

// 并发发送Publisher 会等待所有 ACK
err := publisher.Publish("my-topic", messages...)
if err != nil {
    log.Fatal(err)
}

log.Println("所有消息发送成功")

错误处理和 NACK

// 在消费端
for msg := range messages {
    // 处理消息
    if err := processMessage(msg); err != nil {
        log.Println("处理失败:", err)
        msg.Nack() // 拒绝消息
        continue
    }
    msg.Ack() // 确认消息
}

配置参数

TCPPublisherConfig

type TCPPublisherConfig struct {
    ServerAddr     string        // 必填: TCP 服务器地址,如 "127.0.0.1:9090"
    ConnectTimeout time.Duration // 连接超时,默认 10s
    AckTimeout     time.Duration // ACK 超时,默认 30s
    MaxRetries     int           // 最大重试次数,默认 3
}

TCPSubscriberConfig

type TCPSubscriberConfig struct {
    ListenAddr string // 必填: 监听地址,如 "127.0.0.1:9090"
}

运行示例

# 运行完整示例
cd trustlog-sdk/examples
go run tcp_example.go

性能特点

  • 低延迟: 直接 TCP 连接,无中间件开销
  • 高并发: 支持并发发送多条消息
  • 可靠性: 每条消息都需要 ACK 确认
  • ⚠️ 无持久化: 消息仅在内存中传递

适用场景

适合:

  • 内网服务间直接通信
  • 开发和测试环境
  • 无需消息持久化的场景
  • 低延迟要求的场景

不适合:

  • 需要消息持久化
  • 需要高可用和故障恢复
  • 公网通信(需要加密)
  • 需要复杂的路由和负载均衡

常见问题

Q: 如何处理连接断开?

A: 当前版本连接断开后需要重新创建 Publisher。未来版本将支持自动重连。

Q: 消息会丢失吗?

A: TCP 适配器不提供持久化,连接断开或服务重启会导致未确认的消息丢失。

Q: 如何实现多个消费者?

A: 当前版本将消息发送到第一个订阅者。如需负载均衡,需要在应用层实现。

Q: 支持 TLS 加密吗?

A: 当前版本不支持 TLS。未来版本将添加 TLS/mTLS 支持。

下一步