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

今天遇到一个问题,在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."

img

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

dubbo.protocol.name=dubbo

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

img

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

img

(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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554741.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dubbo2.7文档详解

本篇博文参考dubbo官方文档 本编博文参考javaguide之rpc 文章目录一.RPC1.1 什么是 RPC?1.2 为什么要用 RPC?1.3 RPC 能帮助我们做什么呢&#xff1f;1.4 RPC 的原理是什么?1.5 常见的 RPC 框架总结二.既有 HTTP ,为啥用 RPC 进行服务调用?2.1 RPC只是一种设计而已2.2 HTTP…

12nm 制程、Zen+ 微架构 AMD Ryzen 7 2700X 处理器详细测试 - 电脑领域 HKEPC Hard

12nm 制程、Zen 微架构 AMD Ryzen 7 2700X 处理器详细测试 代号 Pinnacle Ridge、AMD 第二代 Ryzen 处理器正式登场&#xff0c;基于经改良的 Zen 微架构&#xff0c;改善了 Cache 及记忆体延迟表现&#xff0c;更先进的 12nm LP 制程&#xff0c;令核心时脉进一步提升&#…

Java之Serializable接口实现序列化和反序列化实例以及部分序列化的四种方法

首先需要明确的概念: 序列化&#xff1a;将数据结构或对象转换成二进制字节流的过程反序列化&#xff1a;将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程持久化&#xff1a;将数据写入文件中长久保存的过程称之为持久化序列化主要目的&#xff1a;是…

win10死机频繁怎么解决

Windows 10已经推出好几年&#xff0c;系统趋于稳定&#xff0c;但依旧不是完美&#xff0c;蓝屏、死机状态还是会出现&#xff0c;只是概率降低了很多&#xff0c;如果你的电脑遇到了突然死机或者频繁卡死的情况&#xff0c;或许你应该考虑对电脑进行重置了。系统自带的恢复重…

Jar包常见的反编译工具介绍与使用

反编译JAR能干什么: 排查问题、分析商业软件代码逻辑&#xff0c;学习优秀的源码思路。 反编译工具介绍 JD-GUI 下载地址&#xff1a;http://java-decompiler.github.io/ 点评&#xff1a;支持的java版本不会太高&#xff0c;中文注释能够正常显示。 Luyten 下载地址&#…

400 bad request的原因意思和解决方法

我们的电脑在使用的过程中&#xff0c;有的小伙伴在上网的时候可能就遇到过系统提示&#xff1a;400 bad request的情况。据小编所知这种情况&#xff0c;大致意思就是出现了错误的请求或者请求不能满足。原因是因为我们请求的语法格式出现呢错误或者其他情况等等。我们可以通过…

重装系统win10提示磁盘布局不受UEFI固件支持怎么办

原因分析&#xff1a; Win10系统新增UEFI检测机制&#xff0c;在BIOS开启了UEFI时&#xff0c;如果硬盘分区表格式不是GPT&#xff0c;则会提示无法重装系统win10&#xff0c;也就是说UEFIGPT或LegacyMBR才能安装win10。 解决方法一&#xff1a;关闭UEFI 1、重启系统时按Del…

win7按f8后没有进入安全模式怎么解决

win7f8后没有进入安全模式&#xff0c;在正确操作按F8没有进入安全模式之后&#xff0c;不知道怎么解决win7按f8后没有进入安全模式怎么解决&#xff0c;其实非常的简单&#xff0c;下面来看看详细的解决方法吧。 win7按f8后没有进入安全模式怎么解决 第一种方法&#xff1a;…

电脑开机就进入bios的解决方法

最近很多人反映自己的电脑一开机就直接进入bios里&#xff0c;无法正常进入系统。这是怎么回事呢?开机进入bios无法进入系统怎么办呢?别着急&#xff0c;今天就为大家带来电脑开机就进入bios的解决方法。 电脑开机就进入bios的解决方法&#xff1a; 1、如果是电脑的硬盘出了…

Serializable序列化和Externalizable序列化与反序列化的使用

1、序列化是干啥用的&#xff1f; 序列化的原本意图是希望对一个Java对象作一下“变换”&#xff0c;变成字节序列&#xff0c;这样一来方便持久化存储到磁盘&#xff0c;避免程序运行结束后对象就从内存里消失&#xff0c;另外变换成字节序列也更便于网络运输和传播&#xff…

Win10系统如何查看电脑是否是UEFI启动模式

Win10系统如何查看电脑是否是UEFI启动模式?现在越来越多的新电脑都采用UEFI来引导电脑系统&#xff0c;UEFI提高了开机后操作系统的启动速度&#xff0c;使电脑更加流畅&#xff0c;安全性更强&#xff0c;而传统的BIOS则没有UEFI用起来那么好。如何查看自己Win10系统电脑是否…

win10如何关闭Windows Defender安全保护程序

win10如何关闭Windows Defender安全保护程序&#xff1f;win10如何关闭Windows Defender安全保护程序?在安装的windows操作系统中&#xff0c;自带着安全保护程序“Windows Defender应用”&#xff0c;其实主要是为了保护好其他运行的软件&#xff0c;那该怎么来关闭这个软件呢…

2020-12-11

bios怎么恢复出厂设置? 1 第一步 打开电脑 在电脑出现开机提示时按下热键(一般是del或F2)就可以进入到bios设置界面 2 第二步 在bios设置界面中找到并选择“Load Optimized Default”&#xff0c; 然后按下回车键 3 第三步 在弹出窗口中选择“OK“ 然后回车键确定即可 …

JAVA序列化和反序列化的底层实现原理解析 更新时间:2019年11月27日 14:38:39 作者:myseries 这篇文章主要介绍了JAVA序列化和反序列化的底层实现原理解析,文中通

一、基本概念 1、什么是序列化和反序列化 &#xff08;1&#xff09;Java序列化是指把Java对象转换为字节序列的过程&#xff0c;而Java反序列化是指把字节序列恢复为Java对象的过程&#xff1b; &#xff08;2&#xff09;序列化&#xff1a;对象序列化的最主要的用处就是在…

笔记本电脑重启快捷键是什么

品牌型号&#xff1a;联想小新Air-14 2020 系统&#xff1a;win10 1909 64位企业版 部分用户可能电脑型号不一样&#xff0c;但系统版本一致都适合该方法。 用电脑用久了的朋友们都知道电脑的快捷键在哪里&#xff0c;笔记本电脑重启快捷键是什么?下面就给大家分享一下笔记…

新手iso系统怎么安装 新手安装iso镜像文件详细步骤

操作系统大多是iso格式的文件&#xff0c;尤其是Windows系统&#xff0c;都是.iso镜像&#xff0c;如果电脑可以正常使用&#xff0c;iso镜像文件只需解压出来就可以安装&#xff0c;但是对于新手来说&#xff0c;可能解压iso系统都是个问题&#xff0c;那么新手iso系统怎么安装…

Java获取一天的起止时间(Java8写法使用 LocalDateTime)

Calendar calendar new GregorianCalendar();// 0可以修改&#xff0c;0代表当前时间&#xff0c;-1代表前一天calendar.add(Calendar.DAY_OF_MONTH,0);//一天的开始时间 yyyy:MM:dd 00:00:00calendar.set(Calendar.HOUR_OF_DAY,0);calendar.set(Calendar.MINUTE,0);calend…

Windows10系统以太网显示“未识别的网络”如何解决

如果你的Win10系统电脑连不上网&#xff0c;那么可能会是三种情况导致的&#xff1a;受限未识别网络、拨号不成功或者网线没插好。其中&#xff0c;本地连接(以太网)提示“未识别的网络”情况是我们最经常碰到的。如果你的Win10系统无法访问网络&#xff0c;且在有线连接路由器…

如何在bios里调节风扇转速 bios设置风扇转速的方法

CPU的温度对电脑的正常运行有很大的影响&#xff0c;如果温度过高那么电脑就不能正常工作&#xff0c;风扇在降低温度中发挥着很大的作用&#xff0c;那么如何在bios里调节风扇转速呢?下面就给大家分享bios设置风扇转速的方法。 1、启动电脑按快捷键进入BIOS里面&#xff0c;…

win7开机黑屏怎么解决?win7开机黑屏出现reboot and select的解决方法

很多用户有遇见电脑黑屏的情况&#xff0c;而且还出现 reboot and select proper boot deviceor insert boot media in selected boot device 的提示&#xff0c;win7开机黑屏怎么解决呢?可能是硬盘接口数据线出现松动了&#xff0c;也可能是硬盘坏了。今天小编整理了相关的教…