需求背景

因为 Go-Cannal 经常挂掉,导致 MySQL binlog 同步到 ES 的链路故障。所以改用了另外一种同步方案。用某云的 DTS 消费 MySQL 的 binlong,用 DTS 的 Java 客户端消费 kafka 协议的消息,得到 MySQL 的变更。Java 再将变更 Push 到 RocketMQ。改造原有的 Go 代码,消费 RocketMQ 消息,完成业务逻辑( 复用之前的逻辑代码,减小开发量 )。

新方案采用 MQ 持久化避免消费者 panic 导致数据丢失,同时消费者可以分布式处理消息提高吞吐率。

问题

Go-SDK 的官方文档 : https://help.aliyun.com/document_detail/141783.html?spm=5176....

坑一,RocketMQ 的服务不能用 apache RocketMQ 的 Go client。必须使用官方的 sdk,且官方 sdk 只有 http 协议版本。

坑二,官方的 SDK 中的 token 字段并无用处,可以为空或者任意字符

坑三,官方的 SDK 中 GetConsumer(InstanceID, Topic, Consumer, "*") 第三个参数其实是 TopicName ,或者必须写成 TopicName 一样的值。

坑四,官方的 SDK 调用之前必须配置好 Group,且 Group 必须是 HTTP 的。

示例代码

一个可以跑通的代码 demo 如下:


package main

import (
    "context"
    "fmt"
    "os"
    "rocketmq-demo/mq_http_sdk"
    "time"
)

var (
    AccessKey    = "RAM帐号的key"
    AccessSecret = "RAM帐号的Secret"
    Endpoint     = "必须是http协议的endpoint"
    Topic        = "topicName"
    GroupID      = "必须是http协议的group且事先授权"
    Token        = "任意值"
    InstanceID   = "从web控制台复制"
)

func main() {
    //client := client
    cli := mq_http_sdk.NewAliyunMQClientWithTimeout(Endpoint, AccessKey, AccessSecret, Token, time.Second*5)
    consumer := cli.GetConsumer(InstanceID, Topic, Topic, "*")
    var responseChan = make(chan mq_http_sdk.ConsumeMessageResponse, 1)
    var errChan = make(chan error, 1)
    func(responseChan chan mq_http_sdk.ConsumeMessageResponse, errChan chan error) {
        consumer.ConsumeMessage(responseChan, errChan, 10, 30)
    }(responseChan, errChan)
    go func() {
        for {
            select {
            case response := <-responseChan:
                fmt.Println("Receive Message: ", response.Messages)
                // 消费成功
                err := consumer.AckMessage([]string{"OK"})
                if err != nil {
                    fmt.Println("Ack Error: ", err)
                }
            case err := <-errChan:
                fmt.Println("Error: ", err)
            }
        }
    }()
    time.Sleep(10 * time.Second)
}

Airy
2.4k 声望69 粉丝

github.com/airylinus