RockMq安装到使用

工作需要,得装一个MQ,选择了rocketmq,具体对比一搜很多,其实也就是普通使用,既然大家都说这个好,那就这个吧。

官网的下载地址http://rocketmq.apache.org/dowloading/releases/,现在最新版本是4.5.2,选择rocketmq-all-4.5.2-bin-release.zip,这个是编译好的,下载下来可以直接用。

RockMq安装到使用_第1张图片

大概就是这样,上面的logs文件夹是自己加的,里面有broker,nameserver,console的三个日志文件,几个sh脚本也是自己加的,方便启动和停止。

192.168.1.224是我本地装的虚拟机的地址,路径就是装rocketmq的路径了。

注意java代码里配置的ip,即使程序和mq装在同一个机器上,也不能使用localhost,必须写局域网ip才可以!!!

broker_startup.sh

nohup sh bin/mqbroker -n 192.168.1.224:9876 >/home/rocketmq/rocketmq-all-4.5.2-bin-release/logs/broker.log 2>&1 &

sh bin/mqshutdown broker

sh bin/mqshutdown broker

nameserver_startup.sh

nohup sh bin/mqnamesrv >/home/rocketmq/rocketmq-all-4.5.2-bin-release/logs/mqnamesrv.log 2>&1 &

nameserver_shutd.sh

sh bin/mqshutdown namesrv

console_startup.sh

nohup java -jar lib/rocketmq-console-ng-1.0.1.jar >/home/rocketmq/rocketmq-all-4.5.2-bin-release/logs/console.log 2>&1 &

console_shutd.sh写的有点问题,就不贴了。

修改conf/broker.conf

RockMq安装到使用_第2张图片

autoCreateTopicEnable=false和autoCreateSubscriptionGroup=false关闭自动创建topic和group。

地址写虚拟机本地ip,不要写localhost。

如果需要可视化的控制台,可以到github上https://github.com/apache/rocketmq-externals下载,有个rocketmq-console的子项目,就是控制台,下载之后修改application.properties,修改这几个就可以了

server.port=12581
rocketmq.config.namesrvAddr=192.168.1.224:9876
rocketmq.config.isVIPChannel=false

pom.xml文件中有个4.4.0,指定mq的版本,因为我用的4.5.2,所以改成了4.5.2,结果编译报错,提示什么方法没覆盖,这里不需要改,就4.4.0就可以,编译命令

mvn clean package -Dmaven.test.skip=true

第一次编译花了18分钟。。。。。期间哗哗的报错,最后居然提示编译成功,把编译好的包放到刚才的mq的包的lib路径下,然后将包压缩成tar,上传到服务器,压缩纯粹是为了上传的快,不压缩上传的特别慢。

解压命令

tar -xvf rocketmq-all-4.5.2-bin-release.tar

RockMq安装到使用_第3张图片

然后设置环境变量

export NAMESRV_ADDR=192.168.1.224:9876

上面这样设置只是临时生效,要永久生效的话需要修改etc/profile,在最后面加上上面这一句

然后执行刷新生效

source /etc/profile

之后进入到rocketmq的目录,用写好的脚本启动mq,然后执行测试消息

#发送消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
#消费消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

看到消息刷屏了就说明启动的没问题。

然后新建topic和group

#新建topic $位置替换为topic的名字
sh bin/mqadmin updateTopic -n 192.168.1.224:9876  -b 192.168.1.224:10911  -t $

#新建group $位置替换为group的名字
sh bin/mqadmin updateSubGroup -n 192.168.1.224:9876  -b 192.168.1.224:10911  -g $

之后就把9876,10911,12581三个端口视情况放行,修改防火墙设置就行,如果是云服务器,则需要设置安全策略放行。

如果你的机器内存很小,需要修改下面这几个文件

bin/tools.sh,bin/runbroker.sh,bin/runserver.sh

其中都有

JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m"

这样的一行配置,修改成合适的内存大小就行了,执行新建topic和group,以及测试消息的时候会用到bin/tools.sh

到此rocketmq就安装好了,下面是使用的部分。

首先是pom.xml,注意版本号和安装的版本要一致


            org.apache.rocketmq
            rocketmq-client
            4.5.2
        

配置文件,因为我的生产者和消费者是在同一个应用里,所以在一起,一般都是分开的

rocketMQ.producer.statement.address=192.168.1.224:9876
rocketMQ.producer.statement.group=statement
rocketMQ.producer.statement.instanceName=statement
rocketMQ.consumer.statement.address=192.168.1.224:9876
rocketMQ.consumer.statement.group=statement
rocketMQ.consumer.statement.topic=statement
rocketMQ.consumer.statement.tag=*

配置类,用于在一些地方取值

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MQProperties {

    //对账topic

    private static String statementTopic;
    //对账tag

    private static String statementTag;

    public static String getStatementTopic() {
        return statementTopic;
    }

    public static String getStatementTag() {
        return statementTag;
    }

    @Value("${rocketMQ.consumer.statement.topic}")
    public void setStatementTopic(String statementTopic) {
        MQProperties.statementTopic = statementTopic;
    }
    @Value("${rocketMQ.consumer.statement.tag}")
    public void setStatementTag(String statementTag) {
        MQProperties.statementTag = statementTag;
    }
}

生产者,这里没用@Bean主要是考虑以后要是再加多个生产者,方便用名字区分,然而并不会再加了,感觉多此一举


import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Slf4j
@Component
public class MQProducerHandler {

    @Value("${rocketMQ.producer.statement.address:}")
    private String statementAddress;

    @Value("${rocketMQ.producer.statement.group:}")
    private String statementGroup;

    @Value("${rocketMQ.producer.statement.instanceName:}")
    private String statementInstanceName;

    private DefaultMQProducer statementProducer;
    private boolean isAvailable_statementProducer = false;

    @PostConstruct
    public void createStatementProducer() {
        log.info("StatementProducer 创建中");
        statementProducer = new DefaultMQProducer(statementGroup);
        statementProducer.setNamesrvAddr(statementAddress);
        statementProducer.setInstanceName(statementInstanceName);
        statementProducer.setVipChannelEnabled(false);
        statementProducer.setRetryTimesWhenSendAsyncFailed(2);//发送失败后重试次数
        try {
            statementProducer.start();
            isAvailable_statementProducer = true;
            log.info("StatementProducer 创建成功");
        } catch (MQClientException e) {
            log.error("StatementProducer 创建失败", e);
        }
    }

    public DefaultMQProducer getStatementProducer() {
        return statementProducer;
    }

    public boolean isAvailable_statementProducer() {
        return isAvailable_statementProducer;
    }
}

消费者同理


import com.xxx.ccc.service.IEtcStatementService;
import com.xxx.ccc.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class StatementConsumer {

    @Value("${rocketMQ.consumer.statement.address:}")
    private String address;

    @Value("${rocketMQ.consumer.statement.group:}")
    private String group;

    @Value("${rocketMQ.consumer.statement.topic:}")
    private String topic;

    @Value("${rocketMQ.consumer.statement.tag:}")
    private String tag;


    @Autowired
    private IEtcStatementService iEtcStatementService;

    private DefaultMQPushConsumer consumer;

    @PostConstruct
    public void createStatementConsumer() {
        try {
            log.info("StatementConsumer 创建中");
            consumer = new DefaultMQPushConsumer(group);
            consumer.setNamesrvAddr(address);
            consumer.subscribe(topic, tag);
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            consumer.registerMessageListener((MessageListenerConcurrently) (messageList, context) -> {
                try {
                    for (MessageExt messageExt : messageList) {
                        String message = new String(messageExt.getBody(), StandardCharsets.UTF_8);
                        iEtcStatementService.statementConsume(message);
                    }
                } catch (Exception e) {
                    log.error("StatementConsumer消费失败:" + JsonUtils.serialize(messageList), e);
                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            });
            consumer.start();
            log.info("StatementConsumer 创建成功");
        } catch (MQClientException e) {
            log.error("StatementConsumer 创建失败", e);
        }


    }
}

生产的地方,send方法的重载巨多,最简单的就是传一个string,同步返回,失败了就抛出异常

        //推送到队列
        DefaultMQProducer statementProducer = mqProducerHandler.getStatementProducer();
        String messageKey = "statement_add_" + etcStatement.getId();
        Message message = new Message(
                MQProperties.getStatementTopic(),
                MQProperties.getStatementTag(),
                messageKey,
                ("" + etcStatement.getId()).getBytes(StandardCharsets.UTF_8)
        );
        try {
            //同步发送,发送失败则会抛出异常
            statementProducer.send(message);
            log.info("消息发送成功:" + messageKey);
        } catch (Exception e) {
            log.error("消息发送失败:" + messageKey, e);
            throw ExpFactory.resp(ErrorResps.ETC_STATEMENT_NULL.get());
        }

这样简单的使用还是很容易的。

补一个遇到的坑,装了rocketmq之后我又在虚拟机上装了docker,然后我本地跑的程序就连不上mq了,看控制台

RockMq安装到使用_第4张图片

这里的地址应该是1.224,是虚拟机的ip,但是现在显示的是172.17.0.1:10911,这个ip是docker的ip

RockMq安装到使用_第5张图片

 

网上搜了下说是broker自动搜网络,搜错了,所以要在conf文件夹下加一个broker.properties文件,里面就配一个变量

brokerIP1=192.168.1.224

然后修改下启动broker的脚本

nohup sh bin/mqbroker -n 192.168.1.224:9876 -c conf/broker.properties >/home/rocketmq/rocketmq-all-4.5.2-bin-release/logs/broker.log 2>&1 &

加上-c指定配置文件, 这样启动起来网络就对了。

 

 

你可能感兴趣的:(RockMq安装到使用)