RabbitMQ死信队列原理与SpringBoot实战:消息不丢失的终极方案
1. 死信队列到底在解决什么问题1.1 从一次线上事故说起消息中间件用久了早晚会碰到一类让人头疼的场景消息明明发出去了消费者那边却迟迟没有动静既没有成功回执也没有失败记录就这么悬在半空中。更麻烦的是有些消息反复投递多次每次都在同一个环节卡住像卡了带的录音机循环往复地消耗着系统资源。我最早接触死信队列就是因为一个订单超时未支付的场景。当时的设计很简单订单创建后往消息队列里丢一条延迟消息到点后消费者检查订单状态如果还是未支付就自动关闭。逻辑本身没毛病但上线后陆续出现了一些“幽灵订单”——状态一直停在待支付既没关闭也没支付查日志发现消息确实被消费了但消费过程中抛了异常而异常又被吞掉了消息就这么无声无息地消失了。这个问题逼着我去研究 RabbitMQ 的死信机制。说白了死信队列就是给那些“正常路径走不通”的消息准备的一个收容所。消息在队列里待着如果因为某些原因无法被正常消费它不应该被随意丢弃而应该被转到一个专门的地方让开发者能够看到、分析、处理。这个专门的地方就是死信队列。1.2 死信队列的核心价值很多人第一次听到“死信”这个词会觉得它是个很高级、很复杂的东西。其实拆开来看它的本质非常朴素一个普通的队列通过绑定特定的交换机接收那些从其他队列“退回来”的消息。它本身没有任何特殊能力特殊的是消息进入它的方式。死信队列解决的核心问题可以归纳为三个层面。第一是消息不丢失那些消费失败、过期、被拒绝的消息不会凭空消失而是有了一个明确的去处。第二是问题可追溯开发人员可以通过监控死信队列快速定位哪些消息出了问题、问题出在哪个环节。第三是系统可恢复死信队列里的消息可以被重新处理比如人工介入修复后重新投递或者由专门的补偿服务自动重试。在实际项目中死信队列往往和延迟队列、重试机制配合使用。比如用户下单后 30 分钟未支付消息进入死信队列触发关单逻辑又比如某个服务临时不可用消息消费失败后进入死信队列等服务恢复后再重新消费。这些场景背后都是同一套机制在支撑。1.3 适合哪些人阅读这篇内容主要面向已经用过 RabbitMQ 基础功能、但对死信队列还停留在“听说过”阶段的开发者。如果你正在设计订单超时、支付回调、异步通知这类对消息可靠性要求较高的业务死信队列几乎是绕不开的一环。即使你目前用的是其他消息中间件死信的核心思想也是相通的理解之后可以迁移到类似的设计中。接下来的内容会从原理讲起然后一步步搭建一个可运行的示例最后分享一些我在实际项目中踩过的坑和总结的经验。代码部分基于 SpringBoot 和 RabbitMQ 的常规整合方式不会涉及过于冷门的配置确保你跟着做就能跑通。2. 死信的产生条件与底层原理2.1 消息变成死信的三种典型情况消息不会无缘无故变成死信RabbitMQ 对“死信”的定义非常明确只有满足以下条件之一的消息才会被投递到死信交换机第一种是消息被拒绝。消费者在消费消息时调用了basicNack或basicReject方法并且把requeue参数设置为false。这个操作相当于告诉 RabbitMQ“这条消息我不要了也别再放回原队列了。”消息被拒绝后如果队列配置了死信交换机它就会被路由过去。第二种是消息过期。队列可以设置消息的 TTLTime To Live也就是消息在队列中的最大存活时间。如果一条消息在队列里待的时间超过了这个阈值还没有被消费它就会变成死信。这里有个细节需要注意TTL 可以设置在队列级别也可以设置在消息级别两者的行为略有不同后面会详细说。第三种是队列达到最大长度。当队列中堆积的消息数量超过设定的最大长度时最早进入队列的消息会被挤出去。如果队列配置了死信交换机这些被挤出去的消息就会进入死信队列而不是被直接丢弃。这三种情况覆盖了绝大多数死信产生的场景。在实际业务中消息过期和消息被拒绝是最常见的两种。比如延迟队列的实现本质上就是利用消息过期后进入死信队列来触发后续逻辑。2.2 死信交换机与死信路由键死信队列并不是一个独立的队列类型它就是一个普通的队列只不过是通过死信交换机绑定过来的。在声明业务队列时需要额外指定两个参数x-dead-letter-exchange和x-dead-letter-routing-key。x-dead-letter-exchange指定死信要发送到哪个交换机。这个交换机可以是任何类型的交换机通常是 Direct 类型因为死信的路由键往往是固定的。x-dead-letter-routing-key则指定死信被转发时使用的路由键。如果不设置这个参数消息会保留原来的路由键。这里有一个容易混淆的点死信交换机本身并不存储消息它只负责路由。真正存储死信的是绑定到死信交换机上的队列。所以完整的链路是业务队列中的消息变成死信后被发送到死信交换机死信交换机根据路由键把消息投递到死信队列消费者再从死信队列中消费。2.3 消息 TTL 的两种设置方式消息过期是产生死信最常见的原因之一而 TTL 的设置方式直接影响到死信的行为。RabbitMQ 支持两种粒度的 TTL 设置队列级别的 TTL在声明队列时通过x-message-ttl参数设置单位是毫秒。这个队列中所有消息都遵循同一个过期时间。一旦消息在队列中停留超过这个时间就会变成死信。这种方式的好处是统一管理缺点是缺乏灵活性所有消息的过期时间都一样。消息级别的 TTL在发送消息时通过消息属性设置过期时间。每条消息可以有不同的 TTL。但这里有一个非常重要的坑RabbitMQ 队列中的消息是顺序存储的只会检查队首消息是否过期。如果队首消息的 TTL 很长即使后面的消息 TTL 很短也不会被优先处理。这意味着消息级别的 TTL 在队列中可能会出现“过期不消失”的情况直到它成为队首。我在实际项目中更倾向于使用队列级别的 TTL因为行为更可预测。如果确实需要不同的过期时间通常会声明多个队列每个队列设置不同的 TTL而不是依赖消息级别的 TTL。2.4 死信消息的头部信息当消息变成死信后RabbitMQ 会在消息的头部添加一些额外的信息方便开发者排查问题。这些头部信息包括x-death一个数组记录了消息变成死信的原因和次数。每个元素包含reason原因如expired、rejected、maxlen、queue原队列名称、time变成死信的时间等字段。x-first-death-reason消息第一次变成死信的原因。x-first-death-queue消息第一次变成死信时所在的队列。x-first-death-exchange消息第一次变成死信时所在的交换机。这些头部信息在排查问题时非常有用。比如你可以通过x-death数组的长度判断消息被重试了多少次通过reason字段判断是过期还是被拒绝。在编写死信消费者时建议把这些信息记录下来方便后续分析。3. SpringBoot 整合死信队列的完整实现3.1 项目依赖与基础配置先确保项目中引入了 RabbitMQ 的 SpringBoot 起步依赖。在pom.xml中添加dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-amqp/artifactId /dependency然后在application.yml中配置 RabbitMQ 的连接信息spring: rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / listener: simple: acknowledge-mode: manual prefetch: 1这里有几个关键配置需要说明。acknowledge-mode设置为manual表示手动确认这是使用死信队列时推荐的方式因为只有手动确认才能精确控制消息何时被拒绝。prefetch设置为 1 表示每次只预取一条消息避免消息在消费者端堆积过多导致处理不及时。3.2 声明交换机、队列与绑定关系接下来通过 Java 配置类声明业务队列、死信交换机、死信队列以及它们之间的绑定关系。这是整个死信机制的核心配置Configuration public class RabbitMQConfig { // 业务交换机 public static final String BUSINESS_EXCHANGE business.exchange; // 业务队列 public static final String BUSINESS_QUEUE business.queue; // 业务路由键 public static final String BUSINESS_ROUTING_KEY business.routing.key; // 死信交换机 public static final String DEAD_LETTER_EXCHANGE dead.letter.exchange; // 死信队列 public static final String DEAD_LETTER_QUEUE dead.letter.queue; // 死信路由键 public static final String DEAD_LETTER_ROUTING_KEY dead.letter.routing.key; Bean public DirectExchange businessExchange() { return new DirectExchange(BUSINESS_EXCHANGE, true, false); } Bean public Queue businessQueue() { return QueueBuilder.durable(BUSINESS_QUEUE) .withArgument(x-dead-letter-exchange, DEAD_LETTER_EXCHANGE) .withArgument(x-dead-letter-routing-key, DEAD_LETTER_ROUTING_KEY) .withArgument(x-message-ttl, 10000) .withArgument(x-max-length, 1000) .build(); } Bean public Binding businessBinding() { return BindingBuilder.bind(businessQueue()) .to(businessExchange()) .with(BUSINESS_ROUTING_KEY); } Bean public DirectExchange deadLetterExchange() { return new DirectExchange(DEAD_LETTER_EXCHANGE, true, false); } Bean public Queue deadLetterQueue() { return QueueBuilder.durable(DEAD_LETTER_QUEUE).build(); } Bean public Binding deadLetterBinding() { return BindingBuilder.bind(deadLetterQueue()) .to(deadLetterExchange()) .with(DEAD_LETTER_ROUTING_KEY); } }这段配置里业务队列设置了三个关键参数x-dead-letter-exchange指定死信交换机x-dead-letter-routing-key指定死信路由键x-message-ttl设置消息过期时间为 10 秒x-max-length设置队列最大长度为 1000 条。当消息过期或被挤出去时就会自动进入死信队列。注意x-message-ttl和x-max-length不是必须的你可以根据业务需要选择是否设置。如果只关心消费失败的消息可以只配置死信交换机不设置 TTL 和最大长度。3.3 消息生产者与消费者代码生产者负责往业务交换机发送消息Service public class MessageProducer { Autowired private RabbitTemplate rabbitTemplate; public void sendMessage(String message) { rabbitTemplate.convertAndSend( RabbitMQConfig.BUSINESS_EXCHANGE, RabbitMQConfig.BUSINESS_ROUTING_KEY, message ); System.out.println(发送消息 message); } }消费者监听业务队列并模拟消费失败的情况Component public class BusinessConsumer { RabbitListener(queues RabbitMQConfig.BUSINESS_QUEUE) public void handleMessage(String message, Channel channel, Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException { try { System.out.println(收到业务消息 message); // 模拟业务处理 if (message.contains(error)) { throw new RuntimeException(模拟业务异常); } // 手动确认 channel.basicAck(deliveryTag, false); } catch (Exception e) { System.err.println(消费失败 e.getMessage()); // 拒绝消息不重新入队进入死信队列 channel.basicNack(deliveryTag, false, false); } } }这里的关键在于basicNack方法的第三个参数requeue设置为false。如果设置为true消息会被重新放回原队列而不是进入死信队列。很多初学者在这里踩坑发现消息一直循环消费就是因为requeue设置成了true。死信消费者负责处理进入死信队列的消息Component public class DeadLetterConsumer { RabbitListener(queues RabbitMQConfig.DEAD_LETTER_QUEUE) public void handleDeadLetter(String message, Channel channel, Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Header(name x-death, required false) ListMapString, Object xDeath) throws IOException { try { System.out.println(收到死信消息 message); if (xDeath ! null !xDeath.isEmpty()) { MapString, Object deathInfo xDeath.get(0); System.out.println(死信原因 deathInfo.get(reason)); System.out.println(原队列 deathInfo.get(queue)); System.out.println(死信时间 deathInfo.get(time)); } // 这里可以进行人工处理、记录日志、发送告警等 channel.basicAck(deliveryTag, false); } catch (Exception e) { // 死信队列的消息一般不再拒绝避免无限循环 channel.basicNack(deliveryTag, false, false); } } }死信消费者中获取了x-death头部信息可以清楚地看到消息变成死信的原因、原队列和时间。这些信息对于排查问题非常有价值。3.4 测试与验证写一个简单的测试接口来验证整个流程RestController public class TestController { Autowired private MessageProducer producer; GetMapping(/send) public String send(RequestParam String msg) { producer.sendMessage(msg); return 发送成功 msg; } }启动项目后访问http://localhost:8080/send?msghello消息会正常进入业务队列并被消费。访问http://localhost:8080/send?msgerror消息会消费失败并进入死信队列。访问http://localhost:8080/send?msgtimeout消息会在 10 秒后过期进入死信队列。通过 RabbitMQ 的管理界面可以清楚地看到消息的流转过程。业务队列中的消息在消费失败或过期后会出现在死信队列中死信队列的消费者会打印出详细的死信信息。4. 实际项目中的常见问题与排查技巧4.1 消息没有进入死信队列的排查思路这是最常见的问题之一。消息明明消费失败了但死信队列里空空如也。排查时按照以下顺序检查第一检查队列是否配置了死信交换机。如果队列声明时没有设置x-dead-letter-exchange参数消息变成死信后会被直接丢弃。可以通过 RabbitMQ 管理界面查看队列的参数确认x-dead-letter-exchange是否存在。第二检查requeue参数。如果消费者调用basicNack时把requeue设置为true消息会重新回到原队列而不是进入死信队列。这是最容易忽略的一点。第三检查死信交换机和死信队列的绑定关系。死信交换机必须和死信队列正确绑定并且路由键要匹配。如果路由键不匹配消息会被死信交换机丢弃。第四检查消息是否真的变成了死信。如果消息被正常消费并确认了自然不会进入死信队列。可以在消费者中打印日志确认消息的处理状态。4.2 消息重复消费与幂等处理死信队列的消息被重新消费时可能会出现重复消费的情况。比如消息因为网络抖动被拒绝进入死信队列但业务实际上已经处理成功了重新消费就会导致重复处理。解决这个问题的核心是幂等设计。常见的做法包括在数据库中为每条消息记录一个唯一 ID消费前先检查该 ID 是否已经处理过或者使用 Redis 的setnx命令做去重又或者在业务层面设计成天然幂等的操作比如更新操作而不是插入操作。我在项目中通常会在消息发送时生成一个全局唯一的消息 ID消费者处理前先查一下这个 ID 是否存在于处理记录表中。如果存在就直接确认不再重复处理。这个方案虽然增加了一次数据库查询但对于保证数据一致性来说非常值得。4.3 死信队列消息堆积的处理死信队列的消息如果长期不处理会越积越多最终可能导致磁盘告警。处理死信消息有几种策略人工介入对于重要的业务消息可以开发一个管理后台让运营人员查看死信消息并手动处理。这种方式适合消息量不大、但每条消息都很重要的场景。自动重试对于临时性故障导致的消息失败可以设置一个定时任务定期从死信队列中拉取消息重新投递到业务队列。但要注意设置重试次数上限避免无限循环。记录归档对于确认无法处理的消息可以将其记录到数据库或日志文件中然后从死信队列中移除。这样既保留了问题现场又不会让队列无限膨胀。告警通知当死信队列的消息数量超过阈值时触发告警通知开发人员。这是最基本的监控手段建议一定要配置。4.4 死信队列的监控指标在生产环境中死信队列需要重点监控以下几个指标指标名称说明建议阈值死信队列消息数当前堆积的死信消息数量超过 100 条告警死信消息增长率单位时间内新增的死信消息数突然飙升时告警死信消费失败率死信消费者处理失败的比例超过 5% 告警死信消息年龄最早一条死信消息的存活时间超过 24 小时告警这些指标可以通过 RabbitMQ 的 HTTP API 获取然后接入到现有的监控系统中。我一般会用定时任务每分钟拉取一次数据推送到监控平台配置好告警规则。4.5 一个容易被忽略的坑死信队列的 TTL如果给死信队列也设置了 TTL那么死信消息在死信队列中过期后会再次变成死信。如果死信队列没有配置死信交换机消息就会被丢弃。这个行为有时候会让人困惑明明消息进了死信队列怎么又不见了我的建议是死信队列一般不要设置 TTL让它作为消息的最终归宿。如果确实需要控制死信消息的存活时间可以设置一个较长的 TTL并且给死信队列也配置死信交换机形成一个最终的“兜底队列”。但这样层层嵌套会让系统变得复杂大多数场景下没必要这么做。4.6 死信消息的重新投递有时候我们希望把死信队列中的消息重新投递回业务队列比如服务恢复后重新处理之前失败的消息。实现方式有两种一种是手动编写代码从死信队列中消费消息然后通过RabbitTemplate重新发送到业务交换机。这种方式灵活可控可以在重新投递前做一些处理比如修改消息内容、增加重试次数标记等。另一种是利用 RabbitMQ 的 Shovel 插件配置一个从死信队列到业务交换机的搬运任务。这种方式不需要写代码但灵活性较差适合简单的重新投递场景。我在项目中更倾向于第一种方式因为可以在重新投递时加入更多的控制逻辑比如判断重试次数是否超过上限、是否需要修改消息内容等。5. 死信队列的进阶用法与设计建议5.1 结合延迟队列实现定时任务死信队列最经典的进阶用法就是实现延迟队列。RabbitMQ 本身没有直接提供延迟队列的功能但通过 TTL 加死信队列的组合可以完美模拟出延迟效果。具体做法是声明一个没有消费者的队列设置x-message-ttl为延迟时间并配置死信交换机。消息发送到这个队列后不会有人消费等 TTL 到期后自动变成死信进入死信队列。死信队列的消费者再执行真正的业务逻辑。这个方案的好处是不需要引入额外的组件利用 RabbitMQ 自身的能力就能实现。但有一个限制延迟时间是固定的由队列的 TTL 决定。如果需要不同的延迟时间就得声明多个队列每个队列设置不同的 TTL。这在延迟时间种类不多的场景下是可行的但如果延迟时间很灵活就不太适合了。5.2 死信队列的命名规范在项目中死信队列的命名最好遵循一定的规范方便识别和管理。我通常采用这样的命名方式业务队列{业务名}.queue业务交换机{业务名}.exchange死信队列{业务名}.dlq死信交换机{业务名}.dlx其中dlq是 Dead Letter Queue 的缩写dlx是 Dead Letter Exchange 的缩写。这样命名一眼就能看出队列的用途在管理界面中也能快速找到对应的死信队列。5.3 死信消息的告警策略死信队列的消息不应该被静默处理而应该触发告警。我的做法是在死信消费者中判断消息的重要程度对于关键业务消息直接发送告警通知对于非关键消息记录日志并定期汇总。告警的渠道可以根据团队的习惯选择比如邮件、企业通讯工具、短信等。告警内容要包含足够的信息消息内容、死信原因、原队列、发生时间等。这样收到告警的人可以快速判断问题的严重程度决定是否需要立即处理。5.4 死信队列的容量规划死信队列的容量规划经常被忽略但它直接影响到系统的稳定性。如果死信队列没有设置最大长度消息会无限堆积最终占满磁盘。如果设置了最大长度超出部分的消息会被丢弃可能导致重要信息丢失。我的建议是给死信队列设置一个合理的最大长度同时配置告警。最大长度根据业务的重要程度和消息量来定比如设置为 10000 条。当死信队列的消息数接近这个阈值时告警就会触发提醒开发人员及时处理。这样既避免了磁盘被占满又给了足够的缓冲时间。5.5 多级死信队列的设计在一些复杂的业务场景中单级死信队列可能不够用。比如消息第一次失败后进入死信队列重新投递后再次失败如果还是进入同一个死信队列就无法区分是第几次失败。这时候可以设计多级死信队列一级死信队列处理第一次失败的消息二级死信队列处理重试后仍然失败的消息。每级死信队列可以有不同的处理策略比如一级自动重试二级人工介入。实现多级死信队列的关键是在消息头部记录重试次数每次重新投递时增加计数。当计数超过阈值时路由到更高级别的死信队列。这个方案会增加系统的复杂度建议在确实有需要时才使用。5.6 死信队列与事务的结合如果业务操作涉及数据库事务死信队列的使用需要特别注意。比如消费者在处理消息时开启了数据库事务处理失败后事务回滚然后调用basicNack拒绝消息。这个顺序很重要必须先完成事务回滚再拒绝消息。如果顺序反了消息被拒绝进入死信队列但事务还没回滚可能会导致数据不一致。另外如果消息确认和数据库事务需要保证原子性可以考虑使用 RabbitMQ 的事务机制或者采用本地消息表等最终一致性的方案。这些方案各有优劣需要根据业务的具体需求来选择。6. 我在实际项目中的几点体会死信队列这个机制刚接触的时候觉得挺简单不就是消息失败了换个地方待着嘛。但真正在项目中用起来才发现细节非常多每一个参数、每一个调用顺序都可能影响到最终的行为。我印象最深的一次是消息一直循环消费的问题。当时消费者处理失败后调用了basicNack但requeue参数设置成了true结果消息被重新放回队列又被同一个消费者拿到再次失败再次放回形成了死循环。日志里满屏都是同一条消息的消费记录CPU 也被打满了。后来把requeue改成false消息进入死信队列问题才解决。这个坑让我明白死信队列的第一道门槛就是理解requeue参数的含义。另一个体会是关于死信队列的监控。刚开始用的时候我只关注业务队列的消息堆积忽略了死信队列。直到有一天发现磁盘空间异常排查后才发现死信队列里积压了几十万条消息都是几个月前消费失败的。从那以后我把死信队列的监控作为标配任何项目只要用了死信队列就必须配置消息数量和增长率的告警。还有一点是关于死信消息的处理策略。我见过一些项目死信队列配置了消息也进去了但从来没有人去看。这样的死信队列形同虚设只是把问题从业务队列转移到了死信队列并没有真正解决问题。死信队列的价值在于让问题可见、可追溯、可处理如果缺少了后续的处理环节它就只是一个“垃圾堆”。最后分享一个小技巧在死信消费者中可以把死信消息的完整信息包括x-death头部序列化后存入数据库。这样即使消息被确认删除了问题现场仍然保留着方便后续分析和复盘。这个做法在排查偶发性问题时特别有用因为有些问题不是每次都能复现的保留现场就变得非常重要。

相关新闻

用语言模型预测实证AI研究结果:技术拆解与复现指南

用语言模型预测实证AI研究结果:技术拆解与复现指南

最近在盯 2025 年 NeurIPS 的投稿风向时,一个题目特别扎眼:《Predicting Empirical AI Research Outcomes with Language Models》。干这行的朋友一听就明白,这不是让语言模型去跑实验、算指标,而是想用语言模型提前判断“一篇实证…

2026/10/18 5:30:41 阅读更多 →
改进鲸鱼优化算法在微网能量优化管理中的Matlab仿真与实践

改进鲸鱼优化算法在微网能量优化管理中的Matlab仿真与实践

微网能量优化这件事,听起来像是个纯电力专业的活,但真正上手做过的人都知道,做到后期其实就是个数学优化问题。光伏出力的随机性、负荷曲线的波动、储能充放电的时机、跟大电网交易的电价博弈,全部要揉进一个目标函数里求解。而求…

2026/10/18 5:30:41 阅读更多 →
从RAG到Function Calling:企业级AI智能体六大核心技术实践指南

从RAG到Function Calling:企业级AI智能体六大核心技术实践指南

1. 从"会聊天的机器人"到"能干活的下属",企业对智能体的预期变了AI智能体(AI Agent)这个词近两年几乎被说烂了,但我在企业落地大模型开发项目的过程中发现一个很扎心的现象:大多数团队做的第一个智…

2026/10/18 5:30:41 阅读更多 →

最新新闻

Netty实战进阶:粘包半包、EventLoop线程边界与长连接心跳

Netty实战进阶:粘包半包、EventLoop线程边界与长连接心跳

不少人可能和我有同样的感受:Netty的入门教程看了一遍又一遍,Echo服务器、聊天室Demo敲得飞起,但一到真实项目里要“实战应用”了,反而手足无措。客户端发过来的数据一多,消息全黏在一起;连接一挂&#xff…

2026/10/18 7:17:00 阅读更多 →
扫码点餐小程序多门店源码跑通指南

扫码点餐小程序多门店源码跑通指南

简介:这是一套基于Java后端与uniapp(Vue3)前端实现的在线点餐小程序完整源码,面向计算机、电子信息等专业学生及初级全栈开发者,适用于课程设计、期末大作业或毕业设计参考。系统支持扫码点餐、外卖配送与到店自取双模…

2026/10/18 7:17:00 阅读更多 →
新能源汽车实训仿真教学软件选型与课堂实施经验

新能源汽车实训仿真教学软件选型与课堂实施经验

做职业教育这行的人,多半都有过一种尴尬:理论课讲得头头是道,学生一到实训车跟前就手足无措。尤其是新能源汽车实训,教材上写的、课件里放的、实车上摸的,三者经常对不上。前几年我们引了一套以比亚迪秦EV为原型的电动…

2026/10/18 7:17:00 阅读更多 →
结合AI客户端玩转go MCP项目开发:TaoToken统一Key接入实战

结合AI客户端玩转go MCP项目开发:TaoToken统一Key接入实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 7:17:00 阅读更多 →
鸿蒙编码与安全双翼:中小企业智能化改造的落地指南

鸿蒙编码与安全双翼:中小企业智能化改造的落地指南

前几天一位做设备运维的中小企业负责人找我,说客户要求巡检数据必须可追溯、不能外泄,而他们过去的办法是拍照发到工作群。这个场景我最近半年至少遇到过五次,几乎已经成为中小企业在智能化改造里最典型的痛点。很多人一听到“鸿蒙编码”和“…

2026/10/18 7:17:00 阅读更多 →
返利系统架构设计:订单归集、分润与对账全链路解析

返利系统架构设计:订单归集、分润与对账全链路解析

做返利类APP这事,外行看着简单——不就是把商品链接套上推广参数丢给用户,等平台结算佣金再返一部分出去吗?真上手你会知道,开发量最大的根本不是前端页面,而是后端的订单归集、分润和对账三块。这三块任何一个环节出问…

2026/10/18 7:16:00 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →