准备工作:zookeeper集群部署https://blog.csdn.net/DavidSoCool/article/details/96431181

创建一个maven-archetype-quickstart

 

一直next,工程名和Artifactid一样就行了,直接finish

项目结构:

在新建一个maven-archetype-quickstart,用做接口jar依赖

 dubbo-api

 项目结构:

在创建一个springboot和dubbo-api同级,用于发布服务

修改打包方式为jar

 

dubbo-provider

就默认的,直接next,finish

项目结构:

到dubbo-api中创建一个接口类

在dubbo-provider的pom.xml中加入dubbo-api依赖,然后compile,再install下,install是为了让api生成jar包,后面可以被依赖,不然会报错找不到jar。

 

 在加入dubbo、zookeeper依赖

 

 在dubbo-provider的application.properties配置dubbo信息

#配置服务名,必须
dubbo.application.name=springboot-dubbo
#配置注册中心,非zookeeper集群只要把问号开始后面的去掉就行
dubbo.registry.address=zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181,192.168.50.134:2181

#配置扫描路径,扫描对应的@Service类
dubbo.scan.base-packages=com.david.dubbo.dubboprovider

到实现类里配置dubbo注解,不要选成spring的!!

 完整注解路径:

 接下来在创建一个springboot web项目,作为客户端调用发布的dubbo服务

 

选择web,勾选Spring Web Starter,可以帮助我们快速构建一个web工程,点next,然后直接finish。

在dubbo-client的pom.xml里面引入dubbo-api和其他jar

配置dubbo-client的properties属性

#配置服务名
dubbo.application.name=springboot-dubbo-client
#配置注册中心,非zookeeper集群只要把问号开始后面的去掉就行
dubbo.registry.address=zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181,192.168.50.134:2181
#配置扫描路径,扫描对应的@Reference
dubbo.scan.base-packages=com.david.dubbo

创建请求地址类 HelloController.java

package com.david.dubbo.dubboclient;

import com.david.dubbo.SayHelloService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    // 这里和spring的有区别,不是@AutoWrite
    @Reference
    private SayHelloService sayHelloService;

    @GetMapping("/say")
    public String say(@RequestParam("name") String name){
        return sayHelloService.sayHello(name);
    }
}

项目结构:

启动dubbo-provider和dubbo-client,dubbo-client的端口默认8080,不知道为什么两边启动都会报错,提示 Invalid config event received,但是服务是可以调用的,知道原因的可以留言指教一下。

****************************** 负载均衡算法 ************************************

配置的属性名称: roundrobin 轮询、random 随机、leastactive 最小活跃值、consistenthash 一致哈希

random:

权重随机算法,根据权重值进行随机负载。它的算法思想很简单。假设我们有一组服务器 servers = [A, B, C],他们对应的权重为 weights = [5, 3, 2],权重总和为 10。现在把这些权重值平铺在一维坐标值上,[0, 5) 区 间属于服务器 A,[5, 8) 区间属于服务器 B,[8, 10) 区间属于服务器 C。接下来通过 随机数生成器生成一个范围在 [0, 10) 之间的随机数,然后计算这个随机数会落到哪个 区间上。比如数字 3 会落到服务器 A 对应的区间上,此时返回服务器 A 即可。权重 越大的机器,在坐标轴上对应的区间范围就越大,因此随机数生成器生成的数字就会 有更大的概率落到此区间内。只要随机数生成器产生的随机数分布性很好,在经过多 次选择后,每个服务器被选中的次数比例接近其权重比例。

leastactive:

最少活跃调用数算法,活跃调用数越小,表明该服务提供者效率越高,单位时间内可处理更多的请求这个是比较科学的负载均衡算法。 每个服务提供者对应一个活跃数 active。初始情况下,所有服务提供者活跃数均为 0。 每收到一个请求,活跃数加 1,完成请求后则将活跃数减 1。在服务运行一段时间后, 性能好的服务提供者处理请求的速度更快,因此活跃数下降的也越快,此时这样的服 务提供者能够优先获取到新的服务请求。

consistenthash:

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

roundrobin:

加权轮询算法是指将请求轮流分配给每台服务器。举个例子,我们有三台服务器 A、B、C。 我们将第一个请求分配给服务器 A,第二个请求分配给服务器 B,第三个请求分配给 服务器 C,第四个请求再次分配给服务器 A。这个过程就叫做轮询。轮询是一种无状 态负载均衡算法,实现简单,适用于每台服务器性能相近的场景下。但现实情况下, 我们并不能保证每台服务器性能均相近。如果我们将等量的请求分配给性能较差的服 务器,这显然是不合理的。因此,这个时候我们需要对轮询过程进行加权,以调控每 台服务器的负载。经过加权后,每台服务器能够得到的请求数比例,接近或等于他们 的权重比。比如服务器 A、B、C 权重比为 5:2:1。那么在 8 次请求中,服务器 A 将 收到其中的 5 次请求,服务器 B 会收到其中的 2 次请求,服务器 C 则收到其中的 1次请求。

****************************** 配置负载均衡 ************************************

负载均衡可以配置在服务端,也可以配置在客户端

在服务端duobbo-provider中配置,不配置默认为随机算法:

在客户端duobbo-client中配置,不配置默认为空,会通过zk获取服务端的设置,所以暂时就不设置客户端:

在服务端增加打印输出,并配置负载均衡方式为轮询:

然后在idea中增加2个springboot启动方式,修改dubbo的启动端口号分别为20881、28002,然后分别启动。

然后在启动客户端,访问浏览器请求3次,3次的参数各不同

查看3个服务的打印输出,3次请求都分别落在了3个服务上。

 

其他算法暂不测试了。。。

 

******************************************* 集群容错 *****************************************

在分布式网络通信中,容错能力是必须要具备的,什么叫容错呢? 从字面意思来看: 容:是容忍, 错:是错误。 就是容忍错误的能力。 我们知道网络通信会有很多不确定因素,比如网络延迟、网络中断、服务异常等,会造成当前这次请求出现失败。当服务通信出现这个问题时,需要采取一定的措施应对。 而 dubbo 中提供了容错机制来优雅处理这种错误,在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试

failover:

失败自动切换,当出现失败,重试其它服务器。(缺省) 通常用于读操作,但重试会带来更长延迟。 可通过 retries="2" 来设置重试次数(不含第一次)。

failfast:

快速失败,只发起一次调用,失败立即报错。 通常用于非幂等性的写操作,比如新增记录。

failsafe:

失败安全,出现异常时,直接忽略。 通常用于写入审计日志等操作。

failback:

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

forking:

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

broadcast:

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

在实际应用中查询语句容错策略建议使用默认 failover ,而增删改建议使用 failfast 或者使用 failover (retries=”0”) 策略,防止出现数据重复、添加等等其它问题!建议在设计接口时候把查询接口方法单独做一个接口提供查询。

 

******************************************* 服务降级 *****************************************

当某个非关键服务出现错误时,可以通过降级功能来临时屏蔽这个服务。降级可以有 几个层面的分类: 自动降级和人工降级; 按照功能可以分为:读服务降级和写服务 降级;

1. 对一些非核心服务进行人工降级,在大促之前通过降级开关关闭哪些推荐内容、评 价等对主流程没有影响的功能。

2. 故障降级,比如调用的远程服务挂了,网络故障、或者 RPC 服务返回异常。 那么 可以直接降级,降级的方案比如设置默认值、采用兜底数据(系统推荐的行为广告 挂了,可以提前准备静态页面做返回)等等 。

3. 限流降级,在秒杀这种流量比较集中并且流量特别大的情况下,因为突发访问量特 别大可能会导致系统支撑不了。这个时候可以采用限流来限制访问量。当达到阀值 时,后续的请求被降级,比如进入排队页面,比如跳转到错误页(活动太火爆,稍 后重试等)

那么,Dubbo中如何实现服务降级呢?Dubbo中提供了一个mock的配置,可以通过 mock来实现当服务提供方出现网络异常或者挂掉以后,客户端不抛出异常,而是通过 Mock数据返回自定义的数据 。

实现服务降级 

在dubbo-client端创建一个mock类,当出现服务降级时,会被调用:

接着修改客服端调用服务配置参数,增加mock配置,以及修改timeout=500, 表示本次调用的超时时间是0.5秒,这样可以模拟出失败的场景 需要配置cluster=failfast,否则因为默认是failover导致客户端会发起3次重试,等待的时间比较长。 继续修改服务端代码,只需要加一个休眠时间让客户端调用超时即可:

启动后浏览器调用结果:

 

******************************************* 启动时检查  *****************************************

Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"。 可以通过 check="false" 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。 

 registry、reference、consumer都可以配置check这个属性. 

 

******************************************* 多版本支持   *****************************************

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间 不引用。 可以按照以下的步骤进行版本迁移:

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

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

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

 

******************************************* 主机绑定   *****************************************

默认的主机绑定方式 
1. 通过LocalHost.getLocalHost()获取本机地址。 

2. 如果是127.*等loopback(环路地址)地址,则扫描各网卡,获取网卡IP。 1. 如果是springboot,修改配置:dubbo.protocol.host=”” 2. 如果注册地址获取不正确,可以通过在dubbo.xml中加入主机地址的配置 <dubbo:protocol host="205.182.23.201"> 
缺省主机端口 
dubbo: 20880 
rmi: 1099 
http: 80 
hessian: 80 
webservice: 80 
memcached: 11211 
redis: 6379

******************************************* Dubbo 新的功能   *****************************************

动态配置规则 
动态配置是Dubbo2.7版本引入的一个新的功能,简单来说,就是把dubbo.properties 中的属性进行集中式存储,存储在其他的服务器上。 那么如果需要用到集中式存储,那么还需要一些配置中心的组件来支撑。 目前Dubbo能支持的配置中心有:apollo、nacos、zookeeper 
 
其实,从另外一个角度来看,我们之前用zookeeper实现服务注册和发现,本质上就是使用zookeeper实现了配置中心,这个配置中心只是维护了服务注册和服务感知的 功能。在 2.7 版本中,dubbo 对配置中心做了延展,出了服务注册之外,还可以把其 他的数据存储在zookeeper上,从而更好的进行维护 
在 dubboadmin 添加配置 
应用名称可以是 global,或者对应当前服务的应用名,如果是 global 表示全局配置, 针对所有应用可见 配置的内容,实际就是 dubbo.properties 中配置的基本信息。只是同意存储在了 zookeeper上 
 

本地的配置文件添加配置中心 
在application.properties中添加配置中心的配置项,app-name对应的是上一步创建 的配置项中的应用名. dubbo.config-center.address=zookeeper://192.168.50.132:2181 
dubbo.config-center.app-name=spring-boot-provider

需要注意的是,存在于配置中心上的配置项,本地仍然需要配置一份。所以下面这些 配置一定要加上。否则启动不了。这样做的目的是保证可靠性 
dubbo.application.name=springboot-dubbo 
dubbo.protocol.port=20880 
dubbo.protocol.name=dubbo 
dubbo.registry.address=zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181 ,192.168.50.134:2181 

配置的优先级 
引入配置中心后,配置的优先级就需要关注了,默认情况下,外部配置的优先级最高, 也就是意味着配置中心上的配置会覆盖本地的配置。当然我们也可以调整优先级 
dubbo.config-center.highest-priority=false 

配置中心的原理 
默认所有的配置都存储在/dubbo/config节点,具体节点结构图如下。 namespace,用于不同配置的环境隔离。 config,Dubbo 约定的固定节点,不可更改,所有配置和服务治理规则都存储在此节点下。 

dubbo/application,分别用来隔离全局配置、应用级别配置:dubbo是默认group值, application对应应用名 dubbo.properties,此节点的node value存储具体配置内容 

元数据中心 
Dubbo2.7的另外一个新的功能,就是增加了元数据的配置。 在Dubbo2.7之前,所有的配置信息,比如服务接口名称、重试次数、版本号、负载策 略、容错策略等等,所有参数都是基于 url 形式配置在 zookeeper 上的。这种方式会 造成一些问题 1. url内容过多,导致数据存储空间增大 2. url需要涉及到网络传输,数据量过大会造成网络传输过慢 3. 网络传输慢,会造成服务地址感知的延迟变大,影响服务的正常响应。

服务提供者这边的配置参数有30多个,有一半是不需要作为注册中心进行存储和粗暗 地的。而消费者这边可配置的参数有 25 个以上,只有个别是需要传递到注册中心的。
 所以,在 Dubbo2.7 中对元数据进行了改造,简单来说,就是把属于服务治理的数据 发布到注册中心,其他的配置数据统一发布到元数据中心。这样一来大大降低了注册 中心的负载。 
元数据中心配置 
元数据中心目前支持redis和zookeeper。官方推荐是采用redis。毕竟redis本身对于 非结构化存储的数据读写性能比较高。当然,也可以使用zookeeper来实现。 在配置文件中添加元数据中心的地址 
dubbo.metadata-report.address=zookeeper://192.168.50.132:2181 dubbo.registry.simplified=true  //注册到注册中心的URL是否采用精简模式的 (与低版本兼容) 
 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐