Linux rocketMQ 安装和使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/walle167/article/details/70242931
在对比了RabbitMQ,apacheMQ之后,发现还是 rocketMQ 好用。
为什么好用,百度查查就都知道了。
不说废话直接说说 Linux安装:

1、需要软件(免安装版)

  下载地址
  [release  下载地址](https://github.com/apache/incubator-rocketmq/releases)
  https://github.com/apache/incubator-rocketmq/releases
  rocketmq-all-4.0.0-incubating-bin-release.zip

2、安装JDK环境

就不多说了

3、启动namesrv

进入安装文件夹的bin 下面

这里写图片描述
使用命令:nohup sh mqnamesrv &
查看 nohup日志
这里写图片描述
发现报错信息Caused by: java.net.UnknownHostException: smkzfbweb02: 未知的名称或服务
这个时候查看文件/etc/hosts 和 /etc/hostname
发现问题所在了,我的生产服务器的hostname 被管理员改了,但是没有加入到 hosts 对应列表中,所以报错。java.net.UnknownHostException

我们修改 /etc/hosts 文件
这里写图片描述

再次启动
The Name Server boot success. serializeType=JSON

4、启动broker

使用命令 nohup sh mqbroker -n “1273.0.0.1:9876” &
查看日志
这里写图片描述
这里说的是# Native memory allocation (malloc) failed to allocate 8589934592 bytes for committing reserved memory. 内存不足够了。
查看配置文件
这里写图片描述
runbroker.sh文件是 broker 的启动文件
runserver.sh 文件是 namesev 启动文件

查看
这里写图片描述
这里写图片描述

这里发现他们的默认需要的内存 都很大,所以根据自己的服务器配置 减少一些配置

配置好了之后再启动就OK了。

package com.cat.common.rocketmq;

import java.util.Properties;

import org.apache.log4j.Logger;

import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel;
import com.cat.common.lang.RDate;
import com.cat.common.lang.RString;
import com.cat.common.lang.RUuid;
import com.cat.common.properties.PropertiesUtil;

/**
 * RocketMQ不保证消息不重复,如果你的业务需要保证严格的不重复消息,需要你自己在业务端去重。
 * 线上应该关闭autoCreateTopicEnable,即在配置文件中将其设置为false。。后果就是:以后所有该TOPIC的消息,都将发送到这台broker上,达不到负载均衡的目的。
 * API 3.6.2.Final JAR包是有问题,不推荐使用,目前使用,3.5.9JAR 可以
 * 使用3.6.2jar问题是,生产者发送的消息,消费者消费后,不能把消息状态同步给 broken,导致消费者 重启后,还是会再次受到 消息,重复消费。
 * 集群消费者= 多个消费者都是 集群消费者,订阅了同一个消息后,broken会把消息平均分配到 所有集群消费者
 * 不同的集群消费者(指定了不通的组名),订阅同一个TOPIC ,都会收到这个topic消息
 * 广播消费者= 多个广播消费者 订阅了同一个消息后,每个广播消费者都会 接收到消息
 * 同一个JVM里面只能存在唯一的 组名+实例名 的 生产者,或者是消费者,所以以下的生产者和消费者的实例名称都用uuid 指定
 * @author luoyang
 *
 */
public class RocketMqUtils{

   private static Logger _logger = Logger.getLogger(RocketMqUtils.class);

   private static final Logger _socketLog = Logger.getLogger("SocketMQSendMessage");

   private static DefaultMQProducer producer;

   private static DefaultMQPushConsumer consumer;

   private static DefaultMQPushConsumer broadConsumer;

   private static Object obj = null;

   private static Properties properties = null;

   private static void initProperties(){
      if(null == properties){
         properties = new Properties();
//         String path = RSystemConfig.Home_Path + "socketmq.properties";
         String path =  "d://socketmq.properties";
         properties = PropertiesUtil.getInstance().getProperties(path);
         _logger.info(" init socketmq.properties success.");
      }
   }

   public static void sendMessage(String topic,
                                  String messageContent){
      try{
         if(RString.isBlank(topic)){
            return;
         }
         if(null == producer){
            getProducer();
         }
         _logger.info("sendMessage topic=" + topic + " messageContent=" + messageContent);
         _socketLog.info(RString.format("{0}, sendMessage topic={1}, messageContent={2}", RDate.getCurrentTimeStr() + "|", topic, messageContent));
         // topic, body
         Message msg = new Message(topic, messageContent.getBytes());
         SendResult sendResult = producer.send(msg);
         _logger.info("sendMessage  sendResult=  " + sendResult.toString());
      }catch(Exception e){
         _socketLog.error(RDate.getCurrentTimeStr() + "| sendMessage topic=" + topic + " messageContent=" + messageContent, e);
      }

   }

   /**
    * 发送消息,工具类
    * 
    * @param topic 
    * @param messageContent 消息内容
    * @param repeatTime 如果发送失败,允许重复发送的次数,每次失败间隔200ms之后继续发送
    */
   public static void sendMessage(String topic,
                                  String messageContent,
                                  int repeatTime){
      _logger.info("sendMessage  topic=" + topic + " messageContent=" + messageContent);
      _socketLog.info(RString.format("{0}, sendMessage topic={1}, messageContent={2}", RDate.getCurrentTimeStr() + "|", topic, messageContent));
      if(RString.isBlank(topic)){
         return;
      }
      if(null == producer){
         getProducer();
      }
      boolean result = false;
      for(int i = 1; i <= repeatTime; i++){
         try{
            Message msg = new Message(topic, messageContent.getBytes());
            SendResult sendResult = producer.send(msg);
            _logger.info("sendMessage  sendResult= " + sendResult.toString());
            result = true;
         }catch(Exception e){
            e.printStackTrace();
            _logger.error("send message have exception" + e + "topic=" + topic + " messageContent=" + messageContent);
         }
         _logger.info("sendMessage  topic=" + topic + " messageContent=" + messageContent);
         if(!result){
            try{
               Thread.sleep(200);
            }catch(InterruptedException e){
               e.printStackTrace();
               _logger.error("send message have exception" + e + "topic=" + topic + " messageContent=" + messageContent + "repeat time=" + i);
            }
            continue;
         }else{
            break;
         }
      }
   }

   private static synchronized DefaultMQProducer getProducer(){
      if(null != producer){
         return producer;
      }
      initProperties();
      //一个jvm内,具有相同producerGroup名字的生产者实例只有一个。 
      producer = new DefaultMQProducer(RTopicConstants.Product_Group);
      producer.setNamesrvAddr(properties.getProperty("namesrv_addr"));
      producer.setInstanceName(RUuid.makeUuid());
      try{
         // 生产者开启
         producer.start();
         // 关闭容器时,关闭生产者
         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){

            public void run(){
               _logger.info("getProducer" + ".............producer.shutdown.....");
               producer.shutdown();
            }
         }));
         _logger.info("getProducer init product success..data[namesrvAddr={0}]" + properties.getProperty("namesrv_addr"));
      }catch(MQClientException e){
         e.printStackTrace();
         _logger.error("getProducer have exception" + e);
      }
      return producer;
   }

   public static DefaultMQPushConsumer getConsumer(){
      if(null != obj){
         return consumer;
      }
      initConsumer();
      return consumer;
   }

   public static DefaultMQPushConsumer getBroadConsumer(){
      if(null != obj){
         return broadConsumer;
      }
      initConsumer();
      return broadConsumer;
   }

   private static synchronized void initConsumer(){
      try{
         if(null == obj){
            initProperties();
            consumer = new DefaultMQPushConsumer(RTopicConstants.Consumer_Group);
            consumer.setNamesrvAddr(properties.getProperty("namesrv_addr"));
            consumer.setInstanceName(RUuid.makeUuid());

            broadConsumer = new DefaultMQPushConsumer(RTopicConstants.Broad_Consumer_Group);
            broadConsumer.setNamesrvAddr(properties.getProperty("namesrv_addr"));
            broadConsumer.setMessageModel(MessageModel.BROADCASTING);
            broadConsumer.setInstanceName(RUuid.makeUuid());

            obj = new Object();
            _logger.info("intConsumer init consumer success..data[namesrvAddr={0}]" + properties.getProperty("namesrv_addr"));
         }

      }catch(Exception e){
         e.printStackTrace();
         _logger.error("initConsumer have exception" + e);
      }
   }

}
package com.cat.common.rocketmq;


public class RTopicConstants{

   /**
    *  默认集群消费者
    */
   public static final String Consumer_Group="ConsumerGroup";

   /**
    * 广播消费者
    */
   public static final String Broad_Consumer_Group="BroadConsumerGroup";

   /**
    * 生产者群
    */
   public static final String Product_Group="ProductGroup";

   /**
    * 默认生产者
    */
   public static final String Instancename_Producer = "Producer";

   /**-------UIC消息TOPIC-------**/
   public static final String luoyang="luoyang";

}

生产者

package com.cat.common.rocketmq;

import java.util.HashMap;
import java.util.Map;

import com.cat.common.json.RJson;
import com.cat.common.lang.RDate;

public class DemoProduct{

   public static void main(String[] args){
      try{
         for(int i = 0; i < 5; i++){
            Map<String, Object> m = new HashMap<String, Object>();
            m.put("name", i+"1");
            m.put("age", 10);
            m.put("address", i+"杭州市晋江市带卡");
            String msg = RJson.getJson(m);
            RocketMqUtils.sendMessage(RTopicConstants.luoyang, msg);
            Thread.sleep(1000);
            System.out.println(RDate.getCurrentTimeStr()+ ",生产发送消息"+i);
         }

      }catch(Exception e){
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

消费者

package com.cat.common.rocketmq;

import java.util.List;

import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.common.message.MessageExt;

public class DemoCustom{

   public static void initConsumer(){
      try{
         System.out.println("开启集群消费者1:");
         DefaultMQPushConsumer consumer = RocketMqUtils.getConsumer();
         consumer.subscribe(RTopicConstants.luoyang, "*");
         consumer.registerMessageListener(new MessageListenerConcurrently(){
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                            ConsumeConcurrentlyContext context){
               try{
                  MessageExt msg = msgs.get(0);
                  String data = new String(msg.getBody());
                  if(msg.getTopic().equals(RTopicConstants.luoyang)){
                     System.out.println("集群消费者接收到消息:" + data);
                  }
               }catch(Exception e){
                  e.printStackTrace();
                  //一会之后重新发送,可自行判断 时候要重试
                  return ConsumeConcurrentlyStatus.RECONSUME_LATER;
               }
               //根据业务逻辑成功处理  返回成功
               return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
         });
         // 开启消费
         consumer.start();
      }catch(Exception e){
         e.printStackTrace();
      }

   }

   /**
    * 注册广播模式消息
    * @throws MQClientException
    */
   public static void initBroadConsumer()
         throws MQClientException{
      System.out.println("开启广播消费者");
      DefaultMQPushConsumer broadConsumer = RocketMqUtils.getBroadConsumer();
      broadConsumer.subscribe(RTopicConstants.luoyang, "*");
      broadConsumer.registerMessageListener(new MessageListenerConcurrently(){

         public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                         ConsumeConcurrentlyContext context){
            try{
               MessageExt msg = msgs.get(0);
               String data = new String(msg.getBody());
               // 数据解析
               // 同步配置中心数据
               if(msg.getTopic().equals(RTopicConstants.luoyang)){
                  System.out.println("广播消费者接收到消息:" + data);
               }
            }catch(Exception e){
               e.printStackTrace();
               return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
         }
      });
      broadConsumer.start();
   }

   public static void main(String[] args){
      try{
         initConsumer();
         initBroadConsumer();
      }catch(Exception e){
         e.printStackTrace();
      }

   }
}

对于生产者

 //一个jvm内,具有相同producerGroup名字的生产者实例只有一个。 
      producer = new DefaultMQProducer(RTopicConstants.Product_Group);
      producer.setNamesrvAddr(properties.getProperty("namesrv_addr"));
      producer.setInstanceName(RUuid.makeUuid());

同一个JVM 内 组名+InstanceName 必须唯一。
否则会报错。所以我这里设置的instanceName 是uuid

对于消费者
有两种,一种是广播,一种是集群

广播模式的消费者 消息不会保存在broken里面,直接下发到消费者中,所有的广播消费者都会消费消息。

集群模式,如果一组消费者的groupname 一致,就定义为是同一个消费集群。必须保证一台JVM 里面 消费者的instanceName 是唯一的。
同一组的集群消费者 平均消费 消息
并且,如果是集群消费,那么集群消费的所有消费者必须订阅相同的topic,否则会报错

展开阅读全文

没有更多推荐了,返回首页