You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于SMPP 3.4的批量SMS平台:go-smpp包发送千条后超时问题求助

解决go-smpp批量发送SMS超时问题的方案

1. 优化连接管理

  • 改用连接池:单连接并发提交请求容易触发SMPP服务器限流或窗口耗尽,初始化多个Transceiver会话组成连接池,轮询使用不同连接提交请求,分散负载。
  • 自动重连机制:监听会话的错误事件,当检测到超时、连接断开等异常时,销毁旧连接并重新建立会话,避免进程直接终止。

2. 控制发送流量

  • 限制发送速率:不要一次性提交全部1000条短信,根据服务商要求设置速率(通常10-50条/秒),用令牌桶或time.Tick控制发送节奏,避免服务器过载。
  • 调整SMPP窗口大小:初始化会话时通过smpp.WindowSize(N)配置未响应请求的最大数量(N值需符合服务商限制),避免因窗口占满导致后续请求超时。

3. 调整超时配置

  • 延长请求超时:初始化Transceiver时设置更长的smpp.Timeout(10*time.Second),适配批量发送时的服务器响应延迟。
  • 优化心跳间隔:通过smpp.EnquireLinkInterval(30*time.Second)调整EnquireLink发送频率,保持会话活跃,避免被服务器判定为空闲断开。

4. 实现错误重试与异步处理

  • 请求重试逻辑:针对超时的SubmitSM请求,加入重试队列,采用指数退避策略重试3-5次,同时为每条短信添加唯一ID避免重复发送。
  • 异步响应处理:不要同步等待单条短信响应再发下一条,异步提交请求并监听SubmitSMResp通道批量处理响应,避免阻塞发送流程。

5. 会话健康检查

  • 定期心跳检测:定时发送EnquireLink请求,若连续多次无响应立即触发重连。
  • 监控连接状态:记录每个会话的请求成功率、响应时间,当超时率超过阈值时,切换到连接池中的其他可用会话。

代码示例片段

// 初始化连接池
func NewConnPool(size int, addr, user, pass string) ([]*smpp.Transceiver, error) {
    pool := make([]*smpp.Transceiver, 0, size)
    for i := 0; i < size; i++ {
        tc, err := smpp.NewTransceiver(addr, user, pass,
            smpp.Timeout(10*time.Second),
            smpp.EnquireLinkInterval(30*time.Second),
            smpp.WindowSize(50),
        )
        if err != nil {
            return nil, err
        }
        pool = append(pool, tc)
    }
    return pool, nil
}

// 带速率控制的批量发送
func BatchSend(pool []*smpp.Transceiver, messages []string, rate int) {
    ticker := time.NewTicker(time.Duration(1000/rate) * time.Millisecond)
    defer ticker.Stop()
    idx := 0
    for range ticker.C {
        if idx >= len(messages) {
            break
        }
        tc := pool[idx%len(pool)]
        msg := messages[idx]
        go func(t *smpp.Transceiver, m string) {
            pdu := smpp.NewSubmitSM()
            pdu.SourceAddr = "YOUR_SHORT_CODE"
            pdu.DestAddr = "RECIPIENT_NUMBER"
            pdu.ShortMessage = []byte(m)
            resp, err := t.Submit(pdu)
            if err != nil {
                log.Printf("Submit failed: %v, message: %s", err, m)
                // 此处可加入重试队列逻辑
                return
            }
            log.Printf("Message sent, msgid: %s", resp.MessageID)
        }(tc, msg)
        idx++
    }
}

内容的提问来源于stack exchange,提问作者jucan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:15:36