Water2Wine

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
1. producer

MQProducer接口:

public interface MQProducer<K, V> {
    Future<RecordMetadata> send(ProducerRecord<K, V> var1) throws IllegalArgumentException; // 异步发送

    Future<RecordMetadata> send(ProducerRecord<K, V> var1, Callback var2) throws IllegalArgumentException; // 实现了回调函数的异步发送

    void flush(); // cas更新offset

    List<PartitionInfo> partitionsFor(String var1) throws IllegalArgumentException; // 获取分区信息

    long lastOffset(TopicPartition var1) throws InterruptedException; // 获取上一次写入的偏移量

    void close(); // 关闭

    void close(long var1, TimeUnit var3); // 指定时间内关闭
}

获取需要生产的消息:

private static synchronized String getMqProducer() {
        if (null == mqProducer) {
             Properties props = new Properties();
             props.put("key.serializer", StringSerializer.class);
             props.put("value.serializer", ByteArraySerializer.class);

             mqProducer = new MQProducerImpl<>(props);
         }
        } 
        return null;
    }

发送消息:

public void sendMessage(String topic, byte[] msg) {
        AtomicBoolean result = new AtomicBoolean(true); // 使用原子类
        getMqProducer();
        ProducerRecord<String, byte[]> producerRecord = new ProducerRecord<>(topic, msg);
        mqProducer.send(producerRecord, (recordMetadata, e);
        } catch (IOException e) {
            if (null != mqProducer) {
                mqProducer.close();
            }
            result.set(false);
        }
        if (!result.get()) {
            throw new BusinessException("deal send device alarm status ");
        }
    }
2. consumer

MQConsumer接口:

public interface MQConsumer<K, V> {
    Set<TopicPartition> assignment(); // 可以订阅的topic和partition

    Set<String> subscription(); // 可以订阅的topic的String名称

    void subscribe(List<String> var1) throws IllegalArgumentException;
    void subscribe(List<String> var1, ConsumerRebalanceListener var2) throws IllegalArgumentException;
    void subscribe(Pattern var1, ConsumerRebalanceListener var2);
    void unsubscribe();

    void assign(List<TopicPartition> var1);
  
    ConsumerRecords<K, V> poll(long var1); // 拉取消息

    long position(TopicPartition var1); // 获取var1的offset值

    OffsetAndMetadata committed(TopicPartition var1); // 消费完后向指定partition提交偏移量和metadata

    List<PartitionInfo> partitionsFor(String var1) throws IllegalArgumentException;

    // 提交的同步和非同步方法
    void commitSync();
    void commitSync(Map<TopicPartition, OffsetAndMetadata> var1) throws IllegalArgumentException;
    void commitAsync();
    void commitAsync(OffsetCommitCallback var1) throws IllegalArgumentException;
    void commitAsync(Map<TopicPartition, OffsetAndMetadata> var1, OffsetCommitCallback var2) throws IllegalArgumentException;

    void seek(TopicPartition var1, long var2) throws IllegalArgumentException;
    void seekToBeginning(TopicPartition... var1) throws IllegalArgumentException;
    void seekToEnd(TopicPartition... var1) throws IllegalArgumentException;

    String getGroupID();

    Properties getProperties();

    void wakeup();

    void close(); // 关闭消费

    void pause(TopicPartition... var1); // 暂停消费

    void resume(TopicPartition... var1); // 
}

参数:

    public static final String GROUP_ID = "group.id"; // DMQ消息消费的GROUP_ID

    public static final String BOARD_REMOVE_GROUP_ID = "campus_alarm_service_board_remove_group_id"; // 单板移除topic的groupid

    public static final String KEY_DESERIALIZER = "key.deserializer"; // DMQ消息key的反序列化

    public static final String VALUE_DESERIALIZER = "value.deserializer"; // DMQ消息value的反序列化

    public static final String MAX_POLL_RECORDS_KEY = "max.poll.records"; // DMQ中最大pull数

    public static final String MAX_POLL_RECORDS_VALUE = "8"; // DMQ中最大pull数目

    public static final long SLEEP_TIME = 10000L;

    public static final int WAIT_FOR_POLL = 5000;

    private static final Logger LOGGER = LoggerFactory.getLogger(BoardRemoveConsumer.class); // 记录日志用

    private volatile boolean stopped; // 线程停止标志

    private final String topic; // DMQ的Topic

    private MQConsumer<String, byte[]> mqConsumer; // MQConsumer类

停止消费:

public void stop() { // 停止消费
this.stopped = true; 
mqConsumer.close();

开启消费:

public void run() { // 开启消费
        while (!stopped) {
            try {
                if (dealRun()) {
                    continue;
                }

消费的主方法:

private boolean dealRun() {
        if (null == mqConsumer) {
            // 设置消费者配置以及订阅topic
            buildPropertyAndSubscribe();
            // 如果mqConsumer为空,sleep 10s
            if (null == mqConsumer) {
                Thread.sleep(SLEEP_TIME);
                return true;
            }
        }

        // 从DMQ中获取消息
        ConsumerRecords<String, byte[]> records = mqConsumer.poll(WAIT_FOR_POLL);

        // 处理消息
        for (ConsumerRecord<String, byte[]> record : records) {
            dealRecord(record);
        }
        // 提交offset
        mqConsumer.commitSync();
        }
        return false;
    }

设置消费者配置以及订阅topic:

private void buildPropertyAndSubscribe() {
        try {
            // 设置消费者配置
            final Properties props = new Properties();
            // 每个节点都要消费DMQ消息
            props.put(GROUP_ID, BOARD_REMOVE_GROUP_ID); // 设置消费的group_id
            props.put(KEY_DESERIALIZER, StringDeserializer.class); // 设置消息的key的属性为String
            props.put(VALUE_DESERIALIZER, ByteArrayDeserializer.class); // 设置消息的value的属性为bytearray
            props.put(MAX_POLL_RECORDS_KEY, MAX_POLL_RECORDS_VALUE); // 设置最大拉取消息数

            mqConsumer = new MQConsumerImpl<String, byte[]>(props);

            // 订阅topic
            final List<String> topicList = Arrays.asList(topic);
            mqConsumer.subscribe(topicList); // 订阅
        } 
    }

处理消息:

private void dealRecord(ConsumerRecord<String, byte[]> record) {
            // 将接收到的DMQ消息转换成原对象
            NcfNotificationMsg notification = NcfNotificationMsg.parseFrom(
                record.value()); // 通过record获取原对象

            BoardRemoveBean notificationBean = null;
            notificationBean = new BoardRemoveBean(
                XmlUtil.readXmlToDocument(notification.getNotification()),
                notification.getLogicSessionId()); // 读取xml文件
            // 分发消息
            BoardRemoveImpl.getInstance().boardRemoveProcess(notificationBean);
        }
    }

线程分发消息:

void boardRemoveProcess(final BoardRemoveBean bean) {
        BoardRemoveTask task = new BoardRemoveTask(bean); // 根据topic的类型指定不同的消费任务去消费
        executor.execute(task); // 线程池执行该任务
posted on 2020-08-14 14:24  Water2Wine  阅读(567)  评论(0编辑  收藏  举报