NVIDIA Dynamo:让AI推理集群告别“GPU忙闲不均”的调度指挥官
2026/10/20 23:43:17
作为公司前端技术负责人,我负责牵头本次大文件传输系统的技术选型与实现方案。基于客户(政府及集团单位)的严格要求,系统需满足以下核心需求:
功能需求:
兼容性需求:
安全需求:
商务需求:
经调研,主流开源方案存在以下问题:
基于项目需求,建议采用自研核心+成熟组件集成的方案:
前端架构:
后端架构:
// file-chunker.jsexportdefaultclassFileChunker{constructor(file,chunkSize=5*1024*1024){this.file=file;this.chunkSize=chunkSize;this.chunks=[];this.initChunks();}initChunks(){consttotalChunks=Math.ceil(this.file.size/this.chunkSize);for(leti=0;i<totalChunks;i++){conststart=i*this.chunkSize;constend=Math.min(start+this.chunkSize,this.file.size);this.chunks.push({index:i,start,end,blob:this.file.slice(start,end)});}}// 生成文件唯一标识(基于内容+名称+大小)generateFileId(){returnthis.file.name+this.file.size+this.file.lastModified;}}// upload-manager.jsimportFileChunkerfrom'./file-chunker';importCryptoServicefrom'./crypto-service';exportdefaultclassUploadManager{constructor(apiUrl){this.apiUrl=apiUrl;this.crypto=newCryptoService();this.progressStore=this.initProgressStore();}initProgressStore(){// 使用localStorage+IndexedDB双存储方案conststore={get(fileId){try{constdata=localStorage.getItem(`upload_${fileId}`);returndata?JSON.parse(data):null;}catch(e){returnnull;}},set(fileId,progress){try{localStorage.setItem(`upload_${fileId}`,JSON.stringify(progress));// 同步到IndexedDB(代码省略)}catch(e){console.error('Progress store error:',e);}}};returnstore;}asyncuploadFile(file){constfileChunker=newFileChunker(file);constfileId=fileChunker.generateFileId();constexistingProgress=this.progressStore.get(fileId);// 从断点继续letstartChunk=0;if(existingProgress){startChunk=existingProgress.completedChunks;}for(leti=startChunk;i<fileChunker.chunks.length;i++){constchunk=fileChunker.chunks[i];constformData=newFormData();// 加密分片数据constencryptedData=awaitthis.crypto.encrypt(chunk.blob);formData.append('file',encryptedData,`chunk_${chunk.index}`);formData.append('fileId',fileId);formData.append('chunkIndex',chunk.index);formData.append('totalChunks',fileChunker.chunks.length);try{awaitaxios.post(`${this.apiUrl}/upload`,formData,{onUploadProgress:(progressEvent)=>{// 更新进度存储constprogress={completedChunks:i,totalChunks:fileChunker.chunks.length,uploadedBytes:progressEvent.loaded,totalBytes:progressEvent.total};this.progressStore.set(fileId,progress);}});}catch(error){console.error(`Chunk${i}upload failed:`,error);throwerror;// 可以根据需求实现重试机制}}// 上传完成通知awaitthis.notifyComplete(fileId);return{success:true,fileId};}}// ie-polyfill.js// 基础兼容处理import'babel-polyfill';import'core-js/features/promise';import'core-js/features/array/from';import'core-js/features/object/assign';// 自定义事件兼容if(!window.CustomEvent){window.CustomEvent=function(event,params){params=params||{bubbles:false,cancelable:false,detail:undefined};constevt=document.createEvent('CustomEvent');evt.initCustomEvent(event,params.bubbles,params.cancelable,params.detail);returnevt;};window.CustomEvent.prototype=window.Event.prototype;}// XMLHttpRequest兼容增强constoriginalOpen=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(method,url){// IE8 URL处理if(window.XDomainRequest&&!window.XMLHttpRequest.prototype.withCredentials){// 降级处理逻辑(代码省略)}originalOpen.apply(this,arguments);};@RestController@RequestMapping("/api/upload")publicclassUploadController{@AutowiredprivateChunkStorageServicechunkStorageService;@AutowiredprivateProgressServiceprogressService;@PostMappingpublicResponseEntityuploadChunk(@RequestParam("file")MultipartFilefile,@RequestParam("fileId")StringfileId,@RequestParam("chunkIndex")intchunkIndex,@RequestParam("totalChunks")inttotalChunks){try{// 1. 存储分片数据chunkStorageService.saveChunk(fileId,chunkIndex,file.getBytes());// 2. 更新进度信息progressService.updateProgress(fileId,chunkIndex,totalChunks);returnResponseEntity.ok(newUploadResponse(true,"Chunk uploaded successfully"));}catch(Exceptione){returnResponseEntity.status(500).body(newUploadResponse(false,"Upload failed: "+e.getMessage()));}}@GetMapping("/progress")publicResponseEntitygetProgress(@RequestParamStringfileId){ProgressInfoprogress=progressService.getProgress(fileId);returnResponseEntity.ok(progress);}@PostMapping("/merge")publicResponseEntitymergeFile(@RequestBodyMergeRequestrequest){try{// 合并分片逻辑(代码省略)StringfilePath=chunkStorageService.mergeChunks(request.getFileId(),request.getFileName());// 解密存储(根据配置使用SM4/AES)cryptoService.decryptAndStore(filePath,request.getEncryptionType());returnResponseEntity.ok(newMergeResponse(true,filePath));}catch(Exceptione){returnResponseEntity.status(500).body(newMergeResponse(false,"Merge failed: "+e.getMessage()));}}}@ServicepublicclassProgressServiceImplimplementsProgressService{@AutowiredprivateProgressRepositoryprogressRepository;@OverridepublicvoidupdateProgress(StringfileId,intcompletedChunks,inttotalChunks){Optionalexisting=progressRepository.findById(fileId);UploadProgressprogress=existing.orElseGet(()->{UploadProgressnewProgress=newUploadProgress();newProgress.setFileId(fileId);returnnewProgress;});progress.setCompletedChunks(completedChunks);progress.setTotalChunks(totalChunks);progress.setLastUpdated(newDate());progressRepository.save(progress);}@OverridepublicProgressInfogetProgress(StringfileId){OptionalprogressOpt=progressRepository.findById(fileId);returnprogressOpt.map(p->newProgressInfo(p.getFileId(),p.getCompletedChunks(),p.getTotalChunks(),calculatePercentage(p.getCompletedChunks(),p.getTotalChunks()))).orElse(null);}privatedoublecalculatePercentage(intcompleted,inttotal){returntotal>0?((double)completed/total)*100:0;}}龙芯浏览器:
红莲花浏览器:
奇安信浏览器:
统信UOS/中标麒麟/银河麒麟:
Windows 7+IE8:
// 动态数据源配置示例@ConfigurationpublicclassDataSourceConfig{@Bean@Primary@ConfigurationProperties(prefix="spring.datasource.mysql")publicDataSourcemysqlDataSource(){returnDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix="spring.datasource.oracle")publicDataSourceoracleDataSource(){returnDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix="spring.datasource.dameng")publicDataSourcedamengDataSource(){returnDataSourceBuilder.create().build();}// 其他数据源...}// 加密存储服务示例@ServicepublicclassCryptoStorageService{@Value("${crypto.algorithm:SM4}")// 默认使用SM4privateStringcryptoAlgorithm;publicvoidencryptAndStore(StringfilePath,byte[]data){try{byte[]encryptedData;if("SM4".equalsIgnoreCase(cryptoAlgorithm)){encryptedData=sm4Encrypt(data);}else{encryptedData=aesEncrypt(data);}Files.write(Paths.get(filePath),encryptedData);}catch(Exceptione){thrownewCryptoException("Encryption failed",e);}}privatebyte[]sm4Encrypt(byte[]data){// SM4加密实现(使用BouncyCastle等库)// 代码省略...}privatebyte[]aesEncrypt(byte[]data){// AES加密实现// 代码省略...}}第一阶段(1个月):
第二阶段(1.5个月):
第三阶段(1个月):
第四阶段(0.5个月):
基于项目需求,建议采购方案:
源代码授权:
替代方案:
风险控制:
本方案通过自研核心上传下载引擎,结合成熟加密和存储方案,能够全面满足客户的大文件传输需求。建议尽快启动技术预研,与国产软硬件厂商建立合作,确保在信创环境下的兼容性。同时,建议组建专门的项目组,包括前端、后端、测试和安全专家,确保项目按时高质量交付。
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
支持文件批量下载
文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。
支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。
下载完整示例