48. 从零开始学springboot: 接入RocketMQ

Springboot整合Rocketmq系列教程 本教程是基于Springboot2.6.3整合Rocketmq5.0,其中涉及了Rocketmq的安装,消息的发送及消费的代码实现。本文不会对rocketmq的一些概念、原理,及注意事项进行讲解,因为官网已经写的很清楚,又有中文版,详细访问https://rocketmq.apache.org/zh/docs/quickStart/01quickstart。 阅读详情

前言

微服务的架构越来越流行, 很多老旧项目面临着解耦重构, 复杂项目的解耦通常会引入一些中间件来帮助我们更好的完成工作, 本章, 我们就来通过实例了解下消息中间件的用法.

市面上比较流行的消息中间件如下
image.png

因为鱼哥的项目上了阿里的云, 所以选择很简单, 就用RocketMQ即可, 看官们根据实际情况择优选择.

RocketMQ

注意, 本文使用了4.0sdk,截止到文章发表, ali已推出5.0SDK
关于阿里的RocketMQ的介绍官方有详细的文档, 这里就不啰嗦了

官方已SDK提供了简单的接入方式, 需要注意的是, 官方提供了两种协议的SDK

image.png

  • HTTP协议
    采用RESTful风格,方便易用,快速接入,跨网络能力强. 支持Java、C++、.NET、Go、Python、Node.js和PHP七种语言客户端

  • TCP协议
    区别于HTTP简单的接入方式,提供更为专业、可靠、稳定的TCP协议的SDK接入服务. 支持的语言包括Java、C/C++ 以及.NET

注意, 使用的话需要自费开通对应的服务, 通过后才能使用, 大部分管理功能都能在阿里云的控制台中找到.

实例

下面我们就springboot来实际使用下RocketMQ.
为了较好的使用, 我们同时演示tcp何http两种方式

pom引入依赖

<!-- tcp sdk -->
<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>ons-client</artifactId>
    <version>${ali-mq-tcp.version}</version>
</dependency>
<!-- http sdk -->
<dependency>
    <groupId>com.aliyun.mq</groupId>
    <artifactId>mq-http-sdk</artifactId>
    <version>${ali-mq-http.version}</version>
    <classifier>jar-with-dependencies</classifier>
</dependency>

接入tcp方式

定义mq配置类

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "aliyun.rocketmq.tcp")
public class MqTcpProperties {

    //AccessKey ID,身份验证,在RAM控制台创建
    private String accessKeyId;

    //AccessKey Secret,身份验证,在RAM控制台创建
    private String accessKeySecret;

    //实例TCP协议接入地址(内网)
    private String nameSrvAddr;

    //发送超时时间: 3s
    private String sendMsgTimeoutMillis = "3000";

    //线程数目:默认20
    private String consumeThreadNums = "20";

    //订阅方式: 集群
    private String messageModel = "CLUSTERING";


    public Properties getMqProperties() {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.AccessKey, this.accessKeyId);
        properties.setProperty(PropertyKeyConst.SecretKey, this.accessKeySecret);
        properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr);
        // 设置发送超时时间,单位毫秒
        properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, this.sendMsgTimeoutMillis);
        // 设置消费者线程数为20个(默认20)
        properties.setProperty(PropertyKeyConst.ConsumeThreadNums, this.consumeThreadNums);
        // 订阅方式设置
        properties.put(PropertyKeyConst.MessageModel, this.messageModel);
        return properties;
    }
}

定义Topic配置类

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "aliyun.rocketmq.tcp")
public class MqTcpTopicProperties {
    private String topic;
    private String groupId;
    private String tag;
}

封装一个工具类

@Slf4j
public class MqTcpUtil {

    @Autowired
    private ProducerBean producer;

    @Autowired
    private MqTcpProperties mqTcpProperties;

    @Autowired
    private MqTcpTopicProperties mqTcpTopicProperties;

    private ConsumerBean consumerBean;

    /**
     * 同步发送消息 - 配置默认topic
     *
     * @param msgTag      标签,可用于消息小分类标注
     * @param messageBody 消息body内容,生产者自定义内容
     * @param msgKey      消息key值,建议设置全局唯一,可不传,不影响消息投递
     * @return success:SendResult or error:null
     */
    public SendResult sendMsg(String msgTag, String messageBody, String msgKey) {
        Message msg = new Message(mqTcpTopicProperties.getTopic(), msgTag, msgKey, messageBody.getBytes());
        return this.send(msg, Boolean.FALSE);
    }

    /**
     * 同步发送消息 - 配置默认topic - 重试次数
     *
     * @param msgTag      标签,可用于消息小分类标注
     * @param messageBody 消息body内容,生产者自定义内容
     * @param msgKey      消息key值,建议设置全局唯一,可不传,不影响消息投递
     * @param retryTimes  重试次数,注意实际请求次数为 retryTimes + 1
     * @return success:SendResult or error:null
     */
    public SendResult sendMsg(String msgTag, String messageBody, String msgKey, Integer retryTimes) {
        Message msg = new Message(mqTcpTopicProperties.getTopic(), msgTag, msgKey, messageBody.getBytes());
        SendResult result = this.send(msg, Boolean.FALSE);
        if (ObjectUtil.isNotEmpty(result) || retryTimes == 0) {
            return result;
        }
        return this.sendMsg(msgTag, messageBody, msgKey, --retryTimes);
    }

    /**
     * 同步发送消息
     *
     * @param topic       topic名
     * @param msgTag      标签,可用于消息小分类标注
     * @param messageBody 消息body内容,生产者自定义内容
     * @param msgKey      消息key值,建议设置全局唯一,可不传,不影响消息投递
     * @return success:SendResult or error:null
     */
    public SendResult sendMsg(String topic, String msgTag, String messageBody, String msgKey) {
        Message msg = new Message(topic, msgTag, msgKey, messageBody.getBytes());
        return this.send(msg, Boolean.FALSE);
    }

    /**
     * 同步发送单向消息
     *
     * @param topic       topic名
     * @param msgTag      标签,可用于消息小分类标注
     * @param messageBody 消息body内容,生产者自定义内容
     * @param msgKey      消息key值,建议设置全局唯一,可不传,不影响消息投递
     */
    public void sendOneWayMsg(String topic, String msgTag, String messageBody, String msgKey) {
        Message msg = new Message(topic, msgTag, msgKey, messageBody.getBytes());
        this.send(msg, Boolean.TRUE);
    }


    /**
     * 发送普通消息
     *
     * @param msg      消息
     * @param isOneWay 是否单向发送
     */
    private SendResult send(Message msg, Boolean isOneWay) {
        try {
            if (isOneWay) {
                //由于在 oneway 方式发送消息时没有请求应答处理,一旦出现消息发送失败,则会因为没有重试而导致数据丢失。
                //若数据不可丢,建议选用同步或异步发送方式。
                producer.sendOneway(msg);
                success(msg, "单向消息MsgId不返回");
                return null;
            } else {
                //可靠同步发送
                SendResult sendResult = producer.send(msg);
                //获取发送结果,不抛异常即发送成功
                assert sendResult != null;
                success(msg, sendResult.getMessageId());
                return sendResult;
            }
        } catch (Exception e) {
            error(msg, e);
            return null;
        }
    }

    /**
     * 成功日志打印
     *
     * @param msg
     * @param messageId
     */
    private void success(Message msg, String messageId) {
        log.info("发送MQ消息成功 -- Topic:{} ,msgId:{} , Key:{}, tag:{}, body:{}"
                , msg.getTopic(), messageId, msg.getKey(), msg.getTag(), new String(msg.getBody()));
    }

    /**
     * 异常日志打印
     *
     * @param msg
     * @param e
     */
    private void error(Message msg, Exception e) {
        log.error("发送MQ消息失败-- Topic:{}, Key:{}, tag:{}, body:{}"
                , msg.getTopic(), msg.getKey(), msg.getTag(), new String(msg.getBody()));
        log.error("errorMsg", e);
    }


    @PostConstruct
    public void init() {
        log.info("[Init] tcp consumerBean init");
        consumerBean = new ConsumerBean();
    }

    public ConsumerBean getConsumer() {
        return consumerBean;
    }

    public ConsumerBean getDefaultConsumer(MessageListener messageListener) {
        //配置文件
        Properties properties = mqTcpProperties.getMqProperties();
        //消费者
        properties.setProperty(PropertyKeyConst.GROUP_ID, mqTcpTopicProperties.getGroupId());
        //设置消费者线程数为20个(默认20)
        properties.setProperty(PropertyKeyConst.ConsumeThreadNums, mqTcpProperties.getConsumeThreadNums());
        // 广播订阅方式设置
        properties.put(PropertyKeyConst.MessageModel, mqTcpProperties.getMessageModel());
        consumerBean.setProperties(properties);

        //订阅消息
        Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
        //订阅消息
        Subscription smsSubscription = new Subscription();
        smsSubscription.setTopic(mqTcpTopicProperties.getTopic());
        smsSubscription.setExpression(mqTcpTopicProperties.getTag());
        subscriptionTable.put(smsSubscription, messageListener);
        consumerBean.setSubscriptionTable(subscriptionTable);
        return consumerBean;
    }
}

自动注入类

/**
 * rocketMq服务自动配置类
 * 业务系统要使用rocketMq服务服务,需要在配置文件中增加如下配置
 * 【
 * aliyun.rocketmq.tcp.enable=true
 * aliyun.rocketmq.tcp.accessKeyId=
 * aliyun.rocketmq.tcp.accessKeySecret=
 * aliyun.rocketmq.tcp.nameSrvAddr=
 * aliyun.rocketmq.tcp.default.topic=
 * aliyun.rocketmq.tcp.default.groupId=
 * aliyun.rocketmq.tcp.default.tag=
 */
@Slf4j
@Configuration
@EnableConfigurationProperties({MqTcpProperties.class, MqTcpTopicProperties.class})
@ConditionalOnClass({ProducerBean.class, ConsumerBean.class})
@ConditionalOnProperty(prefix = "aliyun.rocketmq.tcp", value = "enable", havingValue = "true")
public class MqTcpDefaultAutoConfiguration {

    @Autowired
    private MqTcpProperties mqTcpProperties;

    @PostConstruct
    public void init() {
        log.info("[Auto Config] MqTcpDefaultAutoConfiguration loading......");
    }

    @Bean(initMethod = "start", destroyMethod = "shutdown")
    @ConditionalOnMissingBean
    public ProducerBean buildProducer() {
        ProducerBean producer = new ProducerBean();
        producer.setProperties(mqTcpProperties.getMqProperties());
        return producer;
    }

    @Bean
    public MqTcpUtil mqTcpUtil() {
        return new MqTcpUtil();
    }

}

核心功能基本完成, 我们可以通过MqTcpUtil执行消息的发送了
新增个测试类

@Test
public void mqTcpTest() {
    // 自定义一条body内容
    JSONObject body = new JSONObject();
    UUID uuid = UUID.randomUUID();
    body.put("notice", "这是一条tcp通知类信息");
    //同步发送消息-不带返回值的(一般使用该方法)
    log.info(String.valueOf(mqTcpUtil.sendMsg("topic", "tag_dev", body.toJSONString(), String.valueOf(uuid))));
}

最后我们加上Ali RocketMq的配置即可

## AK
aliyun.rocketmq.tcp.enable=true
aliyun.rocketmq.tcp.accessKeyId=
aliyun.rocketmq.tcp.accessKeySecret=

## TCP
aliyun.rocketmq.tcp.nameSrvAddr=
aliyun.rocketmq.tcp.sendMsgTimeoutMillis=3000
aliyun.rocketmq.tcp.consumeThreadNums=20
aliyun.rocketmq.tcp.messageModel=CLUSTERING

## topic
aliyun.rocketmq.tcp.topic=
aliyun.rocketmq.tcp.groupId=
aliyun.rocketmq.tcp.tag=

消费者

以上完成了核心功能的接入与开发, 我们已经能正常发送MQ消息了, 通俗点讲就是生产者就绪了, 我们还需要消费者去消费这些消息.

合理的拆分是生产者和消费者分服务部署, 这里为了演示, 鱼哥就直接自产自销了.

定义消费者监听器MqMessageListener

@Slf4j
@Component
public class MqMessageListener implements MessageListener {

    @Override
    public Action consume(Message message, ConsumeContext context) {
        log.info("接收到MQ详细信息:{}", message);
        log.info("解析MQ-Body自定义内容:{}", new String(message.getBody()));
        try {
            //do something..
            return Action.CommitMessage;
        } catch (Exception e) {
            log.error("消费MQ消息失败,msgId:" + message.getMsgID() + ",ExceptionMsg:" + e.getMessage());
            return Action.ReconsumeLater;
        }
    }
}

申明消费者类, 这里我们定义两种消费者, 一种是默认配置的, 一种是主定义配置的,两者选一即可

@Component
public class MqConsumerClient {

//    @Autowired
//    private MqTcpProperties mqTcpProperties;

    @Autowired
    private MqMessageListener mqMessageListener;

//    @Autowired
//    private MqTcpTopicProperties mqTcpTopicProperties;

    @Autowired
    private MqTcpUtil mqTcpUtil;

//    //自定义消费者
//    @Bean(initMethod = "start", destroyMethod = "shutdown")
//    public ConsumerBean messageBuildConsumer() {
//        ConsumerBean consumerBean = mqTcpUtil.getConsumer();
//        //配置文件
//        Properties properties = mqTcpProperties.getMqProperties();
//        //消费者
//        properties.setProperty(PropertyKeyConst.GROUP_ID, mqTopicProperties.getGroupId());
//        //设置消费者线程数为20个(默认20)
//        properties.setProperty(PropertyKeyConst.ConsumeThreadNums, "20");
//        consumerBean.setProperties(properties);
//        //订阅消息
//        Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
//        // 广播订阅方式设置
//        properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING);
//        //订阅消息
//        Subscription smsSubscription = new Subscription();
//        smsSubscription.setTopic(mqTopicProperties.getTopic());
//        smsSubscription.setExpression(mqTopicProperties.getTag());
//        subscriptionTable.put(smsSubscription, mqMessageListener);
//        consumerBean.setSubscriptionTable(subscriptionTable);
//        return consumerBean;
//    }

    // 默认消费者
    @Bean(initMethod = "start", destroyMethod = "shutdown")
    public ConsumerBean defaultConsumer() {
        ConsumerBean consumerBean = mqTcpUtil.getDefaultConsumer(mqMessageListener);
        return consumerBean;
    }
}

最后启动服务, 即可看到消息消费的输出信息

image.png
image.png

接入http方式

定义mq配置类

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "aliyun.rocketmq.http")
public class MqHttpProperties {

    //AccessKey ID,身份验证,在RAM控制台创建
    private String accessKeyId;

    //AccessKey Secret,身份验证,在RAM控制台创建
    private String accessKeySecret;

    //实例TCP协议接入地址(内网)
    private String nameSrvAddr;

    //实例TCP协议接入地址(内网)
    private String sendMsgTimeoutMillis = "3000";

    //线程数目:默认20
    private String consumeThreadNums = "20";

    //线程数目:默认20
    private String messageModel = "CLUSTERING";

    public Properties getMqProperties() {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.AccessKey, this.accessKeyId);
        properties.setProperty(PropertyKeyConst.SecretKey, this.accessKeySecret);
        properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr);
        // 设置发送超时时间,单位毫秒
        properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, this.sendMsgTimeoutMillis);
        // 设置消费者线程数为20个(默认20)
        properties.setProperty(PropertyKeyConst.ConsumeThreadNums, this.consumeThreadNums);
        // 广播订阅方式设置
        properties.put(PropertyKeyConst.MessageModel, this.messageModel);
        return properties;
    }

定义Topic配置类

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "aliyun.rocketmq.http")
public class MqHttpTopicProperties {
    private String topic;
    private String groupId;
    private String tag;
}

定义操作工具类

@Slf4j
public class MqHttpUtil {

    @Autowired
    private MqHttpProperties mqHttpProperties;

    @Autowired
    private MqHttpTopicProperties mqHttpTopicProperties;

    private MQProducer producer;

    private MQConsumer consumer;

    private MQClient mqClient;

    @PostConstruct
    public void init() {
        log.info("[Init] http producer init");
        mqClient = new MQClient(
                // 设置HTTP协议客户端接入点,进入消息队列RocketMQ版控制台实例详情页面的接入点区域查看。
                mqHttpProperties.getNameSrvAddr(),
                // AccessKey ID,身份验证,在阿里云RAM控制台创建。
                mqHttpProperties.getAccessKeyId(),
                // AccessKey Secret,身份验证,在阿里云RAM控制台创建。
                mqHttpProperties.getAccessKeySecret()
        );
    }

    /**
     * 同步发送消息
     *
     * @param topic       topic名
     * @param msgTag      标签,可用于消息小分类标注
     * @param messageBody 消息body内容,生产者自定义内容
     * @param msgKey      消息key值,建议设置全局唯一,可不传,不影响消息投递
     * @return success:SendResult or error:null
     */
    public TopicMessage sendMsg(String topic, String msgTag, String messageBody, String msgKey) {
        producer = mqClient.getProducer(topic);
        TopicMessage msg = new TopicMessage(
                messageBody.getBytes(),
                msgTag);
        msg.setMessageId(msgKey);

        try {
            //可靠同步发送
            TopicMessage sendResult = producer.publishMessage(msg);
            //获取发送结果,不抛异常即发送成功
            assert sendResult != null;
            success(topic, msg);
            return sendResult;

        } catch (Exception e) {
            error(topic, msg, e);
            return null;
        }
    }

    public MQClient getMqClient() {
        return mqClient;
    }

    public MQConsumer getDefaultConsumer() {
        consumer = mqClient.getConsumer(mqHttpTopicProperties.getTopic(), mqHttpTopicProperties.getGroupId(), mqHttpTopicProperties.getTag());
        return consumer;
    }


    /**
     * 成功日志打印
     *
     * @param msg
     */
    private void success(String topic, TopicMessage msg) {
        log.info("发送MQ消息成功 -- Topic:{} ,msgId:{} , tag:{}, body:{}"
                , topic, msg.getMessageId(), msg.getMessageTag(), msg.getMessageBodyString());
    }

    /**
     * 异常日志打印
     *
     * @param msg
     * @param e
     */
    private void error(String topic, TopicMessage msg, Exception e) {
        log.error("发送MQ消息失败-- Topic:{}, msgId:{}, tag:{}, body:{}"
                , topic, msg.getMessageId(), msg.getMessageTag(), msg.getMessageBodyString());
        log.error("errorMsg", e);
    }

自动注入

/**
 * rocketMq服务自动配置类
 * 业务系统要使用rocketMq服务服务,需要在配置文件中增加如下配置
 * 【
 * aliyun.rocketmq.http.enable=true
 * aliyun.rocketmq.http.accessKeyId=
 * aliyun.rocketmq.http.accessKeySecret=
 * aliyun.rocketmq.http.nameSrvAddr=
 * aliyun.rocketmq.http.default.topic=
 * aliyun.rocketmq.http.default.groupId=
 * aliyun.rocketmq.http.default.tag=
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "aliyun.rocketmq.http", value = "enable", havingValue = "true")
public class MqHttpDefaultAutoConfiguration {

    @PostConstruct
    public void init() {
        log.info("[Auto Config] MqHttpDefaultAutoConfiguration loading......");
    }

    @Bean
    public MqHttpUtil mqHttpUtil() {
        return new MqHttpUtil();
    }

}

最后测试下

    @Test
    public void mqHttpTest() {
        // 自定义一条body内容
        JSONObject body = new JSONObject();
        UUID uuid = UUID.randomUUID();
        body.put("notice", "这是一条http通知类信息");
        //同步发送消息-不带返回值的(一般使用该方法)
        log.info(String.valueOf(mqHttpUtil.sendMsg("topic", "tag_dev", body.toJSONString(), String.valueOf(uuid))));
    }

最后增加配置

#***********************MQ-http*********************************
## AK
aliyun.rocketmq.http.enable=true
aliyun.rocketmq.http.accessKeyId=
aliyun.rocketmq.http.accessKeySecret=

## HTTP
aliyun.rocketmq.http.nameSrvAddr=
aliyun.rocketmq.http.sendMsgTimeoutMillis=3000
aliyun.rocketmq.http.consumeThreadNums=20
aliyun.rocketmq.http.messageModel=CLUSTERING

## topic
aliyun.rocketmq.http.topic=topic
aliyun.rocketmq.http.groupId=group_dev
aliyun.rocketmq.http.tag=tag_dev

运行测试
image.png
image.png

项目地址

注意: 案例需要配置你自己申请的RocketMQ配置,否则无法启动.

https://github.com/MrCoderStack/SpringBootDemo/tree/master/sb-alibaba-rocketmq

请关注我的订阅号

订阅号.png

SpringBoot整合RocketMQ 实现:RocketMQListener 接口消费消息,通过@RocketMQMessageListener指定consumerGroup,topic,和tags。) 注解标记,监听器需要实现RocketMQLocalTransactionListener 接口 , txProducerGroup 是事务组的名字。通过 @RocketMQTransactionListener(txProducerGroup =生产者增加事务消息发送方法。 阅读详情

相关推荐

Mac使用Docker安装RocketMQ,集成到SpringBoot项目

Docker安装RocketMQ,集成到SpringBoot项目 1、构建rocketmq-docker镜像 步骤一 git clone https://github.com/apache/rocketmq-docker.git 步骤二 选择RocketMQ版本并构建镜像 cd image-build sh build-image.sh RMQ-VERSION BASE-IMAGE # 这里是我使用的是:sh build-image.sh 4.8.0 alpine 通过docker images检验镜

weixin_43549148的博客 1183

SpringBoot框架如何接入RocketMQ?

RocketMQ可以广泛应用于各种场景下的消息传递和通信需求,帮助解决分布式系统中的消息通信、数据同步、事件处理等问题

杨荧的优快云博客 3204

RocketMQ(一):Linux安装RocketMQ和常用命令

下载安装 版本:4.8.0 下载地址:https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.8.0/rocketmq-all-4.8.0-source-release.zip 下载成功后,上传到 /opt 目录,并解压

qq_28834355的博客 1601

Springboot集成RocketMQ——简单使用

Springboot集成RocketMQ,进行简单使用

tang_seven的博客 3497

docker集群部署rocketMQ, springboot整合rocketMQ

1、核心概念说明 2、 docker集群部署rocketMQ (一)、拉取镜像 (二) 、创建2个master server (三) 、创建第1个master broker (四) 、创建第2个master broker (五) 、创建第1个slave broker (六) 、创建第2个slave broker (七)、部署RocketMQ的管理工具 3、 springboot整合rocketMQ...

csweldn520的专栏 531

SpringBoot集成RocketMQ事务消息

`RocketMQ` 事务消息(`Transactional Message`)是指***应用本地事务***和***发送消息操作***可以被***定义到全局事务***中,要么同时成功,要么同时失败。`RocketMQ` 的事务消息提供类似 `X/Open XA` 的分布事务功能,通过事务消息能达到分布式事务的最终一致。

gmHappy 1783

Rocketmq基于docker部署并在Springboot中接入

服务器部署 关于在服务器上安装docker并启动守护进程,这里不再赘述,此处假设服务器已经安装完成docker。 安装并运行nameserver docker run -d -p 9876:9876 -vpwd/data/namesrv/logs:/fddata/rocketmq/logs -vpwd/data/namesrv/store:/fddata/rocketmq/store --name...

weixin_30851867的博客 263

计算机组成原理实验(已通关)-华中科技大学头歌Educoder(Logisim)

汉字国标码转区位码实验 汉字机内码获取实验 8位可控加减法电路设计 第2关 CLA182四位先行进位电路设计 第3关 4位快速加法器设计 第4关 16位快速加法器设计 第5关 32位快速加法器设计 第6关 5位无符号阵列乘法器设计 6位有符号补码阵列乘法器 乘法流水线设计 原码一位乘法器设计 偶校验编码设计 偶校验解码电路设计 16位海明编码电路设计 16位海明解码电路设计 海明编码流水传输实验 16位CRC并行编解码电路设计 CRC编码流水传输实验

紫荆鱼的博客 4万+

springboot基础(48): RocketMQ的安装

安装RocketMQ。

不积跬步,无以至千里 607

一文看懂—Agent多智能体协作

多智能体协作已成为AI应对复杂任务的关键范式,通过模拟人类团队分工,实现专业化、高效化和纠错能力。本文系统阐述了多智能体协作的核心概念(智能体分工、工作流编排、工具使用)、与产品规划的关联(任务拆解、错误处理、组织架构设计),以及典型应用场景(报告生成、客服工单、学习规划)。同时剖析了常见陷阱(循环卡死、信息失真、成本失控)及解决方案,并提供了实用工具模板(角色定义卡、工作流画布、成本仪表盘)。最后通过市场竞品分析和旅行规划两个实战案例,展示了多智能体协作的实际价值。该技术正推动AI从单点智能迈向系统智能,

lee006006的博客 1033

5种隐藏代码到图片的实用技巧:从Notepad++到Linux命令全解析

本文详细解析了5种将代码或文本隐藏到图片中的实用数据隐写技巧。从Notepad++尾部追加、Windows命令行合并,到编辑图像元数据、使用十六进制编辑器,再到Linux的cat/dd命令,全面覆盖了从图形界面到命令行的工程化实践方法,帮助开发者和安全研究人员掌握隐蔽信息传输与存储的核心技术。

hh234的博客 353

Mac下Docker安装RocketMQ,RocketMQ与Springboot整合教程

Mac(M1)下使用Docker配置RocketMQ环境,将RocketMQ和SpringBoot进行整合测试

Miao的博客 2642

ENVI遥感技术

记录2024.03.06所遇到的遥感问题

qq_44453923的博客 4330

【rocketmq】springboot 整合 rocketmq

https://www.cnblogs.com/goodAndyxublog/p/11457164.html

batman 447

【宠物识别系统】设计框架

能跑通的 Demo。收集 10,000 张同品种但不同个体的图片。训练ArcFace模型,验证准确率能否达到 99% 以上。搭建Milvus向量数据库。开发移动端 App/小程序。加入“图像质量检测”和“用户反馈纠错”功能。你是更偏向于做软件服务(如寻宠App、保险API),还是做软硬结合的产品(如智能喂食器)?这决定了我们下一步是深挖云端高并发架构,还是边缘端模型压缩。更偏向于软件,应用更广泛些,继续既然专注于纯软件/SaaS (Software as a Service) 方向。

百态·数智思维 | 聚焦大数据、量化与未来AI 1413

学习stm32H7之路开始(STM32H7系列1) 前期准备,HAL库框架

2020.01.07 几个重要的参考网址 1.电子工程世界网 http://tags.eeworld.com.cn/tags/STM32H7 链接: link. 2.转:https://blog.csdn.net/simon223/article/list/2?t=1 链接: link. ———————————————— 版权声明:本文为优快云博主「Simon223」的原创文章,遵循 CC 4....

kengkengkeng963的博客 3408

RocketMQ 概述

消息中间件(Message Queue,MQ)是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。

Dailyblue的专栏 3687

Carla运行显示The following component(s) are required to run this program:DirectX Runtime |nvapi64.dll没有被

Carla运行显示The following component(s) are required to run this p 参考: 【1】EPIC 启动游戏提示The following component(s) are required to run this program:... - 『悬赏问答区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cnhttps://www.52pojie.cn/thread-1485651-1-1.html ...

anananajiushiwo的博客 5万+

springboot基础(49): 整合RocketMQ

整合RocketMQ。

不积跬步,无以至千里 1641

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

中间件学习-RocketMQ-从零到一学习-3RocketMQ 的动手尝试

RocketMQ 的动手尝试

qq_45477639的博客 1537

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

SpringBoot_rocketmq使用实战_docker环境

记录rocketmq 4.8.0 docker环境安装及springboot集成, 消息功能测试持续集成

Myron_007的博客 1981

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

RocketMQ第一话 -- Docker安装以及Springboot集成RocketMQ

RocketMQ第一话 -- Docker安装以及Springboot集成RocketMQ RocketMQ是一个分布式队列模型的消息中间件,现支持事务消息、顺序消息、批量消息。定时消息RocketMQ由mqnamesrv和mqbroker组成,内部由group、topic、queue共同工作。全局顺序:一个Topic内所有的消息都发布到到同一个Queue按先进先出的顺序进行消费 上一篇:RabbitMQ第三话 – RabbitMQ高可用集群搭建 下一篇:RocketMQ第二话 – RocketMQ事务消息

生生不息,则源源不断 694

RocketMQ内容分享(三):消费者和生产者、SpringBoot集成、Spring Cloud Stream集成

在MySpringcloudRocketmqProducerApplication 添加 @EnableBinding(Source.class) 注解。然后创建生产者。@Component@Resource// 封装消息头// 创建消息对象// 发送消息在MySpringcloudRocketmqConsumerApplication 类上添加 @EnableBinding(Sink.class)注解。@Component。

之乎者也·的博客 2350

SpringBoot整合RocketMQ入门案例

ubuntu环境搭建RocketMQ 我在win10安装一直找不到dt.jar,so只能去linus装了。 RocketMQ官网说这样安装,但是不太行,而且很慢。 自己下载的bin格式文件。最后终于成功。 详细步骤 下载RocketMQ的源码(上图示),并解压缩 unzip rocketmq-all-4.2.0-bin-release.zip 在解压缩的目录中,进入bin目录,视情况修...

weixin_43958091的博客 1044

RocketMQ2环境搭建(Linux)+springboot+netty+rocketmq测试

简介 阿里出品,性能高但可视化页面太low,商用的的话,要求真正的懂她(阿里有商用版,在阿里云可以购买) 集群支持   RocketMQ天生对集群的支持非常友好 单Master: 优点:除了配置简单没什么优点 缺点:不可靠,该机器重启或宕机,将导致整个服务不可用 多Master: 优点:配置简单,性能最高 缺点:可能会有少量消息丢失(配置相关),单台机器重启或宕机期间,该机器下未被消费的消息在机器恢复前不可订阅,影响消息实时性 多Master多Slave异步模式:   每个Maste...

zhuhaoyu6666的博客 874
上一篇: 47. 从零开始学springboot: spel结合redisson实现动态参数分布式锁
下一篇: 摸鱼JVM - 执行引擎
码哥说
博客等级 码龄8年 5645粉丝 172原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码哥说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值