今天遇到一个问题,在Controller 层里面,直接使用MultipartFile 来接收上传的图片,遇到几个坑。
一、在spring配置文件里面配置文件上传

 <!--文件上传--><bean name="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver" ><property name="defaultEncoding" value="UTF-8" /><property name="maxUploadSize" value="5242880" /></bean>

我在Controller层和service层的spring配置文件里面都设置了这个配置。
二、怎么实现实现远程调用
看了看MultipartFile的源码发现,这东西是一个接口,其实传进来的是他的一个commons实现类而已,dubbo明显不能跨系统传递这个对象,自己当初一直报invoke method 错误,百度了一下,发现另一个好用的Hessian

pom文件,我的provider和consumer都有这个

     <dependency><groupId>com.caucho</groupId><artifactId>hessian</artifactId><version>4.0.7</version></dependency><dependency><groupId>org.mortbay.jetty</groupId><artifactId>jetty</artifactId><version>6.1.26</version></dependency>

在service层就是我们的provider里面将需要的服务注册成Hessian协议的就可以了。
我的spring-service.xml

  <!-- 提供方应用信息,用于计算依赖关系 --><dubbo:application name="taotao-manager-service-cxl" /><dubbo:registry protocol="zookeeper" address="192.168.11.131:2181" /><!-- 用dubbo协议在20880端口暴露服务 --><dubbo:protocol name="dubbo" port="20880" /><dubbo:protocol name="hessian" port="20887"/><!-- 声明需要暴露的服务接口 --><dubbo:service protocol="dubbo" interface="com.fengqu.service.SaveItemAndDesc" ref="saveItemAndDescImpl"/><dubbo:service protocol="hessian" interface="com.fengqu.service.UploadImageService" ref="uploadImageImpl"/>

然后look一下dubbo-amdin


注册上了

consumer消费者那儿注册一下
我的spring-mvc.xml

<!-- 引用dubbo服务 --><dubbo:application name="taotao-web-cxl"/><dubbo:registry protocol="zookeeper" address="192.168.11.131:2181"/><dubbo:reference protocol="dubbo" interface="com.fengqu.service.SaveItemAndDesc" id="saveItemAndDescImpl"/><dubbo:reference protocol="hessian" interface="com.fengqu.service.UploadImageService" id="uploadImageImpl"/>

dubbo-amdin也注册上了,就不贴图了。

发现能传递这个对象了,但是最后发现MultipartFile.getInputStream() 拿不到InputStream了,没办法只能用byte数组来传递这个InputStream了。

Controller

import org.apache.commons.io.IOUtils;byte[] arr = null;try {arr = IOUtils.toByteArray(uploadFile.getInputStream());}...

service

new ByteArrayInputStream(arr)

ok了,最后图片上传成功



Dubbo文件上传/传输服务

本篇介绍如何设计一个文件上传/传输功能的dubbo接口及遇到的问题;

背景

  1. 在B端业务下,上传文件服务未做好收口,由于历史原因,代码中有各种调用文件服务Client的场景,并且针对不同的业务场景或文件类型,写了不同的方法逻辑;

  2. 文件上传,入口一般是Controller参数里面的MultipartFile,涉及流的读取和传输,需要做好流的关闭,否则容易导致内存泄漏OOM;

  3. 现存的各种文件上传的Service,使用了不同系统的文件上传client(client初始化时需要跟系统的appkey和appSecret绑定),可能是为了拿到各系统CDN域名的URL;不同的appkey和appSecret难以区分和维护;

准备方案

使用内部core服务的dubbo接口,将文件上传的服务给收口,兼容不同文件类型、不同场景的文件上传,对内部其他服务屏蔽上传实现的细节;

解决过程

先说结论——dubbo不适合用来做上传接口;

更好的方案——使用client方式打成内部二方包,在各个应用中配置原上传服务的client和当前二方包收口的上传服务的bean,在代码中调用即可;

在实现过程中尝试过做一个dubbo接口来实现上传服务,过程和问题记录如下;

1. 接口定义

因为接口参数需要包含传输文件,任意文件都是二进制流,因此使用byte[ ]来传输文件数据;

public interface UploadFileFacade {/*** 上传文件 返回url 注意:上传接口存在cdn缓存 短时间内重复调用返回的文件url 下载的文件可能相同* 注意:dubbo的单次传输数据包大小默认8M 可通过修改dubbo.protocol.payload参数调整但此请求满足的数据包大小** @return*/FacadeDefaultDTO<UploadRespDTO> upload(@Valid UploadReqDTO reqDTO);}

入参除了文件字节流,其他的参数有文件名、文件类型;

@Data
public class UploadReqDTO implements Serializable {/*** fileBytes** @see File2BytesTemplate*/@NotNullprivate byte[] bytes;/*** fileName without file extend name** @see UploadReqDTO#fileType*/@NotNullprivate String fileName;/*** fileName with file extend name** @see com.vivo.internet.cp.resource.center.facade.inner.enums.FileTypeEnum*/@NotNullprivate FileTypeEnum fileType;}

返参目前仅包含文件上传后的CDN下载地址,后序可以扩展字段,如文件的有效期、大小等;

@Data
public class UploadRespDTO implements Serializable {/*** downloadUrl using CDN domain*/private String downloadUrl;}

2. 遇到的的问题

(1)性能分析

首先dubbo不适合传输大文件数据;

dubbo协议采用单一长连接,举例:如果每次dubbo请求的数据包大小为500KByte,假设:

(1) 网络为千兆网卡(1024Mbit/8=128MByte)
(2) 每条连接最大7MByte(不同的环境可能不一样,供参考)

则:

  1. 单个服务提供者的TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。
  2. 单个消费者,调用单个服务提供者的TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14

如果能接受,可以考虑使用,否则网络将成为瓶颈;

(2)dubbo数据包大小限制

dubbo每次传输数据包大小默认是8Mb,也就是8388608bit;(8 * 1024 * 1024 = 8388608)

单次dubbo请求的数据包超过这个大小,会报错:

 cause: Data length too large: 36304917, max payload: 8388608, channel: NettyChannel

注意这里说的"数据包大小"针对的是整体参数大小,而不是单个请求参数的大小;

这个"数据包大小"可以通过修改dubbo的配置参数修改,有以下方式;

方式1:通过修改全局配置,这个配置在protocol下;可以在 application.properties 中添加以下配置来修改

#dubbo protocol相关配置#可不配置;如果未设置,默认端口为-1,随机端口
dubbo.protocol.port=13300#可不配置;如果未设置,默认为dubbo
dubbo.protocol.name=dubbo#dubbo服务限制大数据传输,最大限制为8M,这里设置为50Mb
dubbo.protocol.payload=52428800

吐槽一下,部分搜到的帖子里说的配置是 dubbo.protocol.dubbo.payload=11557050,试了是不行,我的dubbo是2.7.12,难道是老版本这样配置?其实最科学的办法还是去官网dubbo:protocol | Apache Dubbo找答案,拼接出来的参数也就是 dubbo.protocol.payload;

方式2:修改单个指定provider的protocol(这个方法还没有验证);在下注册provider的地方加上dubbo:protocol属性

    <dubbo:service interface="com.AA.facade.SelfOperateFacade" ref="selfOperateFacade" version="1.0.0" timeout="3000"><dubbo:parameter key="payload" value="52428800"/></dubbo:service>

(3)修改dubbo配置后启动遇到的"Caused by: java.lang.IllegalStateException: Invalid name=“org.apache.dubbo.config.ProtocolConfig#0” contains illegal character, only digit, letter, ‘-’, ‘_’ or ‘.’ is legal."

解决方案:application.properties 中配置dubbo.protocol.name,重启服务,问题解决;

dubbo.protocol.name=dubbo

(4)调试时IDEA弹窗报错"There is not enough memory to perform the requested operation"

参考了这篇文章IDEA报错There is not enough memory to perform the requested operation,直接在弹窗修改是不行的;于是进入"Help->Edit Custom VM Options"修改,重启IDEA,问题解决;

(5)调试时dubbo报错"Invoke remote method timeout"

org.apache.dubbo.rpc.RpcException: Failfast invoke providers XX
RandomLoadBalance select from all providers (count: 1) for service com.AA.facade.inner.UploadFileFacade method upload on consumer XX use dubbo version 2.7.8.13-VIVO, but no luck to perform the invocation.
Last error is: Invoke remote method timeout. ...

顾名思义,就是dubbo的server响应超时了,想想也是,文件上传场景非常见的快速调用,接口响应时间应该放宽,设置timeout=10000(10秒),重启调试,问题解决;

@DubboService(version = "1.0.0", timeout = 10000)
public class UploadFileFacadeImpl implements UploadFileFacade {...}

参考:

官方中文文档 | Apache Dubbo

Dubbo系统里面MultipartFile文件传输问题Dubbo文件上传/传输服务相关推荐

  1. 大文件传输解决方案:分片上传 / 下载限速

    前言 不少项目中会遇到上传下载视频.更新包.应用程序等文件,此类文件的共同点就是十分巨大,我在项目中遇到过 4G 左右的文件同时 100 多台机器下载,此时如果用 post 上传和下载想一下都不可能, ...

  2. ajax上传 java_使用Ajax进行文件与其他参数的上传功能(java开发)

    文件上传: 记得前一段时间,为了研究Ajax文件上传,找了很多资料,在网上看到的大部分是form表单的方式提交文件,对于Ajax方式提交文件并且也要提交表单中其他数据,发现提及的并不是很多,后来在同事 ...

  3. ssh怎么ftp上传文件到服务器,ssh ftp上传文件到服务器

    ssh ftp上传文件到服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器上分别 ...

  4. 上传excel文件到服务器,excel怎么上传到云服务器

    excel怎么上传到云服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器上分别安 ...

  5. web上传文件到ftp服务器,web 上传文件到ftp服务器上

    web 上传文件到ftp服务器上 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器上分 ...

  6. apk文件部署到云服务器,上传apk到云服务器

    上传apk到云服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器上分别安装数据传 ...

  7. js上传文件到c 服务器,js上传文件到c服务器

    js上传文件到c服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器上分别安装数据 ...

  8. shell上传文件到服务器,shell脚本上传文件到ftp服务器

    shell脚本上传文件到ftp服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具,将文件上传到云服务器.例如QQ.exe.在本地主机和Windows云服务器 ...

  9. xshell上传本地文件命令_linux学习 XShell上传、下载本地文件到linux服务器

    (一)通过命令行的方式 1.linux服务器端设置 在linux主机上,安装上传下载工具包rz及sz; 如果不知道你要安装包的具体名称,可以使用yum provides */name 进行查找系统自带 ...

最新文章

  1. Kali Linux 初上手记录 初始版本1.0.9
  2. 百度地图infowindow
  3. xshell linux托文件夹,Xshell拖拽文件到linux(rz和sz命令用法详解)
  4. r语言 面板数据回归_R语言_018回归
  5. 数据结构六——堆的应用
  6. android 画中画模式自定义,Android 8.0 Oreo 画中画模式
  7. 视频剪辑软件Movie Studio安装教程
  8. PHP接口报错:500服务器错误
  9. 小刘同学的CMOS模拟集成电路学习小记(不停更新)
  10. 淘宝客佣金设置多少合适?淘宝客的佣金是怎么算的?
  11. 火箭08-09赛程列表
  12. 自学linux驱动从入门到放弃(四)配置rk3288开发板与ubuntu18.04的IP地址
  13. php 发邮件 上传附件,PHPMailer实现PHP的邮件发送,附带附件
  14. NBA最伟大的50位球星
  15. 计算机word基础操作知识点,Office基础和计算机操作基础的知识点(一)
  16. 鱼和熊掌兼得!这些应用是如何使用 Material Design 的?
  17. 1093. 大样本统计-正常统计
  18. Exif Editor For Mac(图像EXIF编辑器软件)
  19. 从前台获取数据,并导出PDF文件
  20. Windows开机无法进入bios模式怎么处理

热门文章

  1. nginx服务器的文档根目录,nginx更改根目录
  2. Linux内核转储---Kdump,Crash使用介绍
  3. (记录)华为机试练习题13—句子逆序
  4. 【Bug】steam双方都是国区 礼物无法入库问题
  5. 用webbroswer控件自动点击确定按钮
  6. [转载] 罗辑思维的「成功」之道
  7. Mac重装OS X系统教程
  8. 2019年4月中国编程语言排行榜,java占有率一骑绝尘,python工资领先
  9. 从塞上明珠到科创新城 榆林数字经济的“速度与激情”
  10. Learning Entity and Relation Embeddings for Knowledge Graph Completion (TransR)论文翻译