Linux rocketMQ 安装和使用

在对比了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 下面

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

我们修改 /etc/hosts 文件
Linux rocketMQ 安装和使用_第3张图片

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

4、启动broker

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

查看
Linux rocketMQ 安装和使用_第6张图片
Linux rocketMQ 安装和使用_第7张图片

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

配置好了之后再启动就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 m = new HashMap();
            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 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 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,否则会报错

你可能感兴趣的:(java)