Java负载均衡服务器实现上传文件同步
负载服务器Z,应用服务器A和B,从A上传的附件,如何在B上下载下来?
这个问题我的解决思路如下(后来被一个装逼的面试官给批评了这种做法,不过我瞧不起他)
服务器A、B上传附件的时候,将这个附件备份到服务器Z,当A、B下载文件的时候,首先会在自己服务器的目录下寻找,如果找不到,就会从服务器Z上下载一份到当前服务器。
服务器之间的文件备份通过sftp,参考:https://www.nhooo.com/article/196008.htm(下文中的SftpCustom类就是这个链接里的“SFTP上传下载文件例子”中的类)
这里主要介绍一下重写上传、下载的方法时应该添加的代码
上传文件,异步操作
newThread(()->{
SftpCustomfu=newSftpCustom();
fu.upload(file.getAbsolutePath(),getFileName(fileDescr));
fu.closeChannel();
}).start();
下载文件,先从当前服务器寻找
StringtmpPath=roots[0].getPath()+'/'+getFileName(fileDescr);
Filefile2=newFile(tmpPath);
if(file2.exists()){
returnFileUtils.openInputStream(file2);
}
SftpCustomfu=newSftpCustom();
fu.download(getFileName(fileDescr),tmpPath);
file2=newFile(tmpPath);
inputStream=FileUtils.openInputStream(file2);
fu.closeChannel();
returninputStream;
cuba框架中重写上传文件类FileStorage.java的代码如下:
packagecom.haulmont.cuba.core.app.custom;
importcom.google.common.util.concurrent.ThreadFactoryBuilder;
importcom.haulmont.cuba.core.app.FileStorageAPI;
importcom.haulmont.cuba.core.app.ServerConfig;
importcom.haulmont.cuba.core.entity.FileDescriptor;
importcom.haulmont.cuba.core.global.*;
importcom.haulmont.cuba.core.sys.AppContext;
importcom.haulmont.cuba.core.sys.SecurityContext;
importorg.apache.commons.io.FileUtils;
importorg.apache.commons.io.IOUtils;
importorg.apache.commons.lang.StringUtils;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importjavax.annotation.PostConstruct;
importjavax.annotation.PreDestroy;
importjavax.inject.Inject;
importjava.io.*;
importjava.nio.charset.StandardCharsets;
importjava.text.SimpleDateFormat;
importjava.util.ArrayList;
importjava.util.Calendar;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importstaticcom.haulmont.bali.util.Preconditions.checkNotNullArgument;
publicclassFileStorageimplementsFileStorageAPI{
privatefinalLoggerlog=LoggerFactory.getLogger(FileStorage.class);
@Inject
protectedUserSessionSourceuserSessionSource;
@Inject
protectedTimeSourcetimeSource;
@Inject
protectedConfigurationconfiguration;
protectedbooleanisImmutableFileStorage;
protectedExecutorServicewriteExecutor=Executors.newFixedThreadPool(5,
newThreadFactoryBuilder().setNameFormat("FileStorageWriter-%d").build());
protectedvolatileFile[]storageRoots;
@PostConstruct
publicvoidinit(){
this.isImmutableFileStorage=configuration.getConfig(ServerConfig.class).getImmutableFileStorage();
}
/**
*INTERNAL.Don'tuseinapplicationcode.
*/
publicFile[]getStorageRoots(){
if(storageRoots==null){
Stringconf=configuration.getConfig(ServerConfig.class).getFileStorageDir();
if(StringUtils.isBlank(conf)){
StringdataDir=configuration.getConfig(GlobalConfig.class).getDataDir();
Filedir=newFile(dataDir,"filestorage");
dir.mkdirs();
storageRoots=newFile[]{dir};
}else{
Listlist=newArrayList<>();
for(Stringstr:conf.split(",")){
str=str.trim();
if(!StringUtils.isEmpty(str)){
Filefile=newFile(str);
if(!list.contains(file))
list.add(file);
}
}
storageRoots=list.toArray(newFile[list.size()]);
}
}
returnstorageRoots;
}
@Override
publiclongsaveStream(finalFileDescriptorfileDescr,finalInputStreaminputStream)throwsFileStorageException{
checkFileDescriptor(fileDescr);
File[]roots=getStorageRoots();
//Storetoprimarystorage
checkStorageDefined(roots,fileDescr);
checkPrimaryStorageAccessible(roots,fileDescr);
Filedir=getStorageDir(roots[0],fileDescr);
dir.mkdirs();
checkDirectoryExists(dir);
finalFilefile=newFile(dir,getFileName(fileDescr));
checkFileExists(file);
longsize=0;
OutputStreamos=null;
try{
os=FileUtils.openOutputStream(file);
size=IOUtils.copyLarge(inputStream,os);
os.flush();
writeLog(file,false);
newThread(()->{
SftpCustomfu=newSftpCustom();
fu.upload(file.getAbsolutePath(),getFileName(fileDescr));
fu.closeChannel();
}).start();
}catch(IOExceptione){
IOUtils.closeQuietly(os);
FileUtils.deleteQuietly(file);
thrownewFileStorageException(FileStorageException.Type.IO_EXCEPTION,file.getAbsolutePath(),e);
}finally{
IOUtils.closeQuietly(os);
}
//Copyfiletosecondarystoragesasynchronously
finalSecurityContextsecurityContext=AppContext.getSecurityContext();
for(inti=1;i
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。