当前位置:首页 » 文件传输 » dubbo上传文件大小限制
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

dubbo上传文件大小限制

发布时间: 2022-10-21 09:01:39

‘壹’ Dubbo简介

Dubbo是Alibaba开源的分布式服务框架,它按照分层的方式来架构,使用这种方式可以使各层解耦。

Dubbo在调用远程的服务的时候再本地有一个接口,就想调用本地方法一样去调用,底层实现好参数传输和远程服务运行结果传回之后的返回。

Dubbo的特点:

(1)它主要使用高效的网络框架和序列化框架,让分布式服务之间调用效率更高。

(2)采用注册中心管理众多的服务接口地址,当你想调用服务的时候只需要跟注册中心询问即可,不像使用WebService一样每个服务都得记录好接口调用方式。

(3)监控中心时实现服务方和调用方之间运行状态的监控,还能控制服务的优先级、权限、权重、上下线等,让整个庞大的分布式服务系统的维护和治理比较方便。

(4)高可用,如果有服务挂了,注册中心就会从服务列表去掉该节点,客户端会像注册中心请求另一台可用的服务节点重新调用。同时注册中心也能实现高可用(ZooKeeper)。

(5)负载均衡,采用软负载均衡算法实现对多个相同服务的节点的请求负载均衡。

Dubbo需要四大基本组件:Rigistry,Monitor,Provider,Consumer。

1、监控中心的配置文件-bbo.properties文件

(1)容器,监控中心是在jetty和spring环境下运行,依赖于注册中心,日志系统是log4j

    bbo.container = log4j,spring,registry,jetty

(2)监控服务的名称,监控系统对整个Dubbo服务系统来说也是一个服务

    bbo.application.name = simple-monitor

(3)服务的所有者,这是Dubbbo的服务的功能,可以指定服务的负责人

    bbo.application.owner = coselding

(4)注册中心的地址,配置后监控中心就能通过注册中心获取当前可用的服务列表及其状态,在页面向你汇报Dubbo中的服务运行情况。

    bbo.registr.address = multicast://{ip}:{port} //广播

    bbo.registr.address = zookeeper://{ip}:{port} //zookeper

    bbo.registr.address = redis://{ip}:{port} //redis

    bbo.registr.address = bbo://{ip}:{port} //bbo

(5)bbo协议端口号

    bbo.protocol.port = 7070

(6)jetty工作端口号

    bbo.jetty.port = 8082

(7)工作目录,用于存放监控中心的数据

    bbo.jetty.directory = ${user.home}/monitor

(8)监控中心报表存放目录

    bbo.charts.directory=${bbo.jetty.directory}/charts

(9)监控中心数据资料目录

    bbo.statistics.directory=${user.home}/monitor/statistics

(10)监控中心日志文件路径

    bbo.log4j.file=logs/bbo-monitor-simple.log

(11)监控中心日志记录级别

    bbo.log4j.level=WARN

2、Dubbo提供负载均衡方式

(1)Random,随机,按权重配置随机概率,调用量越大分布越均匀,默认方式。

(2)RounRobin,轮询,按权重设置轮询比例,如果存在比较慢的机器容易在这台机器上请求阻塞较多。

(3)LeastActive,最少活跃调用数,不支持权重,只能根据自动识别的活跃数分配,不能灵活调配。

(4)ConsistenHash,一致性hash,对相同参数的请求路由到一个服务提供者上,如果有类似灰度发布需求可采用。

3、Dubbo过滤器

Dubbo初始化过程加载ClassPath下的META-INF/bbo/internal/,META-INF/bbo/,META-INF/services/三个路径下的com.alibaba.bbo.rpc.Filter文件。文件内容:

    Name = FullClassName,这些类必须实现Filter接口。

自定义Filter类:

配置文件在配置过滤器,consumer.xml中:

Dubbo对过滤器的加载过程:

    先加载三个路径下的com.alibaba.bbo.rpc.Filter文件里面的键值对,key为过滤器名称,value为过滤器的类的全限定名(这个类必须实现Dubbo中的Filter接口)。

    自定义的类中@Active注解是过滤器设定的全局基本属性。

    Spring在加载consumer.xml文件时,通过 <bbo:consumer filter="xxx" id = "xxx" retrries = "0">这个配置指定消费者端要加载的过滤器,通过filter属性指定过滤器名称。

@Activate注解-自动激活,group属性是表示匹配了对应的角色才被加载,value表示表明过滤条件,不写则表示所有条件都会被加载,写了则只有bbo URL中包含该参数名且参数值不为空才被加载,这个参数会以bbo协议的一个参数K-V对传到Provider。

4、Dubbo的Provider配置

5、Dubbo的Consumer配置

1、Dubbo是什么?

Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式框架。

2、为什么使用Dubbo?

很多公司都在使用,经过很多线上的考验,内部使用了Netty,Zookeeper,保证了高性能可用性。

使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可以提高业务复用灵活性扩展,使前端应用能快速的响应对边的市场需求。分布式架构可以承受更大规模的并发流量。

Dubbo的服务治理图:

3、Dubbo和Spring Cloud的区别

两个没有关联,但是非要说区别,有如下几点:

(1)通信方式不同,Dubbo使用RPC通信,Spring Cloud使用HTTP Restful方式

(2)组成部分不同

4、Dubbo支持的协议

bbo://  (推荐);rmi:// ;hessian:// ;http:// ;webservice:// ;thrift:// ;memcached:// ;redis:// ;rest:// 。

5、Dubbo需要容器吗?

不需要,如果硬要容器的话,会增加复杂性,同时也浪费资源。

6、Dubbo内置的服务容器

Spring Container;Jetty Container;Log4j Container。

7、Dubbo中节点角色

Register,Monitor,Provider,Consumer,Container(服务运行的容器)。

8、Dubbo的服务注册和发现的流程图

9、Dubbo的注册中心

默认使用Zookeper作为注册中心,还有Redis,Multicast,bbo注册中心。

10、Dubbo的配置方式

Spring配置方式和Java API配置方式

11、Dubbo的核心配置

(1)bbo:service 服务配置

(2)bbo:referece 引用配置

(3)bbo:protocol 协议配置

(4)bbo:application 应用配置

(5)bbo:registry 注册中心配置

(6)bbo:monitor 监控中心配置

(7)bbo:provider 提供方配置

(8)bbo:consumer 消费方配置

(9)bbo:method 方法配置

(10)bbo:argument 参数配置

12、在Provider 节点上可以配置Consumer端的属性有哪些?

(1)timeout:方法调用超时

(2)retries:失败重试次数,默认是2次

(3)loadbalance:负载均衡算法,默认随机

(4)actives消费者端,最大并发调用控制

13、Dubbo启动时如果依赖的服务不可用会怎样

Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成。默认check ="true"。

14、Dubbo序列化框架

推荐使用Hessian序列化,还有Dubbo,FastJson,Java自带序列化。

15、Dubbo的通信框架

默认使用Netty框架,另外也提供了Mina,Grizzly。

16、Dubbo集群容错方案

(1)Failover Cluster,失败自动切换,自动重试其他服务器。

(2)Failfast Cluster,快速失败,立即报错,只发起一次调用。

(3)Failsafe Cluster,失败安全,出现异常时,直接忽略。

(4)Failback Cluster,失败自动恢复,记录失败请求,定时重发。

(5)Forking Cluster,并行调用多个服务器,只要一个返回成功即可。

(6)Broadcast Cluster,广播逐个调用所有提供者,任意一个报错则报错。

17、Dubbo的负载均衡策略

(1)Random LoadBalance,随机,按权重设置随机概率,默认。

(2)RoundRobin LoadBalace,轮询,按公约后的权重设置轮训比例。

(3)LeastActive LoadBalace,最少活跃调用数,相同活跃数的随机。

(4)ConsistenHash LoadBalance,一致性hash,相同参数的请求总是发到用一个服务器。

18、指定某一个服务

可以配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。

<bbo:reference interface="com.weidian.bbo.IMyDemo" version="1.0" id="myDemo" url="bbo://127.0.0.1:20880/"></bbo:reference>

19、Dubbo多协议

Dubbo允许配置多协议,在不同服务器上支持不同协议,或者同一服务支持多种协议。

20、当一个服务有多种实现时怎么做?

当一个接口有多种是现实,可以用group属性来分组,服务提供方和消费方都指定同一个group即可。

21、兼容旧版本

使用版本号过度,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。

22、Dubbo可以缓存吗?

Dubbo提供声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量。

23、Dubbo服务之间的调用时阻塞的吗?

默认是同步等待结果阻塞的,支持异步调用。Dubbo是基于NIO的非阻塞实现并行调用的,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个Future对象。

24、Dubbo不支持分布式事务

25、Dubbo必须依赖的包

Dubbo必须依赖JDK,其他为可选。

26、Dubbo使用过程中的问题

Dubbo的设计目的是为了满足高并发小数据量的rpc请求,在大数据量下性能表现不是很好,建议使用rmi或http协议。

27、Dubbo的管理控制台的作用

路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡。

28、Spring boot整合Dubbo

(1)添加依赖

        <!-- https://mvnrepository.com/artifact/com.alibaba.boot/bbo-spring-boot-project -->

        <dependency>

            <groupId>com.alibaba.boot</groupId>

            <artifactId>bbo-spring-boot-starter</artifactId>

            <version>0.1.0</version>

        </dependency>

        <!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->

        <dependency>

            <groupId>com.101tec</groupId>

            <artifactId>zkclient</artifactId>

            <version>0.10</version>

        </dependency>

(2)配置bbo

    ## Dubbo 服务提供者配置

    spring.bbo.application.name=provider

    spring.bbo.registry.address=zookeeper://127.0.0.1:2181

    spring.bbo.protocol.name=bbo

    spring.bbo.protocol.port=20880

    spring.bbo.scan=org.spring.springboot.bbo

    ## Dubbo 服务消费者配置

    spring.bbo.application.name=consumer

    spring.bbo.registry.address=zookeeper://127.0.0.1:2181

    spring.bbo.scan=org.spring.springboot.bbo

‘贰’ bbo 接口上传文件如何去掉大小限制

在消费端增加如下配置
<bbo:provider payload="104857600" />

‘叁’ android 可以使用bbo吗

可以的

DUBBO配置规则详解
研究DUBBO也已经大半年了,对它的大部分源码进行了分析,以及对它的内部机制有了比较深入的了解,以及各个模块的实现。DUBBO包含很多内容,如果想了解DUBBO第一步就是启动它,从而可以很好的使用它,那么如何更好的使用呢?就需要知道DUBBO的各个配置项,以及它可以通过哪些途径进行配置。个人对配置的理解,就好比时对动物的驯服,如何很好的驯服一头猛兽,那就需要知道它各种因子,从而调整,已达到自己期望的结果。这篇不对DUBBO有哪些配置项可以配置,但是通过这篇文章,你应该能够知道DUBBO可以进行哪些配置。本文会通过分析DUBBO加载配置源码的分析,来使得大家对DUBBO的配置一块有更加深入的了解。从而达到“驯服”DUBBO,以使得它成为你们自己的DUBBO。
DUBBO在配置这一块做的确实很完美,提供很很多参数,以及提供了多种渠道。下面进入正题,看看DUBBO怎么加载配置的。在讲这些之前,先给大家介绍一下在DUBBO源码层面定义了哪些类来存储各个模块的配置项,从而了解DUBBO可以对哪些模块进行配置。
哪些东西可以配置
由于大部分项目都会使用Spring,而且DUBBO也提供了通过Spring来进行配置,那么先从这里进行着手。DUBBO加载Spring的集成时在bbo-config下面的bbo-config-spring模块下面,其中有一个类DubboNamespaceHandler,它实现了Spring提供的接口NamespaceHandlerSupport。那么Spring怎么发现整个实现类的呢?在该模块的META-INF文件夹下有两个文件: spring.handlers和spring.schemas,这两个文件里面制定了bbo的namespace的XSD文件的位置以及bbo的namespace由DubboNamespaceHandler来处理解析。说了这么多废话,只是想说明Spring是怎么解析<bbo:.../>配置的。
知道了DUBBO和Spring关于配置一块时怎么整合的之后,那么你应该就不会诧异Spring怎么那么聪明,能够解析bbo的namespace。接下来看看DubboNamespaceHandler类里面有什么东西。

‘肆’ Dubbo——路由机制(下)

在 Dubbo——路由机制(上) ,介绍了 Router 接口的基本功能以及 RouterChain 加载多个 Router 的实现,之后介绍了 ConditionRouter 这个类对条件路由规则的处理逻辑以及 ScriptRouter 这个类对脚本路由规则的处理逻辑。本文继续介绍剩余的三个 Router 接口实现类。

FileRouterFactory 是 ScriptRouterFactory 的装饰器,其扩展名为 file,FileRouterFactory 在 ScriptRouterFactory 基础上增加了读取文件的能力。可以将 ScriptRouter 使用的路由规则保存到文件中,然后在 URL 中指定文件路径,FileRouterFactory 从中解析到该脚本文件的路径并进行读取,调用 ScriptRouterFactory 去创建相应的 ScriptRouter 对象。

下面来看 FileRouterFactory 对 getRouter() 方法的具体实现,其中完成了 file 协议的 URL 到 script 协议 URL 的转换,如下是一个转换示例,首先会将 file:// 协议转换成 script:// 协议,然后会添加 type 参数和 rule 参数,其中 type 参数值根据文件后缀名确定,该示例为 js,rule 参数值为文件内容。

可以再结合接下来这个示例分析 getRouter() 方法的具体实现:

TagRouterFactory 作为 RouterFactory 接口的扩展实现,其扩展名为 tag。但是需要注意的是,TagRouterFactory 与之前介绍的 ConditionRouterFactory、ScriptRouterFactory 的不同之处在于,它是通过继承 CacheableRouterFactory 这个抽象类,间接实现了 RouterFactory 接口。

CacheableRouterFactory 抽象类中维护了一个 ConcurrentMap 集合(routerMap 字段)用来缓存 Router,其中的 Key 是 ServiceKey。在 CacheableRouterFactory 的 getRouter() 方法中,会优先根据 URL 的 ServiceKey 查询 routerMap 集合,查询失败之后会调用 createRouter() 抽象方法来创建相应的 Router 对象。在 TagRouterFactory.createRouter() 方法中,创建的自然就是 TagRouter 对象了。

通过 TagRouter,可以将某一个或多个 Provider 划分到同一分组,约束流量只在指定分组中流转,这样就可以轻松达到流量隔离的目的,从而支持灰度发布等场景。

目前,Dubbo 提供了动态和静态两种方式给 Provider 打标签,其中动态方式就是通过服务治理平台动态下发标签,静态方式就是在 XML 等静态配置中打标签。Consumer 端可以在 RpcContext 的 attachment 中添加 request.tag 附加属性,注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递,我们只需要在起始调用时进行设置,就可以达到标签的持续传递。

了解了 Tag 的基本概念和功能之后,再简单介绍一个 Tag 的使用示例。

在实际的开发测试中,一个完整的请求会涉及非常多的 Provider,分属不同团队进行维护,这些团队每天都会处理不同的需求,并在其负责的 Provider 服务中进行修改,如果所有团队都使用一套测试环境,那么测试环境就会变得很不稳定。如下图所示,4 个 Provider 分属不同的团队管理,Provider 2 和 Provider 4 在测试环境测试,部署了有 Bug 的版本,这样就会导致整个测试环境无法正常处理请求,在这样一个不稳定的测试环境中排查 Bug 是非常困难的,因为可能排查到最后,发现是别人的 Bug。

为了解决上述问题,我们可以针对每个需求分别独立出一套测试环境,但是这个方案会占用大量机器,前期的搭建成本以及后续的维护成本也都非常高。

下面是一个通过 Tag 方式实现环境隔离的架构图,其中,需求 1 对 Provider 2 的请求会全部落到有需求 1 标签的 Provider 上,其他 Provider 使用稳定测试环境中的 Provider;需求 2 对 Provider 4 的请求会全部落到有需求 2 标签的 Provider 4 上,其他 Provider 使用稳定测试环境中的 Provider。

在一些特殊场景中,会有 Tag 降级的场景,比如找不到对应 Tag 的 Provider,会按照一定的规则进行降级。如果在 Provider 集群中不存在与请求 Tag 对应的 Provider 节点,则默认将降级请求 Tag 为空的 Provider;如果希望在找不到匹配 Tag 的 Provider 节点时抛出异常的话,我们需设置 request.tag.force = true。

如果请求中的 request.tag 未设置,只会匹配 Tag 为空的 Provider,也就是说即使集群中存在可用的服务,若 Tag 不匹配也就无法调用。一句话总结,携带 Tag 的请求可以降级访问到无 Tag 的 Provider,但不携带 Tag 的请求永远无法访问到带有 Tag 的 Provider。

下面再来看 TagRouter 的具体实现。在 TagRouter 中持有一个 TagRouterRule 对象的引用,在 TagRouterRule 中维护了一个 Tag 集合,而在每个 Tag 对象中又都维护了一个 Tag 的名称,以及 Tag 绑定的网络地址集合,如下图所示:

另外,在 TagRouterRule 中还维护了 addressToTagnames、tagnameToAddresses 两个集合(都是 Map<String, List<String>> 类型),分别记录了 Tag 名称到各个 address 的映射以及 address 到 Tag 名称的映射。在 TagRouterRule 的 init() 方法中,会根据 tags 集合初始化这两个集合。

了解了 TagRouterRule 的基本构造之后,我们继续来看 TagRouter 构造 TagRouterRule 的过程。TagRouter 除了实现了 Router 接口之外,还实现了 ConfigurationListener 接口,如下图所示:

ConfigurationListener 用于监听配置的变化,其中就包括 TagRouterRule 配置的变更。当我们通过动态更新 TagRouterRule 配置的时候,就会触发 ConfigurationListener 接口的 process() 方法,TagRouter 对 process() 方法的实现如下:

我们可以看到,如果是删除配置的操作,则直接将 tagRouterRule 设置为 null,如果是修改或新增配置,则通过 TagRuleParser 解析传入的配置,得到对应的 TagRouterRule 对象。TagRuleParser 可以解析 yaml 格式的 TagRouterRule 配置,下面是一个配置示例:

经过 TagRuleParser 解析得到的 TagRouterRule 结构,如下所示:

除了上图展示的几个集合字段,TagRouterRule 还从 AbstractRouterRule 抽象类继承了一些控制字段,后面介绍的 ConditionRouterRule 也继承了 AbstractRouterRule。

AbstractRouterRule 中核心字段的具体含义大致可总结为如下:

我们可以看到,AbstractRouterRule 中的核心字段与前面的示例配置是一一对应的。

我们知道,Router 最终目的是要过滤符合条件的 Invoker 对象,下面我们一起来看 TagRouter 是如何使用 TagRouterRule 路由逻辑进行 Invoker 过滤的,大致步骤如下:

上述流程的具体实现是在 TagRouter.route() 方法中,如下所示:

除了之前介绍的 TagRouterFactory 继承了 CacheableRouterFactory 之外,ServiceRouterFactory 也继承 CachabelRouterFactory,具有了缓存的能力,具体继承关系如下图所示:

ServiceRouterFactory 创建的 Router 实现是 ServiceRouter,与 ServiceRouter 类似的是 AppRouter,两者都继承了 ListenableRouter 抽象类(虽然 ListenableRouter 是个抽象类,但是没有抽象方法留给子类实现),继承关系如下图所示:

ListenableRouter 在 ConditionRouter 基础上添加了动态配置的能力,ListenableRouter 的 process() 方法与 TagRouter 中的 process() 方法类似,对于 ConfigChangedEvent.DELETE 事件,直接清空 ListenableRouter 中维护的 ConditionRouterRule 和 ConditionRouter 集合的引用;对于 ADDED、UPDATED 事件,则通过 ConditionRuleParser 解析事件内容,得到相应的 ConditionRouterRule 对象和 ConditionRouter 集合。这里的 ConditionRuleParser 同样是以 yaml 文件的格式解析 ConditionRouterRule 的相关配置。ConditionRouterRule 中维护了一个 conditions 集合(List<String> 类型),记录了多个 Condition 路由规则,对应生成多个 ConditionRouter 对象。

整个解析 ConditionRouterRule 的过程,与前文介绍的解析 TagRouterRule 的流程类似。

在 ListenableRouter 的 route() 方法中,会遍历全部 ConditionRouter 过滤出符合全部路由条件的 Invoker 集合,具体实现如下:

ServiceRouter 和 AppRouter 都是简单地继承了 ListenableRouter 抽象类,且没有覆盖 ListenableRouter 的任何方法,两者只有以下两点区别。

本文我们是紧接 Dubbo——路由机制(上) 的内容,继续介绍了剩余 Router 接口实现的内容。

我们介绍了基于文件的 FileRouter 实现,其底层会依赖之前介绍的 ScriptRouter;接下来又讲解了基于 Tag 的测试环境隔离方案,以及如何基于 TagRouter 实现该方案,同时深入分析了 TagRouter 的核心实现;最后我们还介绍了 ListenableRouter 抽象类以及 ServerRouter 和 AppRouter 两个实现,它们是在条件路由的基础上添加了动态变更路由规则的能力,同时区分了服务级别和服务实例级别的配置。

‘伍’ SpringCloud和Dubbo的区别是什么

springcloud和bbo的最大区别:springcloud抛弃了bbo的rpc通信,采用的是基于http的rest方式。

‘陆’ 为什么bbo不适合传送大数据量

因bbo协议采用单一长连接,
如果每次请求的数据包大小为500KByte,假设网络为千兆网卡(1024Mbit=128MByte),每条连接最大7MByte(不同的环境可能不一样,供参考),
单个服务提供者的TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。
单个消费者调用单个服务提供者的TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14。
如果能接受,可以考虑使用,否则网络将成为瓶颈。

‘柒’ rpc框架都有哪些rmi bbo

Dubbo分层

config(配置层 )

proxy(服务代理层)

registry( 注册中心层)

cluster( 路由层)

monitor( 监控层)

protocol( 远程调用层)

exchange( 信息交换层)

transport( 网络传输层)

serialize( 数据序列化层)

对外配置接口
以ServiceConfig, ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类
Javassist ProxyFactory
Jdk ProxyFactory
服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton
以ServiceProxy为中心,扩展接口为ProxyFactory
选择

Zookeeper

Redis

Multicast

Simple

支持基于网络的集群方式,有广泛周边开源产品,建议使用bbo-2.3.3以上版本(推荐使用)
依赖于Zookeeper的稳定性
支持基于客户端双写的集群方式,性能高
要求服务器时间同步,用于检查心跳过期脏数据
去中心化,不需要安装注册中心
依赖于网络拓普和路由,跨机房有风险
Dogfooding,注册中心本身也是一个标准的RPC服务
没有集群支持,可能单点故障
封装服务地址的注册与发现
以服务URL为中心,扩展接口为RegistryFactory, Registry, RegistryService
选择

Spring

Jetty

Log4j

自动加载META-INF/spring目录下的所有Spring配置
启动一个内嵌Jetty,用于汇报状态
大量访问页面时,会影响服务器的线程和内存
自动配置log4j的配置,在多进程启动时,自动给日志文件按进程分目录
用户不能控制log4j的配置,不灵活
条件路由

脚本路由

基于条件表达式的路由规则,功能简单易用
有些复杂多分支条件情况,规则很难描述
基于脚本引擎的路由规则,功能强大
没有运行沙箱,脚本能力过于强大,可能成为后门
Random

RoundRobin

LeastActive

ConsistentHash

随机,按权重设置随机概率(推荐使用)
在一个截面上碰撞的概率高,重试时,可能出现瞬间压力不均
轮循,按公约后的权重设置轮循比率
存在慢的机器累积请求问题,极端情况可能产生雪崩
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差,使慢的机器收到更少请求
不支持权重,在容量规划时,不能通过权重把压力导向一台机器压测容量
一致性Hash,相同参数的请求总是发到同一提供者,当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动
压力分摊不均
Failover

Failfast

Failsafe

Failback

Forking

Broadcast

失败自动切换,当出现失败,重试其它服务器,通常用于读操作(推荐使用)
重试会带来更长延迟
快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作
如果有机器正在重启,可能会出现调用失败
失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作
调用信息丢失
失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作
不可靠,重启丢失
并行调用多个服务器,只要一个成功即返回,通常用于实时性要求较高的读操作
需要浪费更多服务资源
广播调用所有提供者,逐个调用,任意一台报错则报错,通常用于更新提供方本地状态
速度慢,任意一台报错则报错
封装多个提供者的路由及负载均衡,并桥接注册中心
以Invoker为中心,扩展接口为Cluster, Directory, Router, LoadBalance
Cluster选择

Router选择

路由规则

容器

RPC调用次数和调用时间监控
以Statistics为中心,扩展接口为MonitorFactory, Monitor, MonitorService
Dubbo协议

Rmi协议

Hessian协议

连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO异步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用bbo协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用)
适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况
Dubbo缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低
Dubbo协议缺省每服务每提供者每消费者使用单一长连接,如果数据量较大,可以使用多个连接
为防止被大量连接撑挂,可在服务提供方限制大接收连接数,以实现服务提供方自我保护
在大文件传输时,单一连接会成为瓶颈
总结

可与原生RMI互操作,基于TCP协议
偶尔会连接失败,需重建Stub
参数及返回值需实现Serializable接口
参数及返回值不能自定义实现List, Map, Number, Date, Calendar等接口,只能用JDK自带的实现,因为hessian会做特殊处理,自定义实现类中的属性值都会丢失
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件
适用场景:页面传输,文件传输,或与原生hessian服务互操作
提供者用Dubbo的Hessian协议暴露服务,消费者直接用标准Hessian接口调用
或者提供方用标准Hessian暴露服务,消费方用Dubbo的Hessian协议调用
基于Hessian的远程调用协议
可与原生Hessian互操作,基于HTTP协议
需hessian.jar支持,http短连接的开销大
Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现
可以和原生Hessian服务互操作

总结

约束

封装RPC调用
以Invocation, Result为中心,扩展接口为Protocol, Invoker, Exporter
选择

封装请求响应模式,同步转异步
以Request, Response为中心,扩展接口为Exchanger, ExchangeChannel,ExchangeClient, ExchangeServer
Netty

Mina

Grizzly

性能较好(推荐使用)
一次请求派发两种事件,需屏蔽无用事件
老牌NIO框架,稳定
待发送消息队列派发不及时,大压力下,会出现FullGC
Sun的NIO框架,应用于GlassFish服务器中
线程池不可扩展,Filter不能拦截下一Filter
抽象mina和netty为统一接口
以Message为中心,扩展接口为Channel, Transporter, Client, Server, Codec
选择

Hessian

Dubbo

Json

Java

性能较好,多语言支持(推荐使用)
Hessian的各版本兼容性不好,可能和应用使用的Hessian冲突,Dubbo内嵌了hessian3.2.1的源码
通过不传送POJO的类元信息,在大量POJO传输时,性能较好
当参数对象增加字段时,需外部文件声明
纯文本,可跨语言解析,缺省采用FastJson解析
性能较差
Java原生支持
性能较差
可复用的一些工具
扩展接口为Serialization, ObjectInput, ObjectOutput, ThreadPool
选择

Business

RPC

Remoting

Service
Config
Proxy
Registry
Cluster
Monitor
Protocol
Exchange
Transport
Serialize
层次结构

层说明

‘捌’ Dubbo高性能网关--Flurry介绍

从架构的角度来看,API网关暴露http接口服务,其本身不涉及业务逻辑,只负责包括请求路由、负载均衡、权限验证、流量控制、缓存等等功能。其定位类似于Nginx请求转发、但功能要多于Nginx,背后连接了成百上千个后台服务,这些服务协议可能是rest的,也可能是rpc协议等等。

网关的定位决定了它生来就需要高性能、高效率的。网关对接着成百上千的服务接口,承受者高并发的业务需求,因此我们对其性能要求严苛,其基本功能如下:

Flurry是云集自研的一款轻量级、异步流式化、针对Dubbo的高性能API网关。与业界大多数网关不同的是,flurry自己实现了 http与bbo协议互转的流式化的bbo-json协议,可高性能、低内存要求的对http和bbo协议进行转换。除此之外,其基于 netty作为服务容器,提供服务元数据模型等等都是非常具有特点的。下面我们将详细介绍 flurry的特性:

Flurry 网关请求响应基于Netty线程模型,后者是实现了Reactive,反应式模式规范的,其设计就是来榨干CPU的,可以大幅提升单机请求响应的处理能力。
最终,Flurry通过使用Netty线程模型和NIO通讯协议实现了HTTP请求和响应的异步化。

每一次http请求最终都会由Netty的一个Client Handler来处理,其最终以异步模式请求后台服务,并返回一个CompletableFuture,当有结果返回时才会将结果返回给前端。
见下面一段例子:

有了服务元数据,我们就可以不必需要服务的API包,并能够清晰的知道整个服务API的定义。
这在Dubbo服务Mock调用、服务测试、文档站点、流式调用等等场景下都可以发挥抢到的作用。

小孩子才分对错,成年人只看利弊。额外引入一个元数据生成机制,必然带来运维成本、理解成本、迁移成本等问题,那么它具备怎样的价值,来说服大家选择它呢?上面我们介绍元数据中心时已经提到了服务测试、服务 MOCK 等场景,这一节我们重点探讨一下元数据中心的价值和使用场景。

那么,Dubbo服务元数据能够利用到哪些场景呢?下面我们来详细描述。

Http请求,数据通过JSON传输,其格式严格按照接口POJO属性。返回结果再序列化为Json返回前端。现在大多数开源的网关,在bbo协议适配上都是采用的泛化模式来做到协议转换的,这其中就包括 Soul 等。

JsonString -> JSONObject(Map) -> Binary

将JSON 字符串转换为 JSON 对象模型(JSONObject),此处通过第三方JSON映射框架(如Google的Gson, 阿里的FastJSON等)来做,然后将Map通过Hessian2 协议序列化为Binaray。

自定义的Dubbo-Json协议参考了 dapeng-soa 的流式解析协议的思想,详情请参考: dapeng-json

针对上述泛化模式转换Dubbo协议的缺点,我们在flurry-core 中的 Dubbo-Json 序列化协议做到了这点,下面我们来讲解它是如何高效率的完成JsonString到 bbo hessian2 序列化buffer的转换的。

虽然大部分情况下的JSON请求、返回都是数据量较小的场景, 但作为平台框架, 也需要应对更大的JSON请求和返回, 比如1M、甚至10M. 在这些场景下, 如果需要占用大量的内存, 那么势必导致巨大的内存需求, 同时引发频繁的GC操作, 也会联动影响到整个网关的性能.

Dubbo-Json参考了XML SAX API的设计思想, 创造性的引入了JSON Stream API, 采用流式的处理模式, 实现JSON 对 hessian2 的双向转换, 无论数据包有多大, 都可以在一定固定的内存规模内完成.

流式协议,顾名思义就是边读取边解析,数据像水流一样在管道中流动,边流动边解析,最后,数据解析完成时,转换成的hessian协议也已全部写入到了buffer中。
这里处理的核心思想就是实现自己的Json to hessian2 buffer 的语法和此法解析器,并配合前文提及的元数据功能,对每一个读取到的json片段通过元数据获取到其类型,并使用 hessian2协议以具体的方式写入到buffer中。

首先我们来看看JSON的结构. 一个典型的JSON结构体如下

其对应Java POJO 自然就是上述三个属性,这里我们略过。下面是POJO生成的元数据信息

相比XML而言,JSON数据类型比较简单, 由 Object/Array/Value/String/Boolean/Number 等元素组成, 每种元素都由特定的字符开和结束. 例如Object以'{'以及'}'这两个字符标志开始以及结束, 而Array是'['以及']'. 简单的结构使得JSON比较容易组装以及解析。

如图,我们可以清晰的了解JSON的结构,那么对上述JSON进行解析时,当每一次解析到一个基本类型时,先解析到key,然后根据key到元数据信息中获取到其value类型,然后直接根据对应类型的hessian2序列化器将其序列化到byte buffer中。

当解析到引用类型,即 Struct类型时,我们将其压入栈顶,就和java方法调用压栈操作类似。
通过上面的步骤一步一步,每解析一步Json,就将其写入到byte buffer中,最终完成整个流式的解析过程。

拿上面json为例:

总结:

上述整个请求和响应,网关处理如下:

请求和响应中没有像泛化模式中的中间对象转换,直接一步到位,没有多余的临时对象占用内存,没有多余的数据转换,整个过程像在管道中流式的进行。

如上图所示,flurry bbo网关不必依赖任何bbo接口API包,而是直接通过获取服务元数据、并通过bbo-json流式协议来调用后端服务。其本身不会耦合业务逻辑。

硬件部署与参数调整

对基于Y-Hessian的 异步化、流式转换的Yunji Dubbo API网关进行性能压测,了解它的处理能力极限是多少,这样有便于我们推断其上线后的处理能力,以及对照现有的Tomcat接入层模式的优势,能够节约多少资源,做到心里有数。

性能测试场景

上述场景均使用wrk在压测节点上进行5~10min钟的压测,压测参数基本为12线程256连接或者512连接,以发挥最大的压测性能。

flurry集Dubbo网关、异步、流式、高性能于一身,其目标就是替代一些以tomcat作为bbo消费者的接入层,以更少的节点获得更多的性能提升,节约硬件资源和软件资源。

后续在flurry的基础上,将实现鉴权管理、流量控制、限流熔断、监控收集等等功能

Flurry : 基于Dubbo服务的高性能、异步、流式网关
bbo-json : 自定义的Dubbo协议,支持流式序列化模式,为flurry网关序列化/反序列化组件。
Yunji-doc-site : 与元数据集成相关的项目,以及文档站点

dapeng-soa : Dapeng-soa 是一个轻量级、高性能的微服务框架,构建在Netty以及定制的精简版Thrift之上。 同时,从Thrift IDL文件自动生成的服务元数据信息是本框架的一个重要特性,很多其它重要特性都依赖于服务元数据信息。 最后,作为一站式的微服务解决方案,Dapeng-soa还提供了一系列的脚手架工具以支持用户快速的搭建微服务系统
dapeng-json :dapeng-json协议介绍