Zuul官网关于文件上传的说明
小文件可以正常工作,大文件需要通过/zuul/*这个替代路径来绕过spring(避免进行多部分处理)。另外大文件上传需要提高超时设置。
关于zuul的dispatcherServlet和zuulServlet,一般情况下zuulServlet被嵌入到Dispatch机制中,由DispatcherServlet分派处理,这样可以控制路由,并缓冲请求。如果需要绕过multipart处理,在不缓冲请求的情况下通过zuul,zuulServlet也可以装载在DIspatcher之外,让请求绕过DispatcherServlet。
DispatcherServlet为了方便后续处理流程使用,会将multipart/form请求根据RFC1867规则进行统一分析处理,并且返回MultipartHttpServletRequest实例,通过它可获取file和其他参数,这个过程会影响性能。
处理multipart/form请求的核心代码:
具体配置
一、zuul路由配置
serviceId映射:
zuul:
routes:
publicCommon:
path: /myyule-public-common/**
service-id: myyule-public-common
二、 ribbon及hystrix超时配置
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 900000
myyule-public-common:
ribbon:
ReadTimeout: 600000
ConnectTimeout: 600000
三、 文件上传请求地址加上zuul/
四、 文件上传耗时分析
上传一个大文件(约250M),跟踪请求日志打印如下:
主要耗时在网关到进入文件上传方法内部这一段,其中网关耗时应该较少,因为已经通过zuul/路径绕过了网关对文件的处理,所以分析主要耗时原因在接收MultipartFile这个参数这里。
MultipartFile对象的封装过程:
1.spring检测请求,是否是multipart,不是则返回http request,是,解析resolveMultipart(request) 返回默认的 DefaultMultipartHttpServletRequest。
2.将MultipartParsingResult参数融合在一起,就形成了DefaultMultipartHttpServletRequest对象;在这个对象可以拿到上传的文件MultipartFile
3.MultipartFile的由来。
CommonsMultipartFile file = createMultipartFile(fileItem);
FileItem fileItem = fac.createItem(item.getFieldName(),
item.getContentType(), item.isFormField(), fileName);
Streams.copy(item.openStream(), fileItem.getOutputStream(),
true);
MultipartFile由流复制而来。FileItem由FileItemFactory 接口创建,FileItemFactory默认由DiskFileItemFactory 实现。当上传的文件项目比较小时,直接保存在内存中(速度比较快),比较大时,以临时文件形式,保存在磁盘临时文件夹(速度较慢)。
属性:1) public static final int DEFAULT_SIZE_THRESHOLD :将文件保存在内存还是磁盘临时文件夹的默认临界值,值为10240,即10kb。
小结:大文件上传流程:(1)客户端发起上传请求——(2)网关接收请求并识别到zuul/路径,不对文件流进行处理直接放行——(3)请求转发到上传服务,先对文件流进行解析,将文件写到服务器本地(这一过程涉及到磁盘写入)——(4)上传文件业务处理并调用fastdfs——(5)返回上传结果。耗时主要在第三步。