news 2026/10/20 17:49:24

信创环境下Java大文件分块上传适配与性能调优实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
信创环境下Java大文件分块上传适配与性能调优实践

去年接手了一个内部管理系统向信创环境迁移的改造任务,业务上第一个卡住的功能就是大文件上传。业务场景本身不复杂,就是上传项目文档、培训视频、图纸压缩包这批东西,单文件最大能到2GB到4GB。放在以前的老环境里,改几个中间件参数就能跑。可真切到国产化技术栈之后,问题一个接一个:中间件默认限制直接挡住请求、国产JDK在NIO上的行为差异、数据库方言不兼容、磁盘挂载路径的字符集坑……整个改造过程踩了一圈,才把一套稳定的大文件分块上传方案调通。

这篇文章把我在信创环境里做分块上传适配和优化的完整过程梳理一遍,包括整体方案设计、JAVA实现细节、分块参数怎么定、性能实测数据、常见问题排查。不是理论分析,是能直接拿去复用的实操经验。适合正在做信创迁移适配、或者准备把旧系统迁到国产化技术栈上的JAVA后端同学参考。

1. 信创环境拆解:为什么大文件上传必须重新适配

1.1 国产化技术栈下的四层差异

这里说的信创环境,概括起来是硬件、操作系统、JDK、中间件与数据库四层组合起来的国产化技术栈。和以前熟悉的国外商业技术栈相比,每一层都有细节差异。

硬件层:CPU不光有x86架构,还有大量ARM等其它架构的芯片。指令集不同,JVM的JIT编译策略就有差异,涉及到底层压缩、加密、大文件矢量读取的场景,表现得特别明显。分块上传看起来是纯IO操作,但最终所有读写都会落到系统调用上,不同架构下的系统IO调度行为不完全一样。

操作系统层:主流是各类国产Linux发行版,内核基线不一致,有的偏老有的偏新。部署上去之后,文件描述符上限、挂载点、权限模型、默认的IO调度器都可能和你开发机不一样。我之前就遇到过开发环境一切正常、生产环境压测直接报Too many open files的情况,排查了半天才发现是系统默认的ulimit被调得太保守。

JDK层:团队里用了两类国产JDK,一类是基于OpenJDK二开的,一类是商业自研实现。两者的API表面兼容,内在行为各有各的坑。比如FileChannel.transferTo在某些版本上处理大文件循环时会返回0,还有ZipFile在特定字符集下解压中文文件名会乱码。这些坑平时根本不会暴露,切到国产JDK之后全都冒出来了。

中间件与数据库层:中间件大多是开源项目的二次封装,但基线版本往往偏低,默认参数保守。国产数据库在SQL方言和事务行为上对Oracle、MySQL的兼容度参差不齐,换库之后原本跑得好好的SQL可能要逐个排查改写。

1.2 大文件上传在信创环境最容易踩的三个坑

第一个坑:中间件默认限制。我们线上中间件默认单请求body大小限制在很低的水平,传大文件直接返回413,请求根本到不了应用层。以前在旧环境里改一个配置文件就行,到了信创环境,配置项的命名和生效逻辑全变了,改了半天没生效,最后发现是两层配置叠加拦截。

第二个坑:服务器内存规格普遍偏保守。很多私有化部署环境给的是4核8G这种规格,如果用传统的MultipartFile整包接收,前端把2GB文件一次性POST上来,JVM内存直接被打穿,GC连环抖动,应用跟着假死。这也是必须走分块方案的核心原因之一——不能赌服务器内存足够大。

第三个坑:网络链路不稳定。信创项目大量部署在专网、异地机房之间,链路丢包和限速比公有云环境明显。以前前端用单请求上传大文件,传输中途断开就得全部重来,体验极差。分块之后一块失败只重传那一块,这是刚需。

2. 分块上传方案设计与决策要点

2.1 整体流程:初始化、传块、合并、查状态

我把整套上传拆成四个核心接口,每个接口的职责单一,前后端协作时不容易混乱。

  • 初始化上传:前端把文件名、文件大小、要切成多少块、每块大小、文件级MD5传给服务端。服务端创建临时分块文件占位,生成全局唯一的uploadId,返回给前端。
  • 上传分块:前端拿着uploadId和块编号,按顺序或并发上传每个分块。服务端按块编号写入临时文件对应偏移位置,记录每个分块的上传状态。
  • 合并文件:所有分块上传完成后,前端请求合并接口。服务端校验分块完整性和MD5,按序合并成最终文件。
  • 查询状态:前端随时可以查询某个uploadId下的分块上传情况,用于断点续传和失败重试。

这套流程把上传过程从单次大请求拆成了多个小请求,整体可靠性和可恢复性提升明显。前端实现断点续传的代价也低:每次启动上传前先查状态,拿到已经传成功的块号列表,只传缺失的块。

2.2 为什么选择磁盘暂存而不是内存缓存

我知道有人会用内存缓存来做分块合并——分块传上来,在内存里按uploadId缓存ByteArrayOutputStream,等全传完了再一次性写盘。这种方案在小文件场景下没问题,但几个GB的大文件根本不行。4核8G服务器上同时跑三四个上传任务,内存直接爆掉。

我选的是磁盘暂存方案:每个分块到达后,立刻写入临时目录下的分块文件中。内存在整个上传过程中只保留小块缓冲,大量数据都走page cache,由操作系统内核负责调度落盘。合并在磁盘上进行,也是流式读写,内存占用恒定在几MB级别。

磁盘暂存不是简单写个文件,有几个细节必须处理好:

  1. 临时目录要放在独立的数据盘分区,不要放系统盘或根目录,否则分块写多了把系统盘打满,机器整体出问题。
  2. 临时文件命名用uploadId加ChunkIndex,不要用原始文件名。原始文件名可能包含特殊字符,在跨平台场景下有路径注入风险,而且并发同名文件会互相覆盖。
  3. 必须配套定时清理任务,把超过一定时间仍未完成合并的孤儿分块清理掉。用户中途关浏览器是最常见的情况,不清理时间长了磁盘必然被占满。

2.3 分块参数怎么定:块大小、并发数的计算逻辑

分块大小不是一个拍脑袋的数字,它是在四个约束之间取平衡:存储扇区对齐、网络MTU、单块写入耗时、失败重传成本。

我建议的导算逻辑是这样:

  • 分块太小(比如1MB):HTTP请求数量爆炸,1GB文件要发1024个请求,握手和请求头开销占比非常高,服务端QPS压力大。
  • 分块太大(比如64MB):断点续传的粒度太粗,一旦一个分块在弱网链路传输失败,重传的数据量很大。
  • 以100Mbps内网为例,实际带宽约8到10MB/s,8MB的分块传输时间约0.8到1秒,服务端落盘几毫秒到几十毫秒,传输和等待的比例正好合适。

以1GB文件配8MB分块为例,分块数就是ceil(1073741824 / 8388608) = 128块。前端开3路并发,每轮传3块,约43轮完成,整个流程状态清晰且容易监控。

分块编号从0开始,服务端严格按编号写入对应偏移。这样分块异步抵达、乱序到达都不会影响最终合并结果。

并发度也做过实测:前端并发数在3到5之间比较合适。信创环境常用NAT和负载均衡设备,并发建连数有限,开太高会导致连接排队。而且服务端分块接收属于IO密集型操作,线程太多反而增加上下文切换开销。在4核8G机器上,前端3路并发、服务端接收线程池核心5最大10,整体表现最稳。

3. JAVA核心实现细节与适配写法

3.1 分块接收:RandomAccessFile 按偏移写入

分块接口收到数据后,需要按ChunkIndex写到临时文件的固定偏移位置,而不是追加写。追加写依赖到达顺序,乱序分块会造成数据错位;按固定偏移写天然支持乱序到达。

public void writeChunk(String filePath, int chunkIndex, long chunkSize, InputStream in) throws IOException { try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) { long offset = (long) chunkIndex * chunkSize; raf.seek(offset); byte[] buf = new byte[8192]; int len; while ((len = in.read(buf)) != -1) { raf.write(buf, 0, len); } } }

这段代码看起来简单,实际使用有几个细节:

使用rw而不是rwd模式。rwd模式下每次write都会强制刷盘,性能断崖式下跌。分块写入场景本来就有操作系统的page cache兜底,不需要每次写都刷盘,等合并完再统一保证落盘更合理。

偏移计算必须用long类型。chunkIndex * chunkSize的乘积很容易超过int上限。真见过有人用int算偏移,300块乘以8MB之后数值溢出,文件数据直接写花,排查了大半天。

文件要提前占位。初始化接口里我会先创建临时文件并setLength到文件总大小,这样随机写不会遇到文件尾部未创建的问题。占位后磁盘上表现为稀疏文件,实际不占满空间,大多数Linux文件系统都支持这一点。

3.2 分块合并:NIO Channel 顺序合并

所有分块传完之后,合并接口把所有分块按编号顺序写入目标文件。传统方式是循环打开分块文件,用BufferedInputStream逐个读再写。在分块数量多的时候性能一般,我改成用FileChannel的transferTo做内核态拷贝。

public void mergeChunks(String uploadId, int totalChunks, Path tmpDir, Path target) throws IOException { try (FileChannel out = FileChannel.open( target, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { for (int i = 0; i < totalChunks; i++) { Path chunkPath = tmpDir.resolve(uploadId + ".part." + i); if (!Files.exists(chunkPath)) { throw new IllegalStateException("缺少分块: " + chunkPath); } try (FileChannel in = FileChannel.open(chunkPath, StandardOpenOption.READ)) { long size = in.size(); long written = 0; while (written < size) { long n = in.transferTo(written, size - written, out); if (n <= 0) { break; } written += n; } if (written < size) { fallbackCopy(in, out, written, size); } } } } }

在国产JDK上,transferTo行为不完全一致。有些实现版本在特定文件系统或跨文件系统场景下会返回0,表示本次系统调用没有移动任何字节,但并不是失败。如果代码里不做保护,这里很容易陷入死循环。我加了连续返回0的判断,直接退化成普通read/write拷贝。

分块大小是8MB时,其实退化成read/write性能差距也不大,但正常路径用transferTo可以少做用户态和内核态之间的数据复制。我的建议是默认走transferTo,但要留好fallback路径,这是信创环境适配最通用的思路——不赌底层实现的完美性,把异常路径设计好。

3.3 并发合并锁与状态机控制

合并操作必须做并发保护。前端双击完成按钮、网络重试、接口被重复调用,都可能触发对同一个uploadId的并发合并。如果不加控制,轻则重复IO,重则目标文件被写坏。

我设计了一套简单的状态机:

  • INIT:初始化完成,等待上传分块
  • UPLOADING:分块上传中
  • MERGING:合并中
  • DONE:合并完成

合并接口进入时先判断状态,只有UPLOADING或INIT状态允许合并;MERGING状态说明已经有线程在合并,直接返回或等待;DONE状态直接返回成功。合并失败时回退到UPLOADING状态,允许重新触发合并。

private ConcurrentHashMap<String, String> statusMap = new ConcurrentHashMap<>(); private ConcurrentHashMap<String, Object> mergeLocks = new ConcurrentHashMap<>(); public void mergeFile(String uploadId) { Object lock = mergeLocks.computeIfAbsent(uploadId, k -> new Object()); synchronized (lock) { String status = statusMap.get(uploadId); if ("DONE".equals(status) || "MERGING".equals(status)) { return; } statusMap.put(uploadId, "MERGING"); try { doMerge(uploadId); statusMap.put(uploadId, "DONE"); } catch (Exception e) { statusMap.put(uploadId, "UPLOADING"); throw e; } } }

有一个坑必须提:mergeLocks里的锁对象不要在finally里remove。computeIfAbsent和remove组合在高并发下不是原子的,可能出现一个线程remove掉锁对象、另一个线程同时computeIfAbsent创建新锁对象,导致两个线程拿着不同锁对象并发进入临界区。这里我吃过亏,后来改成锁key保留到整个上传记录清理时才移除,uploadId生命周期本来就不长,保留即可。

多实例部署时,内存状态机不共享。如果系统要横向扩容,状态必须落库,在数据库里用行锁或乐观锁保证并发安全。信创私有化项目很多是单机起步,但为了后续扩展,我在upload_info表里同样存了status字段,内存状态和数据库状态保持一致。

3.4 MD5校验、秒传与断点续传

MD5在分块上传里承担三个作用:分块级校验、文件级校验、秒传指纹。

分块级校验:每个分块上传完成后,服务端计算该分块的MD5并与前端传入值比对,不一致则返回失败,前端重传该分块。这个校验成本很低,但能提前发现链路传输损坏。

文件级校验:合并完成后,服务端重新计算整个文件的MD5,与初始化时前端声明的文件MD5比对。不一致说明合并过程或分块数据有异常,标记该上传失败,防止错误文件进入业务链路。

秒传逻辑:前端在初始化前先传文件大小和MD5指纹,服务端查库,如果已有相同指纹且大小一致的文件记录,直接返回上传成功,前端跳秒完成。对这个业务里大量重复传输的培训视频文件非常有效。

计算大文件MD5不能一次性读入内存,要流式计算。2GB文件如果直接用byte[]读进来,内存直接爆掉,必须在循环里分块读取更新摘要:

public static String md5(Path file) throws IOException { MessageDigest md = MessageDigest.getInstance("MD5"); try (InputStream in = Files.newInputStream(file)) { byte[] buf = new byte[1024 * 1024]; int len; while ((len = in.read(buf)) != -1) { md.update(buf, 0, len); } } return toHex(md.digest()); }

这里用1MB缓冲而不是8KB,可以减少循环次数,毕竟2GB文件读2万多次和读26万次差距还是明显的。

断点续传的状态一致性有一个容易忽略的窗口问题:如果先落库再落盘,磁盘写失败就会出现数据库说上传成功、磁盘上却没有分块文件的假成功状态。我的顺序是严格先落盘、再校验分块大小和MD5、最后写库。写库失败则删除刚写入的分块文件并返回错误。这样磁盘和数据库状态始终一致。

4. 信创环境下的性能调优与实测记录

4.1 分块大小与并发数的对比实测

调优不能靠猜,我在一套典型的4核8G国产服务器、1GB测试文件、100Mbps内网和20Mbps专网两种链路下做了对比实测。

参数组合100Mbps内网耗时20Mbps专网耗时失败重传成本服务端QPS压力
4MB块 + 3并发128秒428秒低高
8MB块 + 3并发106秒405秒中中
16MB块 + 3并发104秒402秒较高低
8MB块 + 5并发105秒406秒中较高

结论很明确:100Mbps下8MB和16MB差距极小,4MB因为请求数翻倍反而慢一些。20Mbps专网下瓶颈完全在带宽,并发数和分块大小对总时长影响很小,但分块小意味着单块重传成本低,弱网下更稳。

最终组合定为8MB分块、前端3路并发。16MB虽然带宽饱和时总耗时略优,但单块在100Mbps下传输约1.6秒,一旦失败重传代价偏高。8MB在可靠性和性能之间最平衡。

并发路数超过5之后,4核8G服务器上开始出现线程调度开销、文件句柄占用偏高等问题,吞吐不再线性增长。前端并发控制到3是最合适的。

4.2 JVM内存与GC适配

传统MultipartFile整包上传方式在信创这种内存规格下是不可接受的。改成自定义分块接口后,内存占用大幅下降,但合并和MD5校验阶段仍然有优化空间。

合并循环里,不要在每块循环体内新建byte[]。刚接手时代码在for循环里声明了byte[] buf = new byte[8192],128个分块跑下来产生大量短期对象,Young GC频繁。把byte[]提到循环外复用同一个缓冲区,GC压力瞬间小了很多。

分块接收接口同理,InputStream读取的byte[]要复用。这个细节写一次,后面所有IO代码都受益。

Direct Memory要限制。用FileChannel和ByteBuffer时,堆外内存不受-Xmx管理,默认MaxDirectMemorySize等于-Xmx大小。在信创环境里如果不显式限制,Native内存容易被顶高。实践参数如下:

-Xms2g -Xmx4g -XX:MaxDirectMemorySize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200

4核8G规格下堆给2G到4G足够。不要贪大,剩余内存留给page cache更划算。之前试过堆给6G,JVM占用吃掉大半物理内存,page cache不足,磁盘IO反而明显变慢。大文件上传是IO密集型任务,内存收益优先给内核页缓存,比给JVM堆更值。

4.3 磁盘IO与文件系统适配

分块临时目录和最终文件目录要落在独立数据盘上,这是强烈的建议。信创环境很多默认安装把数据放在系统盘,分块文件累积起来容量消耗很快,一旦把根分区写满,影响的不只是上传功能,而是整机稳定性。

文件系统选型上,推荐ext4或xfs这类成熟的Linux文件系统。有旧文件系统单文件大小上限偏低,2GB文件就可能触顶。上线前用dd命令造一个比业务上限更大的文件验证写入,能提前发现这类问题。

挂载参数里开启noatime可以降低文件访问时间更新带来的写放大。分块上传过程中大量文件被频繁读取写入,关闭atime更新对IO有可感知的收益。

临时文件和最终文件要尽量落在同一个文件系统上。跨文件系统时transferTo会退化成用户态拷贝,速度明显下降。同一文件系统下,transferTo可以利用内核页缓存直接把数据拷贝出去,开销最小。

有人建议把临时分块目录挂成tmpfs内存盘,我实测过但最终没采用。tmpfs写分块确实快,但大文件所有分块都放内存盘时,内存占用非常恐怖,和整个方案省内存的初衷相悖。开发环境玩玩可以,生产环境不推荐。

5. 常见问题与排障技巧实录

5.1 中间件上传限制与413问题

现象:上传大文件直接被拒绝,返回413或403,应用日志里没有任何记录。

排查思路:

  1. 先看中间件访问日志,判断请求是否到达应用层。如果中间件日志都没有这条请求的完整记录,基本可以确定是中间件层拦截。
  2. 请求体大小限制、连接超时、单连接速率限制这几类配置都可能卡住大文件上传。
  3. 如果请求到达应用层但Spring报错,才是multipart配置问题。

在信创环境里,中间件配置项的命名和生效逻辑经常和常见版本不一样,通过管理控制台页面修改比直接改配置文件更可靠。改完之后一定要重启验证,并确认配置真正生效。

自定义分块接口的一个额外收益是:单块只有8MB,远低于中间件默认限制,所以改造后完全绕开了这层限制,不用去纠结maxPostSize这类参数。

5.2 国产JDK的NIO实现差异

这是信创适配里最容易暗坑的地方,我分三类来说。

FileChannel.transferTo返回0。合并大文件循环时,某些国产JDK版本在某些文件系统组合下会出现这个问题。代码里遇到返回0时不能简单当作失败结束,要加保护逻辑,连续返回0就退化到read/write循环。这也是我在合并代码里留fallbackCopy方法的原因。

文件路径字符集乱码。操作系统的locale环境变量和JDK默认字符集不一致时,创建临时文件路径可能出现乱码或者找不到文件。这类问题和代码关系不大,是运行环境问题。解决办法是把系统LANG和LC_ALL设置成UTF-8后重启应用,代码里创建路径时用Paths和Path对象拼接,不要手写字符串路径。

SecureRandom初始化慢。某些国产JDK使用原生随机数生成器时初始化性能差,导致第一次调用UUID.randomUUID()时阻塞明显。如果系统里有大量uploadId生成操作,可以用时间戳加进程ID加序列号的方式代替UUID,规避这个初始化问题。

5.3 数据库方言与SQL兼容性问题

分块上传需要记录上传元数据、分块状态,都涉及数据库。信创环境数据库迁移后,常见问题集中在SQL方言上:

  1. 空值判断函数不兼容:ifnull、nvl在不同数据库里写法不同,统一改用标准SQL的COALESCE。
  2. 布尔字段差异:国产数据库对bit类型支持不一致,使用TINYINT或SMALLINT替代。
  3. 日期函数不兼容:sysdate、now()这类写法要统一,能用应用层时间戳就统一用时间戳字段。
  4. 自增主键行为差异:分块表的主键尽量用应用层生成的分布式ID,不依赖数据库自增,避免迁移后主键冲突或生成策略不一致。
  5. 批量插入分块状态时不要用upsert语法,不同国产数据库的upsert方言差异很大。用标准批量insert,需要更新时先delete再insert,逻辑清晰且各个数据库都能跑。

5.4 路径分隔符与临时文件清理问题

开发机Windows和生产环境Linux路径分隔符不一致是经典坑。统一使用Paths和Path对象进行路径拼接,不要手工拼字符串。这些API在跨平台时能自动处理分隔符差异。

临时文件清理我建议用定时任务扫描upload_info表,把状态处于UPLOADING且超过2小时没有更新的记录挑出来,先删数据库记录再删磁盘文件。这个顺序有讲究:如果先删磁盘文件,正在上传的分块可能刚好在写入,文件突然消失导致写失败;先删库记录再删文件,至少保证数据库里不会再新增对旧uploadId的查询。

磁盘空间告警也要做。临时目录所在分区使用率超过阈值时,应该停止接收新分块并返回明确错误码,不能闷头写完把磁盘撑爆。这个阈值我一般设在85%。

我把排障经验整理成一张速查表:

问题现象排查优先级常用解法
413拒绝上传大文件直接失败中间件限制先于框架限制调整配置或改分块接口
合并卡住合并任务长时间不结束JDK版本、文件系统、跨盘transferTo退化为read/write
路径乱码文件找不到或文件名异常系统locale、JDK字符集设置LANG/LC_ALL为UTF-8
假成功数据库有状态但磁盘没文件落盘顺序、清理策略先落盘再写库
磁盘写满上传中断、系统异常清理任务、空间告警独立数据盘加定时清理

这次适配做下来,我最大的体会是:信创环境下的问题很少是新框架引入的,大多数是底层组件行为差异叠加出来的。分块上传本身不是什么新方案,但把它做扎实,把异常降级路径和状态一致性考虑清楚,就能在这套技术栈里稳定跑起来。我们最后把上传做成了一个独立可复用组件,可以继续扩展的点包括对象存储后接、视频分片转码联动、弱网下断点策略动态调整。如果你也在做类似的适配,建议先跑通一个最小闭环,再把边界情况补齐——分块上传不是简单的切文件,而是一套状态一致性与资源管理的组合拳。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 17:48:39

盲盒抽奖移动端系统开发:概率引擎、库存原子性与多端支付回调实战

简介&#xff1a;这是一套面向潮玩盲盒电商创业者的移动端商城系统源码&#xff0c;基于ThinkPHP框架开发&#xff0c;覆盖盲盒抽奖、一番赏、抽盒机等核心玩法&#xff0c;可同时适配H5、公众号与APP多端场景&#xff0c;适合具备PHP基础、希望快速搭建盲盒商城的开发者或运营…

作者头像 李华
网站建设 2026/10/20 17:48:33

SM2证书链验证失败?自建Python验证器绕过cryptography白名单

我最近在好几个国密改造项目里连续踩到同一个坑&#xff1a;证书链上只要出现一张SM2证书&#xff0c;Python的cryptography库就率先抛异常&#xff0c;代码里按官方文档写好的链验证逻辑根本走不到握手成功那一步。报错永远是那一句“Unknown signature algorithm OID”或者“…

作者头像 李华
网站建设 2026/10/20 17:48:33

VS2010 MFC下空间B样条曲线插补算法与速度规划实现

做工业上位机软件这些年&#xff0c;我办公室里还摆着一台装着VS2010的老电脑。不是不想换&#xff0c;是很多在产设备的上位机代码就是从那个时代长出来的——MFC的界面框架、基于对话框的参数面板、一套自定义控件的曲线显示区&#xff0c;牵一发动全身。这次要聊的项目&…

作者头像 李华
网站建设 2026/10/20 17:48:32

C++异构计算适配器:弥合std::execution与GPU之间的鸿沟

如果你平时主要写CPU端的并行代码&#xff0c;你一定用过或至少听说过这些写法&#xff1a;std::for_each(std::execution::par, begin, end, work);。这是C标准库从C17开始送给我们的一份礼物——不用手动创建线程、不用自己拆任务&#xff0c;只要把执行策略从seq换成par&…

作者头像 李华
网站建设 2026/10/20 17:46:34

AI辅助打造中医技能号:碎片时间冷启动全记录

和AI一起搞事情#2&#xff1a;边剥龙虾&边做个中医技能来起号上周末我一个人窝在沙发上剥小龙虾&#xff0c;手机架在旁边刷着各种内容平台&#xff0c;突然意识到一个事儿&#xff1a;我刷到的那些点赞高的账号&#xff0c;大多数并不是什么专业机构做的&#xff0c;而是普…

作者头像 李华
网站建设 2026/10/20 17:46:00

AI Agent Harness Engineering:智能体稳定可靠运行的关键工程体系

AI Agent Harness Engineering&#xff0c;这个词最近在圈子里被反复提起。有人把它和“智能体即操作系统”放在一起讨论&#xff0c;认为未来计算平台的核心不再是大模型本身&#xff0c;而是围绕智能体搭建的那套工程体系。我一开始也觉得这说法有点夸张&#xff0c;但自己动…

作者头像 李华