Golang之RocketMQ基础使用

5,232 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

RocketMQ是由阿里巴巴自主研发的消息队列,具有分布式、高并发的特性,目前已捐献至Apache基金会,并成为Apache基金会的顶级开源项目。RocketMQ在使用方面和其他消息队列一样,我们只需要关心如何维护好消息的发布与消费。本文的内容主要分为以下几个部分:

  • RocketMQ的安装

  • 使用rocketmq-console操作RocketMQ中的数据

  • Golang 扩展模块的安装

  • 基于Golang扩展模块操作RocketMQ

Github项目地址:github.com/apache/rock…

官方文档:rocketmq.apache.org/docs/quick-…

rocketmq-client-go 模块参考地址:github.com/apache/rock…

安装

通过Docker安装,总体分为三步:

  • 编写broker.conf文件

  • 编写docker-compose.yml文件

  • 启动服务

如果使用mqadmin操作数据可能会出现以下几种错误:

一、ignoring option PermSize=128m; support was removed in 8.0 ... error='Cannot allocate memory',解决办法如下:

修改与mqadmin同目录的文件tools.sh:

# 修改前
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=128m"
# 修改后
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m"

修改与mqadmin同目录的文件runserver.sh:

# 修改前
JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}"
# 修改后
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m"

修改与mqadmin同目录的文件runbroker.sh:

# 修改前
JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}"
# 修改后
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m"

二、UpdateTopicSubCommand command failed,解决办法如下:

修改与mqadmin同目录的文件tools.sh:

# 修改前
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
# 修改后
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el7_6.x86_64/jre/lib/ext"

安装流程:

  1. 新建rocketmq文件夹,专门用于存放broker.conf\docker-compose.yml文件。在rocketmq目录下新建conf文件夹,进入conf文件夹后新建broker.conf文件。

目录结构:

rocketmq
├── conf
│   └── broker.conf
├── docker-compose.yml

broker.conf 文件

brokerClusterName = DefaultCluster  
brokerName = broker-a  
brokerId = 0  
deleteWhen = 04  
fileReservedTime = 48  
brokerRole = ASYNC_MASTER  
flushDiskType = ASYNC_FLUSH  
# broker容器IP
# 通过客户端远程访问时,需要设置为服务器的IP地址
brokerIP1 = rmqbroker
  1. 编辑 docker-compose.yml 文件,
version: '2'
services:
  namesrv:
    image: rocketmqinc/rocketmq
    container_name: rmqnamesrv
    restart: always
    ports:
      - 9876:9876
    volumes:
      - ./logs:/home/rocketmq/logs
      - ./store:/home/rocketmq/store
    command: sh mqnamesrv
  broker:
    image: rocketmqinc/rocketmq
    container_name: rmqbroker
    restart: always
    ports:
      - 10909:10909
      - 10911:10911
      - 10912:10912
    volumes:
      - ./logs:/home/rocketmq/logs
      - ./store:/home/rocketmq/store
      - ./conf/broker.conf:/opt/rocketmq-4.4.0/conf/broker.conf
    command: sh mqbroker -n namesrv:9876 -c ../conf/broker.conf
    depends_on:
      - namesrv
  console:
    image: styletang/rocketmq-console-ng
    container_name: rocketmq-console
    restart: always
    ports:
      - 9090:8080
    depends_on:
      - namesrv
    environment:
      - JAVA_OPTS= -Dlogging.level.root=info -Drocketmq.namesrv.addr=rmqnamesrv:9876 
      - Dcom.rocketmq.sendMessageWithVIPChannel=false
  1. 后台启动服务
docker-compose up -d

访问 ip:9090,当集群中出现我们在broker.conf中设置DefaultCluster时,说明服务已成功启动

image.png

使用rocketmq-console操作RocketMQ中的数据

  1. 新增修改主题

image.png

  1. 发送消息,在主题列表中点击发送消息,会弹出如下图所示的窗口,在该窗口中填写需要发送的消息

image.png

  1. 查看消息,在消息中选择刚刚发送消息的主题,点击MESSAGE DETAIL查看消息详情

image.png

golang 模块安装

go get github.com/apache/rocketmq-client-go/v2

基于golang 模块的基础使用

1、生产者,发送消息

p, _ := rocketmq.NewProducer(
   producer.WithNameServer([]string{"localhost:9876"}), // 接入点地址
   producer.WithRetry(2), // 重试次数
   producer.WithGroupName("ProductGroup"), // 分组名称
)
p.Start()
// 发送的消息
msg := &primitive.Message{
   Topic: "topicName",
   Body:  []byte("Hello RocketMQ Go Client!"),
}
msg.WithTag("my-tag")
msg.WithKeys([]string{"my-key"})
// 发送消息
result, _ := p.SendSync(context.Background(), msg)
fmt.Println(result)

2、消费者,接受消息

c, _ := rocketmq.NewPushConsumer(
   consumer.WithNameServer([]string{"localhost:9876"}), // 接入点地址
   consumer.WithConsumerModel(consumer.Clustering),
   consumer.WithGroupName("ConsumerGroup"), // 分组名称
)
c.Subscribe("topicName", consumer.MessageSelector{}, func(ctx context.Context, msg ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
   for _, v := range msg {
      fmt.Println(string(v.Body)) // v.Body : 消息主体
   }
   return consumer.ConsumeSuccess, nil
})
forever := make(chan bool)
err = c.Start()
if err != nil {
   t.Fatal(err)
}
<-forever