rocketMQ5.0顺序消息golang接入

本人理解,顺序消息如果不分消息组,那么会影响并行处理速度,所以尽量消息组分的散一些
首先上要求,官方文档如下:
在这里插入图片描述
总结:
1.必须同一个消息组,消息组和消费组不是一个概念,不要混
2.必须单一生产者,也就是说线上生产只能开一个 pod,感觉局限有点高,无法多 pod 接入
3.必须串行发送,这个点也不太好,限制过高
以上三点
在我的案例中(企业微信回调消息)
那么只能开一个接口服务Pod 来接收微信回调,如果挂了,那完蛋,开多个 pod的话,那只有把请求放队列,通过队列pop进行消费再生产消息到 mq,这样同时也解决了第三点的串行发送。

生产的时候如何确定是顺序消息,只需要生产消息的时候给设定一个消息组

msg := &rmq_client.Message{
Topic: Topic,
	Body:  []byte("this is a message : " + strconv.Itoa(i)),
}
// set keys and tag
msg.SetKeys("a", "b")
msg.SetTag("ab")
// 这里设置消息组
msg.SetMessageGroup("fifo")

分组分的越细越好

提高消费速度

当拿到消息后,根据消息分组来进行并发处理,每个分组内进行串行处理,关键代码如下


func (m *RocketMq) ConsumerOrderly(funcMap map[string]func([]byte) error) {
	var err error

	m.consumerOnce.Do(func() {
		Log().Info("##############pro consume orderly start#############", m.MqConfig)
		errTmp := m.proSimConsumer.Start()
		if errTmp != nil {
			Log().Panic("MQ启动失败", errTmp)
			return
		}
	})
	defer m.proSimConsumer.GracefulStop()
	// 总体保证有N个在运行
	var ch = make(chan int, m.MaxGoroutine)
	for {
		fmt.Println("start receive message")
		mvs, errReceive := m.proSimConsumer.Receive(context.TODO(), 8, 20*time.Second)
		if errReceive != nil {
			if strings.Contains(errReceive.Error(), "no new message") {
				Log().Info(errReceive)
			} else {
				Log().Error("顺序消息,拉取MQ消息失败:", errReceive)
			}
			time.Sleep(time.Second * 2)
			continue
		}
	
		var msgGroupMap = make(map[string][]*rmq_client.MessageView, 0)
		for _, v := range mvs {
			if _, ok := funcMap[*v.GetTag()]; !ok {
				Log().Error(v.GetTag(), ": action do not exist")
				continue
			} else {
				// 根据msgGroup汇总
				msgGroup := v.GetMessageGroup()
				msgGroupMap[*msgGroup] = append(msgGroupMap[*msgGroup], v)
			}
		}
		// 最大程度多线程消费
		for _, item := range msgGroupMap {
			ch <- 1
			go func(item []*rmq_client.MessageView) {
				for _, v := range item {
					fmt.Println(*v.GetTag(), *v.GetMessageGroup(), string(v.GetBody()))
					action, _ := funcMap[*v.GetTag()]
					if errTmp := action(v.GetBody()); errTmp != nil {
						Log().Error("mq顺序消费失败", errTmp)
						break
					} else {
						m.proSimConsumer.Ack(context.TODO(), v)
					}
				}
				<-ch
			}(item)
		}
	}
}

最后需要注意的点:

同一个消费者 Group ID 下所有的 Consumer 实例必须保证订阅的 Topic 一致,并且也必须保证订阅 Topic 时设置的过滤规则(Tag)一致。否则您的消息可能会丢失
请保证订阅一致性
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将Golang接入ChatGPT,您可以使用AI的GPT-3 API来实现。以下是一些步骤和示例代码***一步骤。 2. 在Golang中,您可以使用HTTP请求库来与GPT-3 API进行通信。一个常用的库是`net/http`。 3. 在您的代码中,您需要构建一个HTTP POST请求,将您的输入文本发送给GPT-3 API,并接收返回的响应。 下面是一个简单的示例代码,演示如何使用Golang发送请求并接收响应: ```go package main import ( "fmt" "io/ioutil" "net/http" "strings" ) func main() { apiKey := "YOUR_API_KEY" url := "https://api.openai.com/v1/engines/davinci-codex/completions" input := "你想要问的问题" payload := strings.NewReader(fmt.Sprintf(`{ "prompt": "%s", "max_tokens": 50 }`, input)) req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiKey)) res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) fmt.Println(string(body)) } ``` 请确保将`YOUR_API_KEY`替换为您在OpenAI网站上获取的API密钥。 4. 在上述代码中,我们使用了`davinci-codex`引擎,您可以根据您需求选择其他引擎。`max_tokens`参数用于指定生成的响应的最大长度。 5. 运行代码后,您将收到来自GPT-3 API的响应,其中包含生成的文本。 这是一个简单的示例,您可以根据自己的需求进行修改和扩展。请确保遵循OpenAI的使用政策和指导方针。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值