22_1, 接口处理方式要明确同步还是异步, 如文件上传图片返回图片连接和缩略图链接

有一个文件上传服务FileService,其中一个upload文件上传接口特别慢,原因是这个上传接口在内部需要进行两步操作,首先上传原图,然后
压缩后上传缩略图。如果每一步都耗时5秒的话,那么这个接口返回至少需要10秒的时间。

两个步骤如果都异步会出现下图问题
在这里插入图片描述

更合理的方式是,让上传接口要么是彻底的同步处理,要么是彻底的异步处理:

1. 所谓同步处理,接口一定是同步上传原文件和缩略图的,调用方可以自己选择调用超时,如果来得及可以一直等到上传完成,如果等不及 可以结束等待,下一次再重试;
2. 所谓异步处理,接口是两段式的,上传接口本身只是返回一个任务ID,然后异步做上传操作,上传接口响应很快,客户端需要之后再拿 着任务ID调用任务查询接口查询上传的文件URL。

在接口实现上,我们同样把上传任务提交到线程池处理,但是并不会同步等待任务完成,而是完成后把结果写入一个HashMap,任务查询接口通过查询这个HashMap来获得文件的URL:

//计数器,作为上传任务的ID
private AtomicInteger atomicInteger = new AtomicInteger(0);

//暂存上传操作的结果,生产代码需要考虑数据持久化
private ConcurrentHashMap<String, SyncQueryUploadTaskResponse> downloadUrl = new ConcurrentHashMap<>();

//异步上传操作
public AsyncUploadResponse asyncUpload(AsyncUploadRequest request) {
	AsyncUploadResponse response = new AsyncUploadResponse();
	//生成唯一的上传任务ID
	String taskId = "upload" + atomicInteger.incrementAndGet();
	//异步上传操作只返回任务ID
	response.setTaskId(taskId);
	//提交上传原始文件操作到线程池异步处理
	threadPool.execute(() -> {
		String url = uploadFile(request.getFile());
	
	//如果ConcurrentHashMap不包含Key,则初始化一个SyncQueryUploadTaskResponse,然后设置DownloadUrl
	downloadUrl.computeIfAbsent(taskId, id -> new SyncQueryUploadTaskResponse(id)).setDownloadUrl(url);
	});
	//提交上传缩略图操作到线程池异步处理
	threadPool.execute(() -> {
		String url = uploadThumbnailFile(request.getFile());
		downloadUrl.computeIfAbsent(taskId, id -> new SyncQueryUploadTaskResponse(id)).setThumbnailDownloadUrl(url);
	});
return response;
}

文件上传查询接口则以任务ID作为入参,返回两个文件的下载地址,因为文件上传查询接口是同步的,所以直接命名为syncQueryUploadTask:

//syncQueryUploadTask接口入参
@Data
@RequiredArgsConstructor
public class SyncQueryUploadTaskRequest {
	private final String taskId;//使用上传文件任务ID查询上传结果
	} /
	
/syncQueryUploadTask接口出参
@Data
@RequiredArgsConstructor
public class SyncQueryUploadTaskResponse {
	private final String taskId; //任务ID
	private String downloadUrl; //原始文件下载URL
	private String thumbnailDownloadUrl; //缩略图下载URL
} 

public SyncQueryUploadTaskResponse syncQueryUploadTask(SyncQueryUploadTaskRequest request) {
	SyncQueryUploadTaskResponse response = new SyncQueryUploadTaskResponse(request.getTaskId());
	//从之前定义的downloadUrl ConcurrentHashMap查询结果
	response.setDownloadUrl(downloadUrl.getOrDefault(request.getTaskId(), response).getDownloadUrl());
	response.setThumbnailDownloadUrl(downloadUrl.getOrDefault(request.getTaskId(), response).getThumbnailDownloadUrl());
	return response;
}

经过改造的FileService不再提供一个看起来是同步上传,内部却是异步上传的upload方法,改为提供很明确的:

搭配syncQueryUploadTask查询上传结果。使用方可以根据业务性质选择合适的方法:如果是后端批处理使用,那么可以使用同步上传,多等待一些时间问题不大;如果是面向用户的接口,那么接口响应时间不宜过长,可以调用异步上传接口,然后定时轮询上传结果,拿到结果再显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值