当前位置: 首页 > news >正文

RocketMQ 自动注入消费者

目录

  • 前言
  • 一、情景介绍
  • 二、问题分析
  • 三、代码实现


前言

之前接到一个需求,我们项目的技术负责人希望通过配置的形式,在项目启动的时候自动根据配置生成对应的消费者

觉得还有点意思,随即记录一下~


一、情景介绍

比如我这里有一个消费者 MessageConsumer

@Slf4j
@Service
@RocketMQMessageListener(consumerGroup = "mike-group",topic = "mike-message",selectorExpression = "TAG_MESSAGE_CONSUMER",consumeThreadMax = 6,consumeTimeout = 60L)
public class MessageConsumer implements RocketMQListener<NotifyMessage> {@Overridepublic void onMessage(NotifyMessage notifyMessage) {System.err.println("我收到啦~~");System.err.println("message = " + notifyMessage);}
}

在项目启动的时候会根据 @RocketMQMessageListener 注解上的配置生成一个消费者

假如我还需要一个 MessageConsumer 消费者,其 selectorExpression 的配置为 TAG_MESSAGE_CONSUMER_01consumeThreadMax 要设置为 8

通常情况下我们会再复制一个 MessageConsumer 命名为 MessageConsumer_01,然后在新的消费者上改对应的配置,例如:

@Slf4j
@Service
@RocketMQMessageListener(consumerGroup = "mike-group-01",topic = "mike-message",selectorExpression = "TAG_MESSAGE_CONSUMER_01",consumeThreadMax = 8,consumeTimeout = 60L)
public class MessageConsumer_01 implements RocketMQListener<NotifyMessage> {@Overridepublic void onMessage(NotifyMessage notifyMessage) {System.err.println("我收到啦~~");System.err.println("message = " + notifyMessage);}
}

这样做虽然没啥问题,只是这两个类除了配置不一样,其它的代码都是一摸一样的,倘若之后还要有一个 selectorExpression = TAG_MESSAGE_CONSUMER_02 的消费者,那我又得再复制一个 MessageConsumer,这样就造成了大量的代码冗余

所以就希望通过读取配置文件生成对应配置的消费者


二、问题分析

要如何实现这个功能,可以去看下 RocketMQ 的源码,看 Spring 是如何创建 RocketMQ 的消费者的

源码如下:

org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer#initRocketMQPushConsumer

在这里插入图片描述

在该方法中可以看到 Spring 是如何初始化消费者,参照这个方法,只需要在项目启动完成后,将初始化从注解上获取消费者配置的地方换成从配置文件上获取就可以了

通过实现 ApplicationListener<ApplicationReadyEvent> 可以监听项目是否启动完成


三、代码实现

因为消费者是需要通过配置文件的配置来自动生成,那么可以将需要自动生成的消费者(比如 MessageConsumer)其 @RocketMQMessageListener 的配置注释掉

@Slf4j
@Service
//@RocketMQMessageListener(
//        consumerGroup = "mike-group",
//        topic = "mike-message",
//        selectorExpression = "TAG_MESSAGE_CONSUMER",
//        consumeThreadMax = 6,
//        consumeTimeout = 60L)
public class MessageConsumer implements RocketMQListener<NotifyMessage> {@Overridepublic void onMessage(NotifyMessage notifyMessage) {System.err.println("我收到啦~~");System.err.println("message = " + notifyMessage);}
}

配置文件上自动注入消费者的配置最好和 @RocketMQMessageListener 的属性相同,并且可以配置多个自动注入的消费者,那么对应的映射文件可以这么写

AutoConsumerProperties.java

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;import java.util.List;@Data
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "auto-consumer")
public class AutoConsumerProperties {private List<AutoConsumer> messageConsumer;
}

AutoConsumer.java

import lombok.Data;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.SelectorType;@Data
public class AutoConsumer {private String consumerGroup;private String topic;private SelectorType selectorType = SelectorType.TAG;private String selectorExpression = "*";private ConsumeMode consumeMode = ConsumeMode.CONCURRENTLY;private MessageModel messageModel = MessageModel.CLUSTERING;private int consumeThreadMin = 64;private int consumeThreadMax = 64;private long consumeTimeout = 15L;private String accessKey;private String secretKey;private boolean enableMsgTrace;private String customizedTraceTopic;private String nameServer;private String accessChannel;
}

核心代码:

ConsumerStarted.java

import cn.hutool.core.collection.CollUtil;
import com.mike.common.core.utils.JacksonUtil;
import com.mike.server.message.config.properties.AutoConsumer;
import com.mike.server.message.config.properties.AutoConsumerProperties;
import com.mike.server.message.consumer.MessageConsumer;
import com.mike.server.message.domain.entity.NotifyMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.AccessChannel;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.MessageSelector;
import org.apache.rocketmq.client.consumer.listener.*;
import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.support.RocketMQUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;@Slf4j
@Component
public class ConsumerStarted implements ApplicationContextAware, ApplicationListener<ApplicationReadyEvent> /* , InitializingBean, SmartLifecycle */ {@Value("${rocketmq.name-server:}")private String nameServer;@Value("${rocketmq.consumer.topic:}")private String topic;@Value("${rocketmq.consumer.access-key:}")private String accessKey;@Value("${rocketmq.consumer.secret-key:}")private String secretKey;@Resourceprivate AutoConsumerProperties autoConsumerProperties;@Resourceprivate MessageConsumer messageConsumer;private ApplicationContext applicationContext;private final static boolean enableMsgTrace = true;private final static String customizedTraceTopic = null;@Override@SuppressWarnings("all")public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {// 需要等到程序启动完全之后再去启动initConsumer();}public void initConsumer() {List<AutoConsumer> messageConsumers = autoConsumerProperties.getMessageConsumer();if (CollUtil.isEmpty(messageConsumers)) return;final RocketMQListener<NotifyMessage> messageConsumerListener = messageConsumer;this.autoGenerateConsumer(messageConsumers, messageConsumerListener, NotifyMessage.class);}@SuppressWarnings("all")private <R> void autoGenerateConsumer(List<AutoConsumer> autoConsumers, RocketMQListener<R> rocketMQListener, Class<R> objClass) {// 根据 tag 自动生成对应的消费者for (AutoConsumer autoConsumer : autoConsumers) {String consumerGroup = autoConsumer.getConsumerGroup();String nameServer = getValueOrDefault(autoConsumer.getNameServer(), this.nameServer);String topic = getValueOrDefault(autoConsumer.getTopic(), this.topic);String accessKey = getValueOrDefault(autoConsumer.getAccessKey(), this.accessKey);String secretKey = getValueOrDefault(autoConsumer.getSecretKey(), this.secretKey);try {Assert.notNull(consumerGroup, "Property 'consumerGroup' is required");Assert.notNull(nameServer, "Property 'nameServer' is required");Assert.notNull(topic, "Property 'topic' is required");DefaultMQPushConsumer consumer;RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(this.applicationContext.getEnvironment(), accessKey, secretKey);if (Objects.nonNull(rpcHook)) {consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, new AllocateMessageQueueAveragely(), enableMsgTrace, customizedTraceTopic);consumer.setVipChannelEnabled(false);} else {consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, customizedTraceTopic);}consumer.setInstanceName(RocketMQUtil.getInstanceName(this.nameServer));consumer.setNamesrvAddr(this.nameServer);consumer.setAccessChannel(AccessChannel.LOCAL);consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);consumer.setConsumeThreadMin(autoConsumer.getConsumeThreadMin());consumer.setConsumeThreadMax(autoConsumer.getConsumeThreadMax());if (consumer.getConsumeThreadMax() < consumer.getConsumeThreadMin()) {consumer.setConsumeThreadMin(consumer.getConsumeThreadMax());}switch (autoConsumer.getMessageModel()) {case BROADCASTING:consumer.setMessageModel(MessageModel.BROADCASTING);break;case CLUSTERING:consumer.setMessageModel(MessageModel.CLUSTERING);break;default:throw new IllegalArgumentException("Property 'messageModel' was wrong.");}switch (autoConsumer.getSelectorType()) {case TAG:consumer.subscribe(topic, autoConsumer.getSelectorExpression());break;case SQL92:consumer.subscribe(topic, MessageSelector.bySql(autoConsumer.getSelectorExpression()));break;default:throw new IllegalArgumentException("Property 'selectorType' was wrong.");}switch (autoConsumer.getConsumeMode()) {case ORDERLY:consumer.setMessageListener(new DefaultMessageListenerOrderly(autoConsumer, rocketMQListener, objClass));break;case CONCURRENTLY:consumer.setMessageListener(new DefaultMessageListenerConcurrently(autoConsumer, rocketMQListener, objClass));break;default:throw new IllegalArgumentException("Property 'consumeMode' was wrong.");}consumer.start();log.info("Consumer Start Success: {}:{}", topic, autoConsumer.getSelectorExpression());} catch (MQClientException e) {e.printStackTrace();log.info("Consumer Start Failed: {}:{}", topic, autoConsumer.getSelectorExpression());}}}private String getValueOrDefault(String value, String defaultValue) {return StringUtils.isNotBlank(value)? value: defaultValue;}@Override@SuppressWarnings("all")public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public class DefaultMessageListenerOrderly<T> implements MessageListenerOrderly {private final AutoConsumer autoConsumer;private final RocketMQListener<T> rocketMQListener;private final Class<T> objClass;public DefaultMessageListenerOrderly(AutoConsumer autoConsumer, RocketMQListener<T> rocketMQListener, Class<T> objClass) {this.autoConsumer = autoConsumer;this.rocketMQListener = rocketMQListener;this.objClass = objClass;}public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgList, ConsumeOrderlyContext context) {for (MessageExt messageExt : msgList) {log.info("group[{}]-tag[{}] consume start ->>>", autoConsumer.getConsumerGroup(), autoConsumer.getSelectorExpression());log.debug("received msg: {}", messageExt);try {long now = System.currentTimeMillis();this.rocketMQListener.onMessage(doConvertMessage(messageExt, this.objClass));long costTime = System.currentTimeMillis() - now;log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime);} catch (Exception var9) {log.warn("consume message failed. messageId:{}, topic:{}, reconsumeTimes:{}", messageExt.getMsgId(), messageExt.getTopic(), messageExt.getReconsumeTimes(), var9);final long suspendCurrentQueueTimeMillis = 1000L;context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis);return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;}}return ConsumeOrderlyStatus.SUCCESS;}}public class DefaultMessageListenerConcurrently <T> implements MessageListenerConcurrently {private final AutoConsumer autoConsumer;private final RocketMQListener<T> rocketMQListener;private final Class<T> objClass;public DefaultMessageListenerConcurrently(AutoConsumer autoConsumer, RocketMQListener<T> rocketMQListener, Class<T> objClass) {this.autoConsumer = autoConsumer;this.rocketMQListener = rocketMQListener;this.objClass = objClass;}public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgList, ConsumeConcurrentlyContext context) {for (MessageExt messageExt : msgList) {log.info("group[{}]-tag[{}] consume start ->>>", autoConsumer.getConsumerGroup(), autoConsumer.getSelectorExpression());log.debug("received msg: {}", messageExt);try {long now = System.currentTimeMillis();this.rocketMQListener.onMessage(doConvertMessage(messageExt, objClass));long costTime = System.currentTimeMillis() - now;log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime);} catch (Exception var9) {log.warn("consume message failed. messageId:{}, topic:{}, reconsumeTimes:{}", messageExt.getMsgId(), messageExt.getTopic(), messageExt.getReconsumeTimes(), var9);final int delayLevelWhenNextConsume = 0;context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume);return ConsumeConcurrentlyStatus.RECONSUME_LATER;}}return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}}@SuppressWarnings("unchecked")private <T> T doConvertMessage(MessageExt messageExt, Class<T> objClass) {if (Objects.equals(objClass, MessageExt.class)) {return (T)messageExt;} else {String str = new String(messageExt.getBody(), StandardCharsets.UTF_8);if (Objects.equals(objClass, String.class)) {return (T)str;} else {if (objClass != null) {return JacksonUtil.fromJson(str, objClass);} else {log.info("convert failed. str:{}, msgType:{}", str, null);throw new RuntimeException("cannot convert message to " + null);}}}}
}

配置文件 yml 新增自动注入消费者的配置

auto-consumer:message-consumer:- consumer-group: mico-grouptopic: mike-messageselector-expression: TAG_MESSAGE_CONSUMERconsume-thread-max: 6- consumer-group: mike-group-01topic: mike-messageselector-expression: TAG_MESSAGE_CONSUMER_01consume-thread-max: 8- consumer-group: mike-group-02topic: mike-messageselector-expression: TAG_MESSAGE_CONSUMER_02consume-thread-max: 10

如果是配置在 properties 文件中,配置如下:

auto-consumer.message-consumer[0].consumer-group = mico-group
auto-consumer.message-consumer[0].topic = mike-message
auto-consumer.message-consumer[0].selector-expression = TAG_MESSAGE_CONSUMER
auto-consumer.message-consumer[0].consume-thread-max = 6auto-consumer.message-consumer[1].consumer-group = mico-group-01
auto-consumer.message-consumer[1].topic = mike-message
auto-consumer.message-consumer[1].selector-expression = TAG_MESSAGE_CONSUMER_01
auto-consumer.message-consumer[1].consume-thread-max = 8auto-consumer.message-consumer[2].consumer-group = mico-group-02
auto-consumer.message-consumer[2].topic = mike-message
auto-consumer.message-consumer[2].selector-expression = TAG_MESSAGE_CONSUMER_02
auto-consumer.message-consumer[2].consume-thread-max = 10

启动项目进行验证,观察是否有三个消费者被创建

在这里插入图片描述

从日志上看确实根据配置文件自动创建了三个不同的消费者

相关文章:

RocketMQ 自动注入消费者

目录 前言一、情景介绍二、问题分析三、代码实现 前言 之前接到一个需求&#xff0c;我们项目的技术负责人希望通过配置的形式&#xff0c;在项目启动的时候自动根据配置生成对应的消费者 觉得还有点意思&#xff0c;随即记录一下~ 一、情景介绍 比如我这里有一个消费者 Mes…...

RibbitMQ-安装

本文主要介绍RibbitMQ的安装 RabbitMQ依赖于Erlang&#xff0c;因此首先需要安装Erlang环境。分别下载erlang-26.2.5-1.el7.x86_64.rpm、rabbitmq-server-4.0.3-1.el8.noarch.rpm 官网地址&#xff1a;https://www.rabbitmq.com/ 官网文档&#xff1a;https://www.rabbitmq.c…...

非计算机背景但是想从事医学AI研究,需要掌握的编程语言|个人观点·24-11-08

小罗碎碎念 目前&#xff0c;我们从事医学AI研究的&#xff0c;接触的最多的两种编程语言应该就是R和Python了。那么初学者很容易提出一个疑问&#xff0c;**我想从事医学AI相关的研究的话&#xff0c;应该学哪些编程语言呢&#xff1f;**在文章的开头&#xff0c;我可以先给出…...

内置函数【MySQL】

文章目录 日期函数字符串函数数学函数其他函数 日期函数 current_date函数用于获取当前的日期 mysql> select current_date(); ---------------- | current_date() | ---------------- | 2024-11-03 | ---------------- 1 row in set (0.00 sec)current_time函数用于获…...

RNA-seq 差异分析的点点滴滴(1)

引言 本系列[1])将开展全新的转录组分析专栏&#xff0c;主要针对使用DESeq2时可能出现的问题和方法进行展开。 为何使用未经标准化的计数数据&#xff1f; DESeq2 工具包在接收输入时&#xff0c;期望得到的是未经处理的原始计数数据&#xff0c;比如从 RNA-seq 或其他高通量测…...

Windows10/11开启卓越性能模式 windows开启卓越性能电源模式 工作电脑开启卓越性能模式 电脑开启性能模式

Windows10/11开启卓越性能模式 windows开启卓越性能电源模式 工作电脑开启卓越性能模式 电脑开启性能模式 1、所要用到的激活工具2、开启电脑卓越性能模式Windows11Windows10在电源模式中选择卓越性能模式 3、将系统版本切换为 工作站版本 1、所要用到的激活工具 KMS激活工具(…...

day20-21之间的项目实战:若依ruoyi开发(可以跳过)

一&#xff0c;项目概述 官网文档地址&#xff1a;http://doc.ruoyi.vip/ rouyi是一个后台管理系统&#xff0c;基于经典技术组合&#xff08;spring boot&#xff0c;apache shiro&#xff0c;mybatis&#xff0c;thymeleaf&#xff09;主要是让开发者注重专注业务&#xff0…...

双向链表及如何使用GLib的GList实现双向链表

双向链表是一种比单向链表更为灵活的数据结构&#xff0c;与单向链表相比可以有更多的应用场景&#xff0c;本文讨论双向链表的基本概念及实现方法&#xff0c;并着重介绍使用GLib的GList实现单向链表的方法及步骤&#xff0c;本文给出了多个实际范例源代码&#xff0c;旨在帮助…...

ProCalun卡伦纯天然万用膏,全家的皮肤健康守护

受季节交替、生活环境变化、空气污染等方面因素的影响&#xff0c;加上作息不规律导致的免疫力降低&#xff0c;我们或多或少会出现一些如湿疹、痤疮、瘙痒之类的皮肤问题&#xff0c;且反复概率很高。很多人盲目用药&#xff0c;甚至诱发激素依赖性皮炎。所以近年来&#xff0…...

FastAPI全方位分析:优劣尽显

近年来,随着技术的飞速发展,快速构建高性能API的需求越来越强烈。Python作为一个广泛使用的编程语言,也在这一领域下涌现出了许多优秀的框架。FastAPI便是其中一颗璀璨的新星。 FastAPI以其卓越的性能和独特的功能吸引了众多开发者。本文将深入剖析FastAPI的各个方面,详细…...

【rust】rust基础代码案例

文章目录 代码篇HelloWorld斐波那契数列计算表达式&#xff08;加减乘除&#xff09;web接口 优化篇target/目录占用一个g&#xff0c;仅仅一个actix的helloWorld demo升级rust版本&#xff0c; 通过rustupcargo换源windows下放弃吧&#xff0c;需要额外安装1g的toolchain并且要…...

【深度学习】PromptFix:多功能AI修图

PromptFix:你来提示,我们修图 NeurIPS 2024 最近,在计算机视觉和图像处理领域,一个名为PromptFix的新项目引起了广泛关注。PromptFix是一个基于PyTorch实现的开源项目,旨在根据用户的自然语言指令,对受损或需要处理的图像进行智能修复和优化。 本文将详细介绍PromptFix…...

2024最新AI绘画系统软件(Midjourney)+GPT4文档分析总结,多模态识图理解,AI文生图/图生图/混图生图(图像混合)

一、前言 人工智能的快速发展已成为全球关注的焦点&#xff0c;其应用领域广泛&#xff0c;涵盖绘图、语言处理、视频编辑等。前沿技术不仅推动科技创新&#xff0c;还在艺术创作、内容生产和商业实践等方面展示出巨大潜力。例如&#xff0c;AI语言模型显著提升了内容自动生成、…...

【信号处理】基于联合图像表示的深度学习卷积神经网络

Combined Signal Representations for Modulation Classification Using Deep Learning: Ambiguity Function, Constellation Diagram, and Eye Diagram 信号表示 Ambiguity Function(AF) 模糊函数描述了信号的两个维度(dimensions):延迟(delay)和多普勒(Doppler)。 …...

C#基础-区分数组与集合

目录 区分数组与集合 1.定义 1&#xff09;数组 2&#xff09;集合 2.大小 1&#xff09;数组 2&#xff09;集合 3.访问速度 1&#xff09;数组 2&#xff09;集合 4.内存管理 1&#xff09;数组 2&#xff09;集合 5.使用场景 1&#xff09;数组 2&#xff0…...

ORACLE 19C 安装数据库补丁的详细过程

ORACLE 19c安装DB补丁&#xff1a; 1 确定OPatch的可用性&#xff1a;这里需要注意的是p6880880_190000_Linux-x86-64.zip是有版本对应区别的&#xff0c;需要注意你要打的补丁版本是否支持。 2 将原$ORACLE_HOME目录下的OPatch目录删除或者改名&#xff0c;比如说&#xff1a…...

tensorflow案例5--基于改进VGG16模型的马铃薯识别,准确率提升0.6%,计算量降低78.07%

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次采用VGG16模型进行预测&#xff0c;准确率达到了98.875&#xff0c;但是修改VGG16网络结构&#xff0c; 准确率达到了0.9969&#xff0c;并且计算量…...

代码中的设计模式-策略模式

假如我们有一段代码,有很多的if else function executeAction(type) {if (type A) {console.log(Action A);} else if (type B) {console.log(Action B);} else if (type C) {console.log(Action C);} else {console.log(Unknown action);} }executeAction(A); // 输出: Ac…...

后端Node学习项目-项目基础搭建

前言 各位好&#xff0c;我是前端SkyRain。最近为了响应公司号召&#xff0c;开始对后端知识的学习&#xff0c;作为纯粹小白&#xff0c;记录下每一步的操作流程。 项目仓库&#xff1a;https://gitee.com/sky-rain-drht/drht-node 因为写了文档&#xff0c;代码里注释不是很…...

Python | Leetcode Python题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; class Solution:def convertBST(self, root: TreeNode) -> TreeNode:def getSuccessor(node: TreeNode) -> TreeNode:succ node.rightwhile succ.left and succ.left ! node:succ succ.leftreturn succtotal 0node rootwhile nod…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...