在篇章(三)中,由于我的废话实在是太多,鉴于此,这章索性我就直接把example code粘贴出来。talk is cheap,show me the code。
async
consumer
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"log"
"os"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "containerExpireDelayTopic"
//Endpoint = "10.101.26.151:8080"
Endpoint = "127.0.0.1:8080"
AccessKey = ""
SecretKey = ""
ConsumerGroup = "ContainerExpireInformGroup"
Tag = "containerExpireInform"
)
var (
// maximum waiting time for receive func
awaitDuration = time.Second * 5
// maximum number of messages received at one time
maxMessageNum int32 = 16
// invisibleDuration should > 20s,Message retry interval = InvisibleDuration value − Actual duration of message processing
invisibleDuration = time.Second * 20
)
type ContainerExpireRequest struct {
ContainerId string `json:"containerId" form:"containerId"` // 容器ID
EndTime time.Time `json:"endTime" form:"endTime"` // 到期时间
}
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new simpleConsumer instance
simpleConsumer, err := golang.NewSimpleConsumer(&golang.Config{
Endpoint: Endpoint,
ConsumerGroup: ConsumerGroup,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithAwaitDuration(awaitDuration),
golang.WithSubscriptionExpressions(map[string]*golang.FilterExpression{
Topic: golang.NewFilterExpression(Tag),
}),
)
if err != nil {
log.Fatal(err)
}
// start simpleConsumer
err = simpleConsumer.Start()
if err != nil {
log.Fatal(err)
}
// graceful stop simpleConsumer
defer simpleConsumer.GracefulStop()
go func() {
for {
fmt.Println("start receive message...")
mvs, err := simpleConsumer.Receive(context.TODO(), maxMessageNum, invisibleDuration)
var rpcStatus *golang.ErrRpcStatus
if ok := errors.As(err, &rpcStatus); ok {
if rpcStatus.GetCode() != 40401 && rpcStatus.GetMessage() != "no new message" {
fmt.Printf("Failed to receive message for group %s: %v\n", simpleConsumer.GetGroupName(), err)
}
}
for _, mv := range mvs {
// 模拟处理失败
if err = dealMes(); err != nil {
fmt.Println("消费失败...")
if mv.GetDeliveryAttempt() > 3 {
fmt.Println("delivery time :", mv.GetDeliveryAttempt())
//ack message,consumer retry times: default 16
simpleConsumer.Ack(context.TODO(), mv)
message := &ContainerExpireRequest{}
err = json.Unmarshal(mv.GetBody(), message)
if err != nil {
fmt.Printf("containerExpireInform unmarshal message err:%v,tag:%v\n", err, mv.GetTag())
continue
}
if mv.GetDeliveryAttempt() > 3 {
fmt.Printf("containerExpireInform consume message max attempts is greater than 3,messageId:%v\n", mv.GetMessageId())
// ack message
simpleConsumer.Ack(context.TODO(), mv)
// TODO: exec rollback logic
continue
}
simpleConsumer.Ack(context.TODO(), mv)
}
}
}
}
}()
select {}
}
func dealMes() error {
return errors.New("deal message error")
}
producer
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
"log"
"os"
"time"
)
const (
Topic = "containerExpireDelayTopic"
//Endpoint = "10.101.26.151:8080"
Endpoint = "10.101.26.151:8080"
AccessKey = ""
SecretKey = ""
Tag = "containerExpireInform"
)
type ContainerExpireRequest struct {
ContainerId string `json:"containerId" form:"containerId"` // 容器ID
EndTime time.Time `json:"endTime" form:"endTime"` // 到期时间
}
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new producer instance
producer, err := golang.NewProducer(&golang.Config{
Endpoint: Endpoint,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithTopics(Topic),
golang.WithMaxAttempts(3), // set max attempts,default is 3
)
if err != nil {
log.Fatal(err)
}
// start producer
err = producer.Start()
if err != nil {
log.Fatal(err)
}
shanghaiLoc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
// gracefule stop producer
defer producer.GracefulStop()
message := ContainerExpireRequest{
ContainerId: "test-containerId-测试",
EndTime: time.Now().In(shanghaiLoc).Add(time.Second * 5),
}
jsonData, err := json.Marshal(message)
if err != nil {
return
}
msg := &golang.Message{
Topic: Topic,
Body: []byte(jsonData),
}
// set keys and tag
msg.SetKeys("test-key")
msg.SetTag(Tag)
// set delay timestamp
msg.SetDelayTimestamp(time.Now().In(shanghaiLoc).Add(time.Second * 5))
// send message in async
resp, err := producer.Send(context.TODO(), msg)
if err != nil {
log.Fatal(err)
}
for i := 0; i < len(resp); i++ {
fmt.Printf("%#v\n", resp[i])
}
select {}
}
delay
consumer
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "DelayTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = "xxxxxx"
SecretKey = "xxxxxx"
)
var (
// maximum waiting time for receive func
awaitDuration = time.Second * 5
// maximum number of messages received at one time
maxMessageNum int32 = 16
// invisibleDuration should > 20s,Message retry interval = InvisibleDuration value − Actual duration of message processing
invisibleDuration = time.Second * 20
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new simpleConsumer instance
simpleConsumer, err := golang.NewSimpleConsumer(&golang.Config{
Endpoint: Endpoint,
ConsumerGroup: "test-async-group",
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithAwaitDuration(awaitDuration),
golang.WithSubscriptionExpressions(map[string]*golang.FilterExpression{
Topic: golang.SUB_ALL,
}),
)
if err != nil {
log.Fatal(err)
}
// start simpleConsumer
err = simpleConsumer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop simpleConsumer
defer simpleConsumer.GracefulStop()
shanghaiLoc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
go func() {
for {
fmt.Println("start recevie message")
mvs, err := simpleConsumer.Receive(context.TODO(), maxMessageNum, invisibleDuration)
if err != nil {
fmt.Println(err)
}
// ack message
for _, mv := range mvs {
simpleConsumer.Ack(context.TODO(), mv) // consumer retry times: default 16
fmt.Printf("message:%v send time:%v receive time:%v\n", string(mv.GetBody()), mv.GetBornTimestamp().In(shanghaiLoc).Format("2006-01-02 15:04:05"), time.Now().In(shanghaiLoc).Format("2006-01-02 15:04:05"))
}
fmt.Println("wait a moment")
}
}()
// run for a while
select {}
}
producer
package main
import (
"context"
"fmt"
"log"
"os"
"strconv"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "DelayTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = "xxxxxx"
SecretKey = "xxxxxx"
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new producer instance
producer, err := golang.NewProducer(&golang.Config{
Endpoint: Endpoint,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithTopics(Topic),
)
if err != nil {
log.Fatal(err)
}
// start producer
err = producer.Start()
if err != nil {
log.Fatal(err)
}
shanghaiLoc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
// gracefule stop producer
defer producer.GracefulStop()
for i := 0; i < 3; i++ {
// new a message
msg := &golang.Message{
Topic: Topic,
Body: []byte("this is a message : " + strconv.Itoa(i)),
}
// set keys and tag
msg.SetKeys("delay")
msg.SetTag("ab")
// set delay timestamp
msg.SetDelayTimestamp(time.Now().In(shanghaiLoc).Add(time.Second * 10))
// send message in sync
resp, err := producer.Send(context.TODO(), msg)
if err != nil {
log.Fatal(err)
}
for i := 0; i < len(resp); i++ {
fmt.Printf("%#v\n", resp[i])
}
}
}
// sh mqadmin updateTopic -c DefaultCluster -t DelayTopic -n rmqnamesrv:9876 -a +message.type=DELAY
fifo
consumer
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "FIFOTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = ""
SecretKey = ""
)
var (
// maximum waiting time for receive func
awaitDuration = time.Second * 5
// maximum number of messages received at one time
maxMessageNum int32 = 16
// invisibleDuration should > 20s,Message retry interval = InvisibleDuration value − Actual duration of message processing
invisibleDuration = time.Second * 20
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new simpleConsumer instance
simpleConsumer, err := golang.NewSimpleConsumer(&golang.Config{
Endpoint: Endpoint,
ConsumerGroup: "test-fifo-group",
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithAwaitDuration(awaitDuration),
golang.WithSubscriptionExpressions(map[string]*golang.FilterExpression{
Topic: golang.SUB_ALL,
}),
)
if err != nil {
log.Fatal(err)
}
// start simpleConsumer
err = simpleConsumer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop simpleConsumer
defer simpleConsumer.GracefulStop()
shanghaiLoc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
go func() {
for {
fmt.Println("start recevie message")
mvs, err := simpleConsumer.Receive(context.TODO(), maxMessageNum, invisibleDuration)
if err != nil {
fmt.Println(err)
}
// ack message
for _, mv := range mvs {
simpleConsumer.Ack(context.TODO(), mv) // consumer retry times: default 16
fmt.Printf("message:%v send time:%v receive time:%v\n", string(mv.GetBody()), mv.GetBornTimestamp().In(shanghaiLoc).Format("2006-01-02 15:04:05"), time.Now().In(shanghaiLoc).Format("2006-01-02 15:04:05"))
}
fmt.Println("wait a moment")
}
}()
// run for a while
select {}
}
// sh mqadmin updateSubGroup -c DefaultCluster -g orderconsumergroup -n rmqnamesrv:9876 -o true
producer
package main
import (
"context"
"fmt"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
"log"
"os"
"strconv"
)
const (
Topic = "FIFOTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = ""
SecretKey = ""
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new producer instance
producer, err := golang.NewProducer(&golang.Config{
Endpoint: Endpoint,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithTopics(Topic),
)
if err != nil {
log.Fatal(err)
}
// start producer
err = producer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop producer
defer producer.GracefulStop()
for i := 0; i < 100; i++ {
// new a message
msg := &golang.Message{
Topic: Topic,
Body: []byte("message: " + strconv.Itoa(i)),
}
// set keys and tag
msg.SetKeys("fifo")
msg.SetTag("ab")
msg.SetMessageGroup("fifo") // set message group
// send message in sync
resp, err := producer.Send(context.TODO(), msg)
if err != nil {
log.Fatal(err)
}
for i := 0; i < len(resp); i++ {
fmt.Printf("%#v\n", resp[i])
}
}
}
// sh mqadmin updateTopic -c DefaultCluster -t FIFOTopic -n rmqnamesrv:9876 -a +message.type=FIFO
normal
consumer
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "test-normal-topic"
Endpoint = "127.0.0.1:8080"
AccessKey = ""
SecretKey = ""
)
var (
// maximum waiting time for receive func
awaitDuration = time.Second * 5
// maximum number of messages received at one time
maxMessageNum int32 = 16
// invisibleDuration should > 20s,Message retry interval = InvisibleDuration value − Actual duration of message processing
invisibleDuration = time.Second * 20
// receive messages in a loop
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new simpleConsumer instance
simpleConsumer, err := golang.NewSimpleConsumer(&golang.Config{
Endpoint: Endpoint,
ConsumerGroup: "test-normal-group",
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithAwaitDuration(awaitDuration),
golang.WithSubscriptionExpressions(map[string]*golang.FilterExpression{
Topic: golang.SUB_ALL,
}),
)
if err != nil {
log.Fatal(err)
}
// start simpleConsumer
err = simpleConsumer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop simpleConsumer
defer simpleConsumer.GracefulStop()
go func() {
for {
fmt.Println("start recevie message")
mvs, err := simpleConsumer.Receive(context.TODO(), maxMessageNum, invisibleDuration)
if err != nil {
fmt.Println(err)
}
// ack message
for _, mv := range mvs {
//simpleConsumer.Ack(context.TODO(), mv)
fmt.Printf("%#v\n", mv)
}
fmt.Println("wait a moment")
}
}()
// run for a while
select {}
}
producer
package main
import (
"context"
"fmt"
"log"
"os"
"strconv"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "test-normal-topic"
Endpoint = "127.0.0.1:8080"
AccessKey = ""
SecretKey = ""
)
func main() {
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new producer instance
producer, err := golang.NewProducer(&golang.Config{
Endpoint: Endpoint,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithTopics(Topic),
)
if err != nil {
log.Fatal(err)
}
// start producer
err = producer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop producer
defer producer.GracefulStop()
for i := 0; i < 1; i++ {
// new a message
msg := &golang.Message{
Topic: Topic,
Body: []byte("message : " + strconv.Itoa(i)),
}
// set keys and tag
msg.SetKeys("normal-message")
msg.SetTag("normal")
// send message in sync
resp, err := producer.Send(context.TODO(), msg)
if err != nil {
log.Fatal(err)
}
for i := 0; i < len(resp); i++ {
fmt.Printf("%#v\n", resp[i])
}
// wait a moment
time.Sleep(time.Second * 1)
}
}
transaction
consumer
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "TRANSACTIONTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = "xxxxxx"
SecretKey = "xxxxxx"
)
var (
// maximum waiting time for receive func
awaitDuration = time.Second * 5
// maximum number of messages received at one time
maxMessageNum int32 = 16
// invisibleDuration should > 20s,Message retry interval = InvisibleDuration value − Actual duration of message processing
invisibleDuration = time.Second * 20
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new simpleConsumer instance
simpleConsumer, err := golang.NewSimpleConsumer(&golang.Config{
Endpoint: Endpoint,
ConsumerGroup: "test-transaction-group",
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithAwaitDuration(awaitDuration),
golang.WithSubscriptionExpressions(map[string]*golang.FilterExpression{
Topic: golang.SUB_ALL,
}),
)
if err != nil {
log.Fatal(err)
}
// start simpleConsumer
err = simpleConsumer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop simpleConsumer
defer simpleConsumer.GracefulStop()
shanghaiLoc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
go func() {
for {
fmt.Println("start recevie message")
mvs, err := simpleConsumer.Receive(context.TODO(), maxMessageNum, invisibleDuration)
if err != nil {
fmt.Println(err)
}
// ack message
for _, mv := range mvs {
simpleConsumer.Ack(context.TODO(), mv) // consumer retry times: default 16
fmt.Printf("message:%v send time:%v receive time:%v\n", string(mv.GetBody()), mv.GetBornTimestamp().In(shanghaiLoc).Format("2006-01-02 15:04:05"), time.Now().In(shanghaiLoc).Format("2006-01-02 15:04:05"))
}
fmt.Println("wait a moment")
}
}()
// run for a while
select {}
}
producer
package main
import (
"context"
"fmt"
"log"
"os"
"strconv"
"time"
"github.com/apache/rocketmq-clients/golang"
"github.com/apache/rocketmq-clients/golang/credentials"
)
const (
Topic = "TRANSACTIONTopic"
Endpoint = "127.0.0.1:8080"
AccessKey = "xxxxxx"
SecretKey = "xxxxxx"
)
func main() {
// log to console
os.Setenv("mq.consoleAppender.enabled", "true")
os.Setenv(golang.CLIENT_LOG_LEVEL, "error")
golang.ResetLogger()
// new producer instance
producer, err := golang.NewProducer(&golang.Config{
Endpoint: Endpoint,
Credentials: &credentials.SessionCredentials{
AccessKey: AccessKey,
AccessSecret: SecretKey,
},
},
golang.WithTransactionChecker(&golang.TransactionChecker{
Check: func(msg *golang.MessageView) golang.TransactionResolution {
log.Printf("check transaction message:%v, messageId:%v", string(msg.GetBody()), msg.GetMessageId())
return golang.COMMIT
},
}),
golang.WithTopics(Topic),
)
if err != nil {
log.Fatal(err)
}
// start producer
err = producer.Start()
if err != nil {
log.Fatal(err)
}
// gracefule stop producer
defer producer.GracefulStop()
for i := 0; i < 10; i++ {
// new a message
msg := &golang.Message{
Topic: Topic,
Body: []byte("message : " + strconv.Itoa(i)),
}
// set keys and tag
msg.SetKeys("transaction")
msg.SetTag("ab")
// send message in sync
transaction := producer.BeginTransaction()
resp, err := producer.SendWithTransaction(context.TODO(), msg, transaction)
if err != nil {
log.Fatal(err)
}
if err := executeLocalTransaction(i); err != nil {
if rbErr := transaction.RollBack(); rbErr != nil {
log.Printf("回滚事务失败: %v", rbErr)
}
log.Printf("本地事务执行失败: %v", err)
continue
}
for i := 0; i < len(resp); i++ {
fmt.Printf("%#v\n", resp[i])
}
// commit transaction message
err = transaction.Commit()
if err != nil {
log.Fatal(err)
}
}
}
func executeLocalTransaction(index int) error {
// 模拟数据库操作
log.Printf("执行本地事务,更新订单状态,index: %d", index)
// 模拟业务逻辑
if index%3 == 0 {
return fmt.Errorf("模拟本地事务执行失败,index: %d", index)
}
// 模拟执行时间
time.Sleep(time.Millisecond * 10)
return nil
}
// sh mqadmin updateTopic -c DefaultCluster -t TRANSACTIONTopic -n rmqnamesrv:9876 -a +message.type=TRANSACTION