SpringCloud Gateway堆外内存溢出排查:Netty直接内存泄漏定位与调优

1. 从一次线上告警说起:堆外内存溢出到底有多隐蔽

那天凌晨两点多,监控面板突然弹出一连串红色告警,网关节点在十分钟内连续重启了三次。登录机器翻看日志,满屏都是java.lang.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct memory。这个报错和常见的堆内存溢出长得不一样,它指向的是 JVM 堆外的那块直接内存区域。很多同学第一次遇到这个错会本能地去调大-Xmx,结果发现毫无作用,因为方向从一开始就错了。

SpringCloud Gateway 作为微服务架构里的流量入口,底层跑的是 Spring WebFlux 加 Netty 的响应式模型。Netty 在处理网络 IO 时,为了减少数据在堆内堆外之间的拷贝次数,大量使用ByteBuf这类直接内存缓冲区。请求体、响应体、连接缓冲区,统统走的是堆外内存。这就意味着,网关这个组件的内存画像和传统的 Servlet 应用完全不同——堆内存可能很平稳,但堆外内存却在悄悄膨胀,直到某个临界点突然爆掉。

这篇文章适合两类人看:一类是正在用 SpringCloud Gateway 做网关、已经被这个报错折腾过的后端开发;另一类是想提前搞清楚响应式网关内存模型、避免以后踩坑的架构同学。我会把整个排查链路完整还原出来,包括一开始怎么误判、中间怎么用工具定位、最后怎么从代码和参数两个层面把问题摁住。整个过程不涉及任何特殊网络环境,纯粹是 JVM 和框架层面的技术问题。

需要先建立一个基本认知:OutOfDirectMemoryError和OutOfMemoryError: Java heap space是两码事。前者说的是直接内存,这块内存不受-Xmx控制,默认情况下它的大小约等于-Xmx的值,但可以通过-XX:MaxDirectMemorySize单独指定。当 Netty 申请直接内存缓冲区时,如果剩余额度不够,就会抛出这个错误。理解这一点,后面的排查才有方向。

2. 先搞清楚 Netty 的直接内存是怎么被吃掉的

2.1 ByteBuf 的分配与释放机制

Netty 里的数据载体是ByteBuf,它分两种:堆缓冲区(HeapByteBuf)和直接缓冲区(DirectByteBuf)。网关场景下,Netty 默认优先使用直接缓冲区,因为数据最终要经过 Socket 发送,直接内存可以避免一次从堆内到堆外的拷贝。每次有请求进来,Netty 会从内存池里分配一块ByteBuf给这个连接用;请求处理完,这块内存需要被归还到池子里。

问题就出在"归还"这个动作上。Netty 采用的是引用计数(reference counting)机制,每个ByteBuf有一个refCnt。分配出来时计数为 1,每次retain()加 1,每次release()减 1,减到 0 才会真正回收。如果某条代码路径上漏掉了一次release(),这块内存就永远不会被归还,池子里的可用内存越来越少,最终耗尽。

在 SpringCloud Gateway 里,请求体和响应体的读写都封装在框架内部,正常情况下框架会帮你管理好引用计数。但一旦你写了自定义的GlobalFilter或者GatewayFilter,手动去操作ServerWebExchange里的DataBuffer,就很容易破坏这个平衡。这是后面排查的重点方向之一。

2.2 内存池化带来的"假象"

Netty 默认开启了池化分配器PooledByteBufAllocator。池化的好处是分配和回收效率高,但它也带来一个排查上的麻烦:内存被池子持有,即使业务上已经不再使用,从操作系统层面看这块内存也没有立刻还给系统。所以你用top或者free看机器内存,可能一直居高不下,但这不一定是泄漏,可能只是池子还没释放。

真正判断是否泄漏,要看的是"已分配但未归还"的缓冲区数量是否持续增长。这就需要用 Netty 提供的泄漏检测工具,或者通过 JMX 指标来观察。单纯看进程的 RSS 内存,很容易被误导,把正常的池化行为当成泄漏来处理,白白浪费时间。

2.3 网关场景下直接内存的几个主要消耗方

在网关这个特定场景里,直接内存的消耗主要来自这么几块:一是每个连接对应的读写缓冲区,二是请求体和响应体的聚合缓冲区,三是 SSL/TLS 握手时的加密缓冲区(如果开启了 HTTPS)。其中第二块是最容易出问题的,因为网关经常需要读取完整请求体做鉴权、限流、日志记录,一旦用了DataBufferUtils.join()把请求体聚合成一个大的DataBuffer,这块内存就完全由业务代码负责释放了。

我见过不少项目,在过滤器里把请求体读出来做签名校验,读完就忘了释放,每个请求泄漏一点,QPS 一上来,几小时就能把直接内存吃光。这种泄漏的特点是增长曲线很平滑,和流量成正比,重启后恢复,流量上来又复发,非常有规律。

3. 排查工具链:从现象到根因的完整路径

3.1 第一步:确认是直接内存而非堆内存

拿到OutOfDirectMemoryError之后,第一件事是确认堆内存是否正常。用jstat -gc <pid> 1000观察几轮,如果老年代和新生代都没有持续增长,Full GC 后也能回落,那基本可以排除堆内存问题。同时用jcmd <pid> VM.native_memory summary看 JVM 的本地内存分布,重点关注Internal和Other这两块,直接内存通常会计入其中。

如果 JVM 启动时加了-XX:NativeMemoryTracking=detail,还能看到更细的分配来源。不过这个参数有性能开销,生产环境一般不开,可以在预发环境复现时打开。另一个更直接的办法是加-XX:MaxDirectMemorySize并配合-XX:+HeapDumpOnOutOfMemoryError,虽然直接内存溢出不会生成堆转储,但至少能确认溢出时的内存上限。

3.2 第二步:用 Netty 泄漏检测定位未释放的缓冲区

Netty 内置了泄漏检测机制,通过-Dio.netty.leakDetection.level=paranoid可以开启最严格的检测级别。这个级别下,每次ByteBuf被 GC 回收时,如果发现引用计数不为 0,就会打印一条详细的泄漏报告,包含分配时的堆栈信息。这条堆栈就是破案的关键,它能直接告诉你这块内存是在哪行代码分配的。

需要提醒的是,paranoid级别对性能有影响,只适合在预发或压测环境短期开启。生产环境可以用simple级别,它只采样 1% 的缓冲区,开销小很多,但也能捕获到持续泄漏的场景。开启方式是在启动参数里加-Dio.netty.leakDetection.level=simple,或者通过代码ResourceLeakDetector.setLevel()动态设置。

3.3 第三步:结合火焰图和堆外内存采样

如果泄漏检测没有捕获到,说明问题可能不在单个ByteBuf的引用计数上,而是整体分配速率超过了回收速率。这时候可以用async-profiler做一次堆外内存分配采样,命令是./profiler.sh -e alloc -d 60 -f alloc.html <pid>。生成的火焰图里,能看到哪些调用路径在疯狂申请直接内存。

我实际排查时遇到过一个案例,火焰图显示大量分配来自SslHandler的握手缓冲区。原因是网关开启了 HTTPS,但客户端连接池配置不合理,导致频繁重建连接,每次重建都要分配 SSL 缓冲区。这种情况不是泄漏,而是分配压力过大,解决思路是优化连接复用,而不是去查引用计数。

3.4 第四步:观察指标确认泄漏还是压力

区分"泄漏"和"压力过大"有个简单办法:看重启后的表现。如果是泄漏,重启后内存会从低位开始缓慢爬升,爬升速度和请求量正相关,最终触顶;如果是压力过大,重启后很快又会触顶,甚至压测时几秒就爆。另外可以观察PooledByteBufAllocator的 JMX 指标,重点看direct.arenas下各区域的chunkSize和used变化,如果used只增不减,基本可以确定是泄漏。

4. 代码层面的几个高频泄漏点与修复方案

4.1 自定义过滤器里忘记释放 DataBuffer

这是最常见的一种。看下面这段有问题的代码:

@Component public class AuthFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); // 这里读完就返回了,没有 release String body = new String(bytes, StandardCharsets.UTF_8); if (!checkSign(body)) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); }); } }

DataBufferUtils.join()返回的DataBuffer是池化的,用完必须调用DataBufferUtils.release(dataBuffer)。正确写法是在flatMap里用try-finally或者doFinally确保释放:

return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { try { byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); String body = new String(bytes, StandardCharsets.UTF_8); if (!checkSign(body)) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } finally { DataBufferUtils.release(dataBuffer); } });

这里有个细节要注意:DataBufferUtils.join()之后,原始的请求体已经被消费掉了,下游过滤器再想读就读不到了。如果确实需要下游也能读,得用exchange.getAttributes()把读出来的字节缓存起来,或者用ServerHttpRequestDecorator包装一个可重复读的请求。但包装的时候同样要注意,装饰器里的DataBuffer也要正确释放。

4.2 响应体改写时的缓冲区管理

改写响应体比读请求体更麻烦,因为响应是流式的,你得先拦截、缓存、修改、再写回。很多实现会用ServerHttpResponseDecorator,在writeWith方法里做文章。这里如果处理不当,很容易出现缓冲区没释放或者重复释放的问题。

一个稳妥的做法是:在装饰器里用DataBufferFactory重新分配一块缓冲区来存放修改后的内容,原来的缓冲区在读取完后立即释放。写回时用response.writeWith(Mono.just(newBuffer)),让框架负责新缓冲区的释放。切记不要直接把读到的DataBuffer原样返回,那样引用计数会乱掉。

4.3 限流和熔断组件对缓冲区的隐式持有

有些限流实现会基于请求体内容做规则匹配,比如根据请求参数里的某个字段决定限流阈值。这类组件如果在内部缓存了请求体,又没有设置合理的过期策略,就会导致缓冲区被长期持有。排查时如果发现泄漏和特定接口相关,可以重点检查这类组件。

另外,熔断降级返回兜底响应时,如果兜底内容是通过读取原始响应体再拼接生成的,同样要注意释放原始缓冲区。我建议在写这类组件时,统一用一个工具方法封装"读取并释放"的逻辑,避免每处都手写release导致遗漏。

5. 参数调优:给直接内存留出合理空间

5.1 MaxDirectMemorySize 的设置逻辑

默认情况下,-XX:MaxDirectMemorySize等于-Xmx。假设你的网关容器给了 4G 内存,-Xmx设了 2G,那直接内存上限也是 2G,加起来 4G,再加上 Metaspace、线程栈、JVM 自身开销,很容易超过容器限制被 OOM Killer 干掉。所以网关这类大量使用直接内存的应用,必须显式设置这个参数。

我的经验值是:如果-Xmx设 2G,直接内存可以设 1G 到 1.5G,给堆外留出足够空间,同时容器总内存要留 20% 以上的余量。具体数值要看压测结果,观察稳定运行时的直接内存水位,一般不要超过上限的 70%,留出应对流量尖峰的缓冲。

5.2 池化参数的调整

Netty 的池化分配器有几个关键参数:-Dio.netty.allocator.numDirectArenas控制直接内存的 arena 数量,默认是 CPU 核数的 2 倍。arena 太多会导致内存碎片化,每个 arena 都要预分配 chunk,总占用反而上升。对于网关这种场景,建议把这个值调到 CPU 核数或者更小,比如 4 核机器设 4 到 8 就够了。

-Dio.netty.allocator.chunkSize控制每个 chunk 的大小,默认是 16MB。如果网关处理的请求体普遍较小,可以适当调小 chunk,减少浪费;如果经常处理大文件上传下载,则要保持较大 chunk 避免频繁分配。这个参数需要结合业务特征来定,没有万能值。

5.3 连接与超时参数的配合

直接内存的消耗和连接数强相关。每个活跃连接都会占用读写缓冲区,连接数越多,缓冲区总量越大。所以maxConnections、pendingAcquireMaxCount这些参数不能拍脑袋设太大。同时,空闲连接要及时回收,idleTimeout设得太长会导致大量连接挂着占内存,设得太短又会导致频繁重建连接增加分配压力。

我一般会把空闲超时设在 30 到 60 秒之间,配合合理的连接池上限,让连接数稳定在一个可控范围。压测时重点观察连接数和直接内存的对应关系,找到那个"内存不涨、吞吐达标"的平衡点。

6. 几个容易误判的场景与我的实操心得

6.1 把池化缓存当成泄漏

前面提过,Netty 池化分配器会缓存一部分内存不还给系统。有一次我在预发环境看到进程 RSS 一直维持在 3G 不降,以为泄漏了,折腾半天加泄漏检测,结果什么都没抓到。后来才明白,那是池子里的 chunk 被缓存着,属于正常行为。判断标准应该是"已分配未释放的缓冲区数量",而不是进程 RSS。

如果你确实想让池化内存在空闲时归还,可以设置-Dio.netty.allocator.useCacheForAllThreads=false,但这会降低性能,一般不建议在生产开。更合理的做法是接受池化行为,把监控重点放在缓冲区计数上。

6.2 大请求体导致的瞬时峰值

有时候不是泄漏,而是某个时刻来了几个超大请求体,比如批量导入接口一次传几十 MB,网关聚合请求体时瞬间申请大量直接内存,直接把上限打爆。这种情况的特征是溢出时间点和特定请求强相关,日志里能查到对应的大请求。

解决办法有两个方向:一是限制单请求体大小,在网关层加maxInMemorySize配置,超过就拒绝;二是对大请求体走流式处理,不要用join()聚合,边读边转发。SpringCloud Gateway 默认的maxInMemorySize是 256KB,如果业务需要更大,要显式调大,但别调得离谱。

6.3 压测环境复现不出来的坑

有些泄漏只在生产的高并发下才出现,压测环境怎么都复现不了。这通常是因为泄漏和并发竞争有关,比如多线程环境下引用计数操作不是原子的,或者某个异步回调在特定时序下才漏掉释放。遇到这种情况,可以在生产用simple级别的泄漏检测长期挂着,等它下次复现时抓现场。

另外,压测时要注意请求的多样性。如果压测只打一个简单接口,可能刚好绕过了有问题的代码路径。我建议压测用例要覆盖鉴权、限流、响应改写这些复杂链路,才能把潜在问题逼出来。

6.4 升级框架版本带来的变化

SpringCloud Gateway 和 Netty 的版本升级有时会改变内存管理行为。比如某个版本开始默认开启了更激进的池化策略,或者修改了DataBuffer的默认实现。升级后如果突然出现直接内存问题,先对比一下依赖版本的变化,看看 release notes 里有没有相关改动。我遇到过升级后maxInMemorySize默认值变化导致行为不一致的情况,排查时绕了弯路。

建议在升级网关这类核心组件时,先在预发跑一轮完整压测,重点观察直接内存指标,确认无异常再上生产。别小看这个步骤,它能帮你省掉很多半夜被叫起来处理故障的时间。

7. 一套可落地的监控与预防方案

7.1 关键指标采集

要提前发现问题,得把几个核心指标纳入监控:直接内存使用量(通过BufferPoolMXBean获取)、Netty 池化分配器的used和chunkSize、活跃连接数、请求体聚合次数。这些指标可以用 Micrometer 暴露到 Prometheus,配上告警规则,比如直接内存使用率超过 80% 持续 5 分钟就告警。

BufferPoolMXBean是 JDK 自带的,能直接拿到direct类型的内存池使用情况,代码很简单:

List<BufferPoolMXBean> pools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); for (BufferPoolMXBean pool : pools) { if ("direct".equals(pool.getName())) { long used = pool.getMemoryUsed(); long capacity = pool.getTotalCapacity(); // 上报 used 和 capacity } }

7.2 泄漏检测的常态化

生产环境长期开simple级别的泄漏检测,开销可以忽略不计,但能在泄漏发生时第一时间留下堆栈。配合日志采集,一旦出现LEAK关键字就触发告警。这样即使问题在凌晨发生,第二天也能拿着堆栈直接定位,不用再靠猜。

7.3 代码规范上的约束

团队里最好定一条规矩:任何手动操作DataBuffer的地方,必须成对出现获取和释放,并且用工具方法封装,禁止裸写。Code Review 时把这块作为重点检查项。还可以写一个简单的静态检查规则,扫描DataBufferUtils.join的调用点,提醒开发者确认是否释放。

7.4 容量规划的定期回顾

业务在增长,网关的流量特征也会变。建议每个季度回顾一次直接内存的水位和峰值,看看当前参数是否还合适。特别是大促前,要提前压测确认容量,别等到流量洪峰来了才发现内存不够。容量规划这件事,宁可提前做,也别事后补。

我在实际项目里把这套方案落地之后,网关的直接内存问题从"偶发故障"变成了"可观测、可预警、可定位"的常规运维项。最明显的变化是,再也没有因为这个问题半夜被叫起来过。踩过的那些坑,最后都变成了监控面板上的几条曲线和告警规则,这大概就是排查问题的意义所在——不是为了解决这一次,而是为了让下一次不再发生。

相关新闻

RAG知识库文档处理实操:解析、切分与检索效果全面调优

RAG知识库文档处理实操:解析、切分与检索效果全面调优

“收藏备用&#xff01;RAG知识库文档处理实操”&#xff0c;这个标题我第一眼看到就想点头。做RAG知识库的人&#xff0c;谁没被文档处理折磨过&#xff1f;模型选型、Prompt优化这些话题都是热热闹闹的技术高地&#xff0c;结果真正把项目拖死的&#xff0c;往往是最朴素的一…

2026/10/19 17:06:26 阅读更多 →
知网AIGC检测升级:2026降AI率实操方法与底层逻辑

知网AIGC检测升级:2026降AI率实操方法与底层逻辑

知网AIGC检测升级这件事&#xff0c;今年把不少人打了个措手不及。去年还在用的某些“降AI率”套路&#xff0c;现在直接失效&#xff0c;甚至会让重复率一并飙升。我自己的几个文档在升级后重新送审&#xff0c;反馈回来的AIGC标注位置和之前完全不同&#xff0c;有些段落明明…

2026/10/19 17:06:26 阅读更多 →
1390张罂粟检测数据集:VOC/YOLO格式转换与YOLOv8训练实战

1390张罂粟检测数据集:VOC/YOLO格式转换与YOLOv8训练实战

1. 项目概览&#xff1a;1390张双格式数据集到底能做什么最近在整理目标检测训练样本&#xff0c;手头正好有一份“罂粟检测数据集1390张VOCYOLO格式”。这个数字乍一看不算大&#xff0c;但做算法验证和流程测试完全够用。整份数据由三部分构成&#xff1a;原始图片、VOC格式的…

2026/10/19 17:06:26 阅读更多 →

最新新闻

RGAT+GRU融合模型解决APT溯源图稀疏漏报问题

RGAT+GRU融合模型解决APT溯源图稀疏漏报问题

简介&#xff1a;本资源是华中科技大学2023届计算机相关专业&#xff08;如计科、人工智能、网络安全等&#xff09;优秀毕业设计成果&#xff0c;聚焦APT攻击检测这一前沿安全问题&#xff0c;提出并实现了一种基于溯源图建模与RGATGRU融合架构的检测方法优化方案。面向在校本…

2026/10/19 17:38:44 阅读更多 →
文件格式伪装揭秘:从魔数原理到apate工具实战

文件格式伪装揭秘:从魔数原理到apate工具实战

很多人在第一次听说“文件格式伪装”时&#xff0c;第一反应都是&#xff1a;这玩意儿真的能实现吗&#xff1f;改个扩展名谁不会&#xff0c;把.txt改成.exe&#xff0c;文件不照样打不开&#xff1f;如果你也这么想&#xff0c;说明你还没真正理解文件识别的底层逻辑。文件格…

2026/10/19 17:38:44 阅读更多 →
Source Map泄露实战:从检测还原到构建防御的完整指南

Source Map泄露实战:从检测还原到构建防御的完整指南

接手一个站点做安全评估的时候&#xff0c;我习惯先打开开发者工具的 Sources 面板&#xff0c;随手翻一下静态资源目录。很多时候问题就藏在那些不起眼的*.js.map文件里——Webpack 构建后遗留的 Source Map&#xff0c;一旦暴露在生产环境&#xff0c;等于把源码打包好递到别…

2026/10/19 17:38:44 阅读更多 →
MySQL存储过程实战:语法、游标、动态SQL与性能优化全解析

MySQL存储过程实战:语法、游标、动态SQL与性能优化全解析

这年头一说起MySQL存储过程&#xff0c;不少开发者的第一反应就是“能不用就不用”、“业务逻辑别放进数据库”。我早些年也是这个态度&#xff0c;直到接手了几个数据清洗、批量报表、复杂统计类的项目&#xff0c;被接口超时和网络往返折腾得没脾气&#xff0c;才老老实实回头…

2026/10/19 17:38:44 阅读更多 →
Spark性能优化实战:从数据倾斜到资源配置的完整调优指南

Spark性能优化实战:从数据倾斜到资源配置的完整调优指南

1. 为什么 Spark 性能优化是个绕不开的坎干过大数据的人都有一个共识&#xff1a;Spark 作业能跑起来不难&#xff0c;难的是跑得又快又稳。我见过太多团队&#xff0c;集群规模不小&#xff0c;机器配置也不差&#xff0c;但一个 ETL 任务动辄跑两三个小时&#xff0c;资源利用…

2026/10/19 17:38:44 阅读更多 →
open-code-review实战:从零搭建开放可持续的代码审查机制

open-code-review实战:从零搭建开放可持续的代码审查机制

1. 为什么“open-code-review”值得单独拿出来聊第一次听到“open-code-review”这个词&#xff0c;很多人会下意识觉得它只是“代码审查”换了个英文壳子。但真在团队里推过代码审查的人都知道&#xff0c;代码审查这件事&#xff0c;做一次两次不难&#xff0c;难的是把它做成…

2026/10/19 17:37:42 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介&#xff1a;本资源为电源技术方向的学术研究文档&#xff0c;聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略&#xff0c;面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集&#xff0c;共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →