深入理解dubbo分布式服务框架/负载/容错/调优/高可用/面试/技术选型

深入理解dubbo分布式服务框架/负载/容错/调优/高可用/面试

摘要:作为和cloud二分微服务框架天下的dubbo,无论是面试,还是在项目中,屡屡用到,作为阿里生态的政采云,在项目中也用到了dubbo作为服务中间件。本文从介绍dubbo开始,层层递进,讲解其使用情况/核心技术/节点说明/底层原理/高可用/技术选型/面试踩坑。


1、dubbo:分布式服务框架

什么是dubbo?
高性能和透明化的RPC远程服务调用方案(SOA服务治理方案,通过注册中心解决服务发现问题,通过hessian2序列化解决协议约定问题,通过Netty来实现网络传输

能做什么:(让多机器中的进程相互通信)
Dubbo实现服务调用是通过RPC的方式,即客户端和服务端共用一个接口(将接口打成一个jar包,在客户端和服务端引入这个jar包),客户端面向接口写调用,服务端面向接口写实现,中间的网络通信交给框架去实现

同类产品:微服务/服务中间件 阿里dubbo/HSF spring生态的Spring cloud facebook的thrift google的grpc twitter的finagle


2、dubbo核心部分包含:

核心 细节
1、面向接口的远程方法调用(就像调用本地方法一样调用远程方法) 基于长连接的NIO框架抽象封装,包括多种线程模型,序列化方式;
2、软负载均衡及容错机制(可以在内网代替F5等硬负载均衡器) 负载策略:轮询、随机、权重 ;容错:某个server挂了,还有其它的server,就算注册中心挂了,内部的缓存仍然有效
3、服务自动注册与发现 服务不需写死服务提供方地址,注册中心基于接口名查询服务提供者的ip地址,并且能够平滑添加或删除服务提供者

3、dubbo的使用情况?

在阿里内部:除淘系外的阿里子公司,都在使用dubbo,包括:中文主站,国际主站,aliexpree,阿里云,阿里金融,等等
外部:去哪儿,京东,吉利汽车,海康威视,政采云,网易考拉,当当(dubbox)

阿里集团内部使用的分布式服务框架HSF(high speed framework)dubbo从2012年底,阿里停止了对此开源项目的更新,然后由当当维护dubbox

HSF服务框架主要组件(简要介绍,非重点)

1)服务提供者
进行配置服务器发现、服务注册、订阅、失效转移等相关功能
目前淘宝内部大部分应用的部署方式还是一个虚拟机(对应一个操作系统)运行一个Tomcat容器(最近以Docker容器来部署应用)
2)服务调用者
3)地址服务器
地址服务器负责给服务提供者和服务调用者提供部署环境中所有配置服务器和diamond服务器的服务器列表信息,由Nginx提供服务能力

获取服务器列表
服务器列表返回

4)配置服务器(服务注册,服务订阅)
配置服务器在 HSF 框架中主要负责记录环境内所有服务发布和服务订阅信息,并将服务相关信息推送到服务节点上。
配置服务器与所有服务者提供者和调用者均是长连接,采用心跳的方式可监控到各服务运行节点的状况
5)Diamond 服务器(规则推送)
Diamond服务器是一个通用的统一配置管理服务,类似 ZooKeeper,给应用提供统一的配置设置和推送服务,使用场景非常广泛
在HSF服务框架中,则主要承担了服务调用过程中对于服务调用安全管控的规则、服务路由权重、服务QPS阀值等配置规则的保存,所有的信息均是持久化保存到了后端的MySQL 服务器

HSF细节

HSF框架采用Netty+Hessian数据序列化协议实现服务交互(与dubbo相同)
1、这类RPC协议采用多路复用的TCP长连接方式,在服务提供者和调用者间有多个服务请求同时调用时会共用同一个长连接,即一个连接交替传输不同请求的字节块
2、Hessian相比JDK标准的序列化方式(基于serializable接口的标准序列化),时间开销可以缩短很多
3、Hessian 是在性能和稳定性同时考虑下最优的序列化协议
HSF的容错机制
多个应用实例作为服务提供者提供某一相同服务
HSF有风险的地方
依赖大量的闭源项目工程,所以对外部实际也是不可用的。


4、如何使用dubbo?

1)基于rpc(传输层的协议,上层表现层不封装,跳过了很多步骤) 远程服务调用 直接写在@autowired中,很方便

传输层(报文) 网络层(包) 数据链路层(帧格式) 物理层(bite流)

2)dubbo使用方式 全spring配置 接口/ 实现类/zk注册中心
使用流程:
第一步:要在系统中使用dubbo应该先搭建一个注册中心,一般推荐使用zookeeper
第二步:有了注册中心然后是发布服务,发布服务需要使用spring容器和dubbo标签来发布服务。并且发布服务时需要指定注册中心的位置
第三步:服务发布之后就是调用服务。一般调用服务也是使用spring容器和dubbo标签来引用服务,这样就可以在客户端的容器中生成一个服务的代理对象,然后在action或者Controller中直接调用service的方法即可
Zookeeper注册中心的作用:注册和发现服务的作用。类似于房产中介的作用,在系统中并不参与服务的调用及数据的传输。

3)服务提供者

1、定义服务接口

package com.zjut.dubbotest.provider;
import java.util.List;
public interface DemoService{
	String sayHello(String name);
	public List getUsers();
}

2、实现服务接口

public class DemoServiceImpl implements DemoService{
	public String sayHello(String name){
		return "Hello"+name;
	}
	public List getUsers(){
		return list;
	}
}

3、配置Spring:接口、是吸纳类、zk地址

<!-- 声明服务接口 -->  
<dubbo:service interface="com.zjut.dubbotest.provider.DemoService" ref="demoService" />  
<!-- 服务实现类bean配置 -->  
<bean id="demoService" class="com.zjut.dubbotest.provider.DemoServiceImpl" />  
<!-- 使用zookeeper注册中心暴露服务地址 -- 常用-->  
<dubbo:registry address="zookeeper://127.0.0.1:2181" />  
<!-- 服务端口号 -->  
<dubbo:protocol name="dubbo" port="20880" />  
<!-- 提供方应用信息,用于计算依赖关系 -->  
<dubbo:application name="xixi_provider"  />  

4、服务消费者

<!--配置spring zk地址、接口-->
<!--使用zookeeper注册中心暴露服务地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 配置接口、生成远程服务代理,可以像使用本地bean一样使用demoService -->  
<dubbo:reference id="demoService" interface="com.zjut.dubbotest.provider.DemoService" /> 

加载spring文件并写代码调试 context.getBean(“demoSerice”)

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
context.start();
DemoService demoService = (DemoService)context.getBean("demoService");
String hello = demoServic.sayHello("tom");
syso(hello);

5、dubbo节点角色说明:*****

1)、Provider: 服务提供方
作用:服务提供者在启动时,向注册中心注册自己提供的服务
2)、Consumer: 调用远程服务的服务消费方
作用:服务消费者在启动时,向注册中心订阅自己所需的服务
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用
3)、Registry: 服务注册中心
作用:注册中心返回服务提供者地址列表给消费者;如果有变更,基于长连接推送变更数据给消费者

有哪些注册中心:

注册中心 特点
1、Zookeeper注册中心 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者; 建议使用dubbo233以上版本
2、redis 支持基于客户端双写的集群方式,性能高;采用key/Map存储,key存储服务名和类型,Map中key存储服务URL,value服务过期时间。基于redis的发布/订阅模式通知数据变更
3、multicast Multicast注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现。基于网络中组播传输实现

zookeeper注册中心的特点

1、采用push、pull相结合的方式:客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送watcher事件通知
2、软负载均衡:消费者需要在对等的服务提供方中选择一个来执行相关的业务逻辑。实现了动态DNS方案
3、分布式协调/通知 watcher注册、异步通知机制
4、ZooKeeper的节点是通过像树一样的结构来进行维护的,并且每一个节点通过路径来标示以及访问。除此之外,每一个节点还拥有自身的一些信息,包括:数据、数据长度、创建时间、修改时间等等

zookeeper分布式锁:

排它锁(写锁) :如果事务a对数据对象o1加了排它锁,那么在整个加锁期间,只允许事务a对o1进行读取和更新操作,其他任何事务都不能对o1进行操作,直至a释放排它锁。
java中的锁:synchronized和reentrantLock,在zookeeper中,没有类似这样的api可以使用
共享锁(读锁):加上共享锁,数据对所有事务可见

4)、Monitor: 统计服务的调用次调和调用时间的监控中心(提供可视化界面,看服务是否能运行)
定时每分钟发送一次统计数据到监控中心,统计服务消费者和提供者,在内存中累计调用次数和调用时间
5)、Container: 服务运行容器
服务容器Container负责启动,加载,运行服务


6、dubbo源码模块图?(使用maven管理,与maven工程很相似) 20181117

模块名 特点
1、dubbo-common 公共逻辑模块,包括util类和通用模型
2、dubbo-remoting 远程通讯模块,相当于dubbo协议的实现,如果rpc用rmi协议就不用这个包
3、dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理
4、dubbo-cluster 集群模块,将多个服务提供方伪装成一个提供方,包括:负载,容错,路由
5、dubbo-monitor 监控模块,统计服务调用次数,调用时间
6、dubbo-config 配置模块,是dubbo对外的api,用户通过config使用dubbo,隐藏dubbo实现的细节
7、dubbo-container 容器模块,是一个standlone容器,以简单的main加载spring启动,无需把dubbo放入tomcat中。

7、dubbo原理(invoker 动态代理)

1)dubbo总体架构(dubbo框架设计一共分为10层) dubbo框架
最上面的Service层是留给使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层
左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口;位于中轴线上的为双方都用到的接口

作用
1、服务接口层(service) 该层是与实际业务逻辑相关,根据服务提供方和服务消费方的业务设计对应的接口和实现
2、配置层(config) 对外配置接口,以serviceConfig和referenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类
3、服务代理层(proxy) 服务接口同名代理生成服务的客户端stub和服务器端skeleton,以serviceproxy为中心,扩展接口为proxyfactory
4、服务注册层(registry) 封装服务地址的注册和发现(使用zookeeper),以服务url为中心,扩展接口为registryFactory、registry和registryService。可能没有服务注册中心,此时服务提供方直接暴露服务
5、集群层cluster 封装多个提供者的路由及负载均衡,并桥接注册中心,以invoker为中心,扩展接口为cluster,directory,router和loadbalance
6、监控层monitor rpc调用次数和调用时间监控(dubbo-admin),以statistics为中心,扩展接口为monitorfactory,monitor和monitorService。
7、远程调用层protocal ** 封装RPC调用,以invocation和result为中心,扩展接口为protocol,invoker和exportor =》(完成非透明的RPC调用);protocol是服务域,它是invoker暴露和引用的主功能入口,他负责invoker的生命周期管理;invoker是实体域,它是dubbo的核心模型,其他模型都向他靠拢,或转换成它,它代表一个可执行体
8、信息交换层exchange 封装请求响应模式,同步转异步,以request和response为中心,扩展接口为 Exchanger(好熟悉,线程间交换数据), ExchangeChannel, ExchangeClient, ExchangeServer
9、网络传输层transport 抽象mina和netty为统一接口,以message为中心,扩展接口为channel,transportor,client、server和codec
10、数据序列化层serialize 可复用的一些工具,扩展接口为serialization,objectInput,objectOutput和ThreadPool

2)dubbo原理-启动解析、加载配置信息

application module registry monitor provider consumer protocol service reference annotation

3)服务提供者暴露一个服务的详细过程:基于反射,调用实现类通过网络协议发送出去

1、首先ServiceConfig类拿到对外提供服务的实际类引用(引用全部放在applicationcontext容器里面)(如:HelloWorldImpl)
2、然后通过ProxyFactory类的getInvoker方法使用引用生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化
3、接下来就是Invoker转换到Exporter的过程

Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程(如上图中的红色部分),下面我们以Dubbo协议和RMI协议的实现来进行说明:
Dubbo的实现: Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现
//RMI的实现RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,它通过Spring或Dubbo或JDK来实现RMI服务,通讯细节这一块由JDK底层来实现,这就省了不少工作量

4)服务消费者消费一个服务的详细过程基于动态代理,把接口的实例注入到invoker中
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。 //refer()引用远程服务
接下来把Invoker转换为客户端需要的接口(如:HelloWorld)。
关于每种协议如RMI/Dubbo/Web service等它们在调用refer方法生成Invoker实例的细节和上一章节所描述的类似

Invoker是Dubbo领域模型中非常重要的一个概念
Invoker实现了真正的远程服务调用。(invoker实现了集群容错)
用户代码通过proxy调用其对应的Invoker(DubboInvoker、 HessianRpcInvoker中的任何一个)

5)dubbo原理-服务调用


8、dubbo面试题?**

1)dubbo连接注册中心和直连的区别 dubbo服务都是注册在注册中心的,然后表现层查询注册中心获取服务真实地址,然后直接调用

  • 1、dubbo直连一般在开发中环境中使用,但是生产环境很少使用,因为服务是直接调用,没有使用注册中心,很难对服务进行管理。
    Dubbo直连如何使用?
    首先要取消广播,然后客户端直接到指定需要的服务的url获取服务即可。
    服务层配置:

    <dubbo:registry address=”N/A” /> 
    

    表现层配置:

     <!-- <dubbo:registry address=”multicast://224.5.6.7:1234” /> -->// 取消广播,从指定的url中获取服务
    <dubbo:service interface=”com.taotao.manager.service.TestService” id=”testService” timeout=”10000000” />
    
  • 2、使用zookeeper注册中心
    需要指定注册中心类型和注册中心地址,这个时候就不是把服务信息进行广播了,而是告诉给注册中心进行管理。
    表示从注册中心发现监控中心地址,否则直连监控中心:

    <dubbo:registry address=”registry” /> 	
    

2)dubbo与http传统调接口的方法的优势? 这个答案不好
dubbo是一个分布式服务框架,以及soa治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等

3)Dubbo支持哪些协议,每种协议的应用场景,优缺点?

协议 特点
1、dubbo协议(默认选择) 特点:1、单一长连接 (减少网络建立释放带来的性能损失)2、传输方式:NIO2异步非阻塞通讯(考点:异步通信是如何实现的?可以讲nio的三大核心)3、适用范围:适合大并发,小数据量的服务调用,以及消费者远大于提供者(使得数据不会堆积)4、传输协议 TCP (保证数据的可靠传输)5、使用Hessian来序列化 (比java自带的序列化方案强很多)
2、rmi协议 采用JDK标准的rmi协议实现,传输参数和返回参数对象需要实现Serializable接口,使用java标准序列化机制,使用阻塞式短连接 ,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议TCP。多个短连接,TCP协议传输,同步传输,适用常规的远程服务调用和rmi互操作。在依赖低版本的Common-Collections包,java序列化存在安全漏洞;缺点:使用rmi协议,一般会受防火墙的限制,所以对于外部与内部进行通信的场景,就不要使用rmi协议,可以选择http协议或hessian协议
3、webservice 基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多个短连接,基于HTTP传输,同步传输,适用系统集成和跨语言调用
4、http 基于Http表单提交的远程调用协议,使用Spring的HttpInvoke实现。多个短连接,传输协议HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用
5、hessian 集成Hessian服务,基于HTTP通讯,采用Servlet暴露服务,Dubbo内嵌Jetty作为服务器时默认实现,提供与Hession服务互操作。多个短连接,同步HTTP传输,Hessian序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件
6、memcache 基于memcached实现的RPC协议
7、redis 基于redis实现的RPC协议

4)、dubbo面试踩坑,使用dubbo遇到过的问题?

1. 增加提供服务版本号和消费服务版本号

<dubbo:service interface=“com.xxx.XxxService” ref=“xxxService” version=“1.0”/> 
<dubbo:reference id=“xxxService” interface=“com.xxx.XxxService” version=“1.0”/>

2. dubbo reference注解问题
@Reference只能在springbean实例对应的当前类中使用,暂时无法在父类使用;如果确实要在父类声明一个引用,可通过配置文件配置dubbo:reference

3、出现 RpcException: No provider available for remote service异常,表示没有可用的服务提供者***
1)检查连接的注册中心是否正确

  • 若是无法连接到注册中心,检查IP与端口号是否填写正确,检查注册中心是否正常启动

2)到注册中心查看相应的服务提供者是否存在

  • 检查服务层代码是否添加了@service注解,并且该注解的包一定是com.alibaba.dubbo.config.annotation包,不是org.Springframework的包

  • 通过dubbo-admin检查服务层和表现层的ip地址是否正确,以免影响通信

3)检查服务提供者是否正常运行

  • 注意包名不要导错,害老子找了半天,真他妈坑

4、服务提供者没挂,但在注册中心里看不到
首先,确认服务提供者是否连接了正确的注册中心,不只是检查配置中的注册中心地址,而且要检查实际的网络连接
其次,看服务提供者是否非常繁忙,比如压力测试,以至于没有CPU片段向注册中心发送心跳,这种情况,减小压力,将自动恢复。

5、spring和dubbo整合时可能会出现问题
jar包冲突 dubbo中maven依赖传递中存在spring包,当我们在项目中再次引入spring依赖包的时候,项目就会出现冲突问题。
解决方法:在pom文件中加入

<exclusions><groupId>org.springframework</groupId>

去掉dubbo的spring传递依赖

6、解决mapper映射文件不发布的问题?
在dao层的pom文件中添加下面的配置信息 ;若是不添加此节点,mybatis的mapper.xml文件都会被漏掉

<build>
<resources>
	<resource>
		<directory>src/main/java</directory>
		<includes>
			<include>**/*.properties</include>
			<include>**/*.xml</include>
		</includes>
		<filtering>false</filtering>
	</resource>
</resources>
</build>

7、同时配置了 XML 和 properties 文件,则 properties 中的配置无效

  • 只有 XML 没有配置时,properties 才生效。(优先级的问题)
    覆盖策略(优先级由低到高):dubbo.properties -> dubbo.xml -> 虚拟机启动参数 -D(最高)
    jvm启动Ddubbo.protocol.port=20880 -D参数优先,这样可以使用户在部署和启动时进行参数重写;dubbo.xml配置后,会使得dubbo.properties中响应配置项失效;(properties级别最低 ) ;dubbo推荐在Provider上尽量多配置Consumer 端属性;
    配置的覆盖规则:1) 方法级别配置优于接口级别,即小Scope优先 ;2) Consumer端配置 优于 Provider配置 优于 全局配置;3) 最后是Dubbo Hard Code的配置值
    公式:方法级优先,接口级次之,全局配置再次之
    如果级别相同,则消费方优先,提供方次之

    适用范围:timeout retries loadBalance actives

8、dubbo 缺省会在启动时检查依赖是否可用,不可用就抛出异常,阻止 spring 初始化完成,check 属性默认为 true。

  • 测试时有些服务不关心或者出现了循环依赖,将 check 设置为 false。

9、为了方便开发测试,线下有一个所有服务可用的注册中心,这时,如果有一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。

  • 让服务提供者开发方,只订阅服务,而不注册正在开发的服务,通过直连测试正在开发的服务。设置 dubbo:registry 标签的 register 属性为 false。

10、服务注册不上

  • 检查 dubbo 的 jar 包有没有在 classpath 中,以及有没有重复的 jar 包(时机开发不会有这样的问题)
    检查暴露服务的 spring 配置有没有加载(get)
    在服务提供者机器上测试与注册中心的网络是否通(通过dubbo monitor工具检查)

11、出现” 消息发送失败” 异常

  • 通常是接口方法的传入传出参数未实现 Serializable 接口。

5)dubbo工程架构,根据服务化最佳实践

1、分包 在api包防止一份spring的引用配置,这样,只需在spring加载过程中引用此配置即可
2、粒度 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某个步骤,否则将面临分布式事务问题(dubbo未提供分布式事务支持)
不建议使用过于抽象的通用接口,如:Map query(Map)

6)整合springboot
1、引入spring-boot-starter以及dubbo和curator的依赖
版本适配:Springboot starter0.2.0 java 1.8+ spring boot 2.0 dubbo 2.6.2
2、配置application.properties

application.name 是服务名,不能跟别的dubbo提供端重复
registry.protocol 是指定注册中心协议
registry.address 是注册中心的地址加端口号
protocol.name  是分布式固定是dubbo,不要改。
base-package   注解方式要扫描的包

3、dubbo注解 @Service、@Reference

7)dubbo调优?
1、配置原则

调优项 细节
1、配置原则 jvm启动D dubbo.protocol.port=20880 -D参数优先,这样可以使用户在部署和启动时进行参数重写;dubbo.xml配置后,会使得dubbo.properties中响应配置项失效; (properties级别最低 ) ;dubbo推荐在Provider上尽量多配置Consumer端属性;配置的覆盖规则:1) 方法级别配置优于接口级别,即小Scope优先 ;2)Consumer端配置 优于 Provider配置 优于 全局配置;3) 最后是Dubbo Hard Code的配置值
2、重试次数 dubbo失败自动切换当出现失败,重试其它服务器,但重试会带来更长延迟可通过retries="2"来设置重试次数
3、超时时间 为了避免超时导致线程资源耗尽,必须设置超时时间;消费端方法超时1000,消费端接口超时3000(超时后会自动重试3次。数据库会收到3条相同的数据),服务方方法超时2000,服务方接口超时4000 消费端全局6000,服务方全局5000
4、版本号 当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用;可以按照以下的步骤进行版本迁移在低压力时间段,先升级一半提供者为新版本;再将所有消费者升级为新版本;然后将剩下的一半提供者升级为新版本

9、如何实现dubbo的高可用? 整合spring cloud hystrix **

1)zookeeper注册中心宕机,还可以消费dubbo暴露的服务

  • 1、dubbo的健壮性

    1、监控中心宕掉不影响使用,只是丢失部分采样数据
    2、zookeeper的数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
    3、注册中心对等集群,任意一台宕掉后,将自动切换到另一台
    4、注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
    5、服务提供者无状态,任意一台宕掉后,不影响使用
    6、服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

  • 2、注册信息在zookeeper中如何保存?
    类似文件系统,zookeeper的根节点多了一个dubbo节点,最后一个节点是临时节点,而其他节点是持久节点,这样,当服务宕机时,这个节点就会自动消失,不再提供服务,服务消费者也不会再请求。不同的框架会在zookeeper上建不同的节点,互不影响。

2)集群下dubbo负载均衡配置(LoadBalance属性)

Dubbo集群的负载均衡有哪些策略 特点
1、Random LoadBalance 默认 随机,按权重设置随机概率
2、RoundRobin LoadBalance 轮循,按公约后的权重设置轮循比率;缺点:存在慢的提供者累积请求的问题;比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上
3、LeastActive LoadBalance 最少活跃;慢的提供者收到更少请求
4、ConsistentHash 一致性Hash策略;相同参数的请求总是发到同一提供者,基于虚拟节点,当某一台提供者挂时,原本发往该提供者的请求,平摊到其它提供者,不会引起剧烈变动;默认只对第一个参数Hash,如果要修改,请配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />;缺省用160份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />

3)整合hystrix,服务熔断与降级处理

  • 1、什么是服务降级?
    当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作

  • 2、如何实现服务降级?
    向注册中心写入动态配置覆盖规则:

    RegistryFactory  registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
    Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
    registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
    
     1、mock=force:return+null //表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响
     2、还可以改为 mock=fail:return+null //表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响
    
  • 3、集群容错
    在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试;提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,地址路由等集群支持。

容错机制 特点
1、Failover Cluster 默认 失败自动切换,当出现失败,重试其它服务器;通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。<dubbo:service retries=“2” /> 服务配置;<dubbo:reference retries=“2” /> 引用协议 或 dubbo:reference <dubbo:method name=“findFoo” retries=“2” /> </dubbo:reference>
2、Failfast Cluster 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
3、Failsafe Cluster 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作
4、Failback Cluster 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作
5、Forking Cluster 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks=”2”来设置最大并行数
6、Broadcast Cluster 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息

集群模式配置
在服务提供方和消费方配置集群模式<dubbo:service cluster=“failsafe”/>或<dubbo:reference cluster=“failsafe”/>
总结:
1、在实际应用中,查询语句容错策略使用Failover Cluster
2、增删改建议使用Failfast Cluster或者使用Failover Cluster(retries=”0”)策略,防止出现数据重复添加问题 (快速失败

  • 4、整合hystrix 还可更深入

    hystrix作用: 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能
    整合步骤:
    1、配置spring-cloud-starter-netflix-hystrix
    spring boot官方提供了对hystrix的集成,直接在pom.xml里加入依赖;然后在 Application类上增加@EnableHystrix来启用hystrix starter:

@SpringBootApplication
@EnableHystrix
public class ProviderApplication {

2、配置Provider端
在Dubbo的Provider上增加@HystrixCommand配置,这样调用就会经过Hystrix代理
3、配置Consumer端
对于Consumer端,则可以增加一层method调用,并在method上配置@HystrixCommand。当调用出错时,会走到fallbackMethod = "reliable"的调用里

@HystrixCommand(fallbackMethod = "reliable")
public String doSayHello(String name) {
	return demoService.sayHello(name);
}
public String reliable(String name) {
	return "hystrix fallback value";
}

10、 dubbo和spring cloud的技术选择?**

当前开源可选用的微服务框架主要有dubbo、spring cloud等, dubbo具有完备的功能和文档,且在国内被众多大型互联网公司选用(当当、考拉、政采云);Spring cloud可以说是一个更完备的微服务解决方案,对中小型的企业,spring cloud可能是一个更好的选择。

如何评估微服务?
1、内部是否存在异构系统集成的问题;
2、备选框架功能特性是否满足需求
3、http协议的通信对于应用的负载是否会成为瓶颈点
4、社区活跃度、团队技术储备

为什么选择spring cloud?

  • 1、从两个公司的背景来谈
    dubbo是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司,专注于自身的业务;spring cloud是spring家族的产品,专注于企业级开源框架的研发

  • 2、社区活跃度的角度
    dubbo是一个非常优秀的服务治理框架,并且在服务治理、灰度发布、流量分布这方面做得比spring cloud好;除了当当网在基础上增加了rest支持外、已经两年多的时间几乎没有任何更新;spring cloud自从发展到现在,任在不断的高速发展,现在spring cloud即将发布2.0版本

  • 3、从整个大的平台架构来讲

    1)dubbo框架只是专注于服务治理,如果我们需要使用使用注册中心、分布式跟踪这些内容都需要自己去集成Spring cloud几乎考虑了服务治理的方方面面,加上spring boot的支持,开发起来非常便利
    2)dubbo使用rpc通信协议,Spring cloud使用http协议REST API
    3)dubbo通信性能略胜于 spring cloud
    4)dubbo 通过接口的方式相互依赖 ,强依赖关系,需要严格的版本控制,对程序无入侵;Spring cloud 无接口依赖,定义好相关的json字段即可,对程序有一定入侵性

  • 4、从技术发展的角度来讲
    Dubbo一直停滞不前,自然有些掉队(这点我不认同);微服务、分布式链路跟踪等更多新的技术理念的出现,Spring急需一款框架来改善以前的开发模式,因此才会出现Spring Boot/Cloud项目

  • 总结
    dubbo曾经确实很牛逼,但是Spring Cloud是站在近些年技术发展之上进行开发,因此更具技术代表性


11、Dubbo与DubboX区别?

Dubbox:dubbo extensions是当当网基于dubbo2.x的升级版本,其中升级了zookeeper和spring版本,并且支持restful风格的远程调用

在REST中支持dubbo统一的方式用bean validation annotation作参数校验
在RpcContext上支持获取底层协议的Request/Response
支持采用Spring的Java Config方式配置dubbo
在Dubbo协议中支持基于Jackson的json序列化
在Spring AOP代理过的对象上支持dubbo annotation配置
修正@Reference annotation中protocol设置不起作用的bug
修正@Reference annotation放在setter方法上即会出错的bug

使用场景:

  • dubbo:使用Dubbo的RPC调用方式,服务间仍然会存在API强依赖
  • dubbox:相对于Dubbo支持了REST风格的原创调用(HTTP +JSON/XML)

12、 默认使用的是什么通信框架,还有别的选择吗?

  • 默认也推荐使用 netty 框架,还有 mina。

13、服务调用是阻塞的吗?

  • 默认是阻塞的,可以异步调用,没有返回值的可以这么做。

14、服务提供者能实现失效踢出是什么原理?

  • 服务失效踢出基于 zookeeper 的临时节点原理。

15、服务上线怎么不影响旧版本?(灰度发布)

  • 采用多版本开发,不影响旧版本。在配置中添加version来作为版本区分

16、如何解决服务调用链过长的问题?

  • 可以结合 zipkin 实现分布式服务追踪。(后续去了解)

17、说说核心的配置有哪些? 后续解析

核心配置有
dubbo:service/
dubbo:reference/
dubbo:protocol/
dubbo:registry/
dubbo:application/
dubbo:provider/
dubbo:consumer/
dubbo:method/


18、dubbo 在安全机制方面如何解决的?

  • dubbo 通过 token 令牌防止用户绕过注册中心直连,然后在注册中心管理授权,dubbo 提供了黑白名单,控制服务所允许的调用方。

19、服务调用超时问题怎么解决

  • dubbo在调用服务不成功时,默认是会重试两次的。这样在服务端的处理时间超过了设定的超时时间时,就会有重复请求,比如在发邮件时,可能就会发出多份重复邮件,执行注册请求时,就会插入多条重复的注册数据,那么怎么解决超时问题呢?如下
  • 对于核心的服务中心,去除dubbo超时重试机制,并重新评估设置超时时间。业务处理代码必须放在服务端,客户端只做参数验证和服务调用,不涉及业务流程处理 全局配置实例
    <dubbo:provider delay="-1" timeout=“6000” retries=“0”/>
    当然Dubbo的重试机制其实是非常好的QOS保证,它的路由机制,是会帮你把超时的请求路由到其他机器上,而不是本机尝试,所以 dubbo的重试机器也能一定程度的保证服务的质量。但是请一定要综合线上的访问情况,给出综合的评估。

出身一般,能在社会上有所作为的人,都有这么一些基本特征:有着极为强烈的进取心,一门心思扑在事业上,付出了比绝大多数人都要多的心血与努力;不管学历如何,都有着很强的学习能力,头脑活,而且都有一定的综合能力;赶上了一定的机遇或者有贵人帮扶进取心越强,能力越大,机遇越大,作为就越大

发布了26 篇原创文章 · 获赞 18 · 访问量 9749

猜你喜欢

转载自blog.csdn.net/qq_28959087/article/details/86529788