您的位置:首页 > 其它

Dubbo实际应用基本配置讲解

2017-08-11 14:42 323 查看

一、发展趋势

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。



单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。 此时,用于加速前端页面开发的Web框架(MVC)是关键。

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。 此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。 此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

产生的问题

在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。

1、当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。

此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。 并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。

2、 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。

3、 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?

4、为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。 其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。

二、架构说明



节点角色说明

Provider: 暴露服务的服务提供方

Consumer: 调用远程服务的服务消费方。

Registry: 服务注册与发现的注册中心。

Monitor: 统计服务的调用次调和调用时间的监控中心。

Container: 服务运行容器。

调用关系说明

1、服务容器负责启动,加载,运行服务提供者。

2、服务提供者在启动时,向注册中心注册自己提供的服务。

3、服务消费者在启动时,向注册中心订阅自己所需的服务。

4、注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

5、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

6、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

三、Spring xml配置

Dubbo在使用Spring配置时,需要添加Schema:



服务提供者配置

<!-- 提供方应用信息,用于计算依赖关系 owner: 负责人 organization: 组织 -->
<dubbo:application name="dubbo-provider" owner="author" organization="slient"/>

<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 用dubbo协议在20880端口暴露服务 threads:服务线程池大小 -->
<dubbo:protocol name="dubbo" port="20882" threads="200"/>

<!-- 监控中心配置 -->
<dubbo:monitor protocol="registry"/>

<!-- 具体的接口实现 -->
<bean id="testService" class="com.slient.dubbo.provider.xml.impl.TestServiceImpl"/>

<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.slient.dubbo.provider.xml.TestService" ref="testService" timeout="300" loadbalance="random" cluster="failover" retries="2" executes="100" actives="100">
<!-- 对于某一方法的配置,非必备  -->
<dubbo:method name="sayBaba" timeout="10000" retries="3" loadbalance="leastactive" actives="5"/>
</dubbo:service>


cluster:集群容错,failsafe(失败安全,出现异常时直接忽略)、failover(失败自动切换,当出现失败,重试其他服务器,通常用于读操作,但重试会带来更长的延迟,因此可通过retries=”2”来设置重试次数,不含一次)

retries: 失败重试次数

actives:最大并发调用限制,当Consumer对一个服务的并发调用到上限之后,新调用会Wait直到超时。在方法上配置(dubbo:method)则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务。

executes:一个服务提供者并行执行请求上限,即当Provider对一个服务的并发调用到上限后,新调用会Wait(Consumer可能到超时)。在方法上配置(dubbo:method)则并发限制针对方法,在接口上配置(dubbo:service),则并发限制针对服务。

服务消费者配置

<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-consumer" owner="author" organization="slient"/>

<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>

<!-- 监控中心配置 -->
<dubbo:monitor protocol="registry"/>

<!-- 调用接口 -->
<dubbo:reference id="testService" interface="com.slient.dubbo.provider.xml.TestService"/>


各配置之间关系



对于参数值的执行顺序:方法级优先,接口级次之,全局配置再次之。如果级别一样,则消费方优先,提供方次之。



启动时检查

Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认 check=”true”。

如果Spring容器是懒加载的,或者通过API编程延迟引用服务,或者可以接受启动时依赖服务不可以,则可关闭check,否则服务临时不可用时,会抛出异常,拿到null引用,如果 check=”false”,总是会返回引用,当服务恢复时,能自动连上。

<!-- 关闭某个服务的启动时检查 -->
<dubbo:reference interface="com.foo.BarService" check="false" />

<!-- 关闭所有服务的启动时检查 -->
<dubbo:consumer check="false" />

<!-- 关闭注册中心启动时检查 -->
<dubbo:registry check="false" />


集群容错

1、Failover Cluster模式

配置值:failover

这种模式是Dubbo集群容错默认的模式选择,调用失败时,会自动切换,重新尝试调用其他节点上可用的服务。对于一些幂等性操作可以使用该模式,如读操作,因为每次调用的副作用是相同的,所以可以选择自动切换并重试调用,对调用者完全透明。

缺点是重试调用会带来响应端的延迟,如果出现大量的重试调用,可能说明我们的服务提供方发布的服务有问题,如网络延迟严重、硬件设备需要升级、程序算法非常耗时,等等,这就需要仔细检测排查了。

可通过
retries="2"
来设置重试次数(不含第一次)。



2、Failfast Cluster模式

配置值:failfast

这种模式称为快速失败模式,调用只执行一次,失败则立即报错。这种模式适用于非幂等性操作,每次调用的副作用是不同的,如写操作,比如交易系统我们要下订单,如果一次失败就应该让它失败,通常由服务消费方控制是否重新发起下订单操作请求(另一个新的订单)。

3、Failsafe Cluster模式

配置值:failsafe

失败安全模式,如果调用失败, 则直接忽略失败的调用,而是要记录下失败的调用到日志文件,以便后续审计。

4、Failback Cluster模式

配置值:failback

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

5、Forking Cluster模式

配置值:forking

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过
forks="2"
来设置最大并行数。

6、Broadcast Cluster模式

配置值:broadcast

广播调用所有提供者,逐个调用,任意一台报错则报错(2.1.0开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息。

7、自定义集群容错

我们可以根据实际应用场景选择合适的集群容错模式。如果我们觉得Dubbo内置提供的几种集群容错模式都不能满足应用需要,也可以定制实现自己的集群容错模式,因为Dubbo框架给我提供的扩展的接口,只需要实现接口
com.alibaba.dubbo.rpc.cluster.Cluster
即可,接口定义如下所示:



负载均衡

1、Random LoadBalance

配置值为:random

可以设置权重,有利于充分利用服务器的资源,高配的可以设置权重大一些,低配的可以稍微小一些。

2、RoundRobin LoadBalance

配置值为:roundrobin

轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

3、LeastActive LoadBalance

配置值为:leastactive

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

4、ConsistentHash LoadBalance

一致性Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

5、自定义负载均衡

Dubbo框架也提供了实现自定义负载均衡策略的接口,可以实现
com.alibaba.dubbo.rpc.cluster.LoadBalance
接口,接口定义如下所示:



注意:

Dubbo中有
AbstractLoadBalance
抽象基类,是所有负载均衡策略实现类的父类,实现了LoadBalance接口 的方法,同时提供抽象方法交由子类实现。也可以通过继承这个类来实现自定义的负载均衡。

直连服务提供者

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A接口配置点对点,不影响B接口从注册中心获取列表。

如果是线上需求需要点对点,可在
<dubbo:reference>
中配置url指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:



服务分组

当一个接口有多种实现时,可以用group区分。

<!-- 服务提供者配置 -->
<dubbo:service group="feedback" interface="com.xxx.IndexService" />
<dubbo:service group="member" interface="com.xxx.IndexService" />

<!-- 服务消费者配置 -->
<dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" />
<dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" />


服务多版本

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

在低压力时间段,先升级一半提供者为新版本

再将所有消费者升级为新版本

然后将剩下的一半提供者升级为新版本

<!-- 老版本服务 -->
<dubbo:service interface="com.foo.BarService" version="1.0.0" />

<!-- 新版本服务 -->
<dubbo:service interface="com.foo.BarService" version="2.0.0" />

<!-- 引用老版本 -->
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

<!-- 引用新版本 -->
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />


并发控制

限制com.foo.BarService的每个方法,服务器端并发执行(或占用线程池线程数)不能超过10个:

<dubbo:service interface="com.slient.dubbo.provider.xml.TestService" executes="10"/>


限制com.foo.BarService的sayHello方法,服务器端并发执行(或占用线程池线程数)不能超过10个:

<dubbo:service interface="com.slient.dubbo.provider.xml.TestService">
<dubbo:method name="sayHello" executes="10"/>
</dubbo:service>


限制com.foo.BarService的每个方法,每客户端并发调用(或占用连接的请求数)不能超过10个:

<dubbo:service interface="com.slient.dubbo.provider.xml.TestService" actives="10"/>


限制com.foo.BarService的sayHello方法,每客户端并发执行(或占用连接的请求数)不能超过10个:

<dubbo:service interface="com.slient.dubbo.provider.xml.TestService">
<dubbo:method name="sayHello" actives="10"/>
</dubbo:service>


官网介绍比较详细,这里只是挑选了一些经常用到的基本配置,详情配置可以查看Dubbo官网配置:http://dubbo.io/user-guide/configuration/xml.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: