文章目录
Dubbo
dubbo是分布式高性能的RPC框架
为什么需要用RPC呢
因为不拆分服务,单个服务太大,所有访问请求都会流向这个服务,导致压力很大,做集群有会导致功能在同一个服务互相影响,多人开发难度也大,
所以要把功能才分成微服务 当垂直应用越来越多,应用之间交互不可避免,(比如各个服务之间的业务交互),所以需要远程调用,
dubbo 的工作原理是什么? dubbo通过处理分层十层架构(https://dubbo.apache.org/zh/docs/v2.7/dev/design/)
- 服务接口层(Service):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。
- Config配置层:对外配置接口,以ServiceConfig、ReferenceConfig为中心,可以直接初始化配置类,也可以通过Spring解析配置生成配置类,设置调用超时,重试次数,连接数,分组,版本号等。
- Proxy服务代理层:服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory,默认:JavassistProxyFactory。
- Registry注册中心层:封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory、Registry、RegistryService。
- Cluster路由负载层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router、LoadBalance。
- Monitor监控层:RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor、MonitorService。
- Protocol协议远程调用层:封将RPC调用,调用Invoker,以Invocation、Result为中心,扩展接口为Protocol、Invoker、Exporter。选择协议,dubbo,rmi,http等
- Exchange信息交换层:封装请求响应模式,同步转异步,将协议数据请求封装为Request、Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient、ExchangeServer。
- Transport网络传输层:抽象MINA和Netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server、Codec。
- Serialize数据序列化层:可复用的一些工具,扩展接口为Serialization、ObjectInput、ObjectOutput、ThreadPool
接口,配置,代理,注册中心,路由负载均衡,监控,远程调用,信息转换,协议转发,序列化
调用链
调用动态代理-注册中心获取列表-路由负载均衡->监控请求->协议使用协议请求->exchange将协议封装成request等,->transport网络传输,netty->序列化传输
提供者监听端的进入网络传输后,进入序列化歇息->到exchange封装解析response->protocol协议解析->调用的代理->实现的接口的被代理类
SPI是啥思想?dubbo的SPI机制是怎么玩儿的?
SPI这个就可以用来做可插拔的插件机制,特别在dubbo中广泛应用,比如过滤器、复杂均衡重写等。
放在METE-INF/dubbo/internal目录下,如文件名就是接口名:com.alibaba.dubbo.rpc.Filter
myException=com.yym.frame.dubbostartmain.filter.RemoteTraceIdFilter
Dubbo如何做负载均衡?
- Random LoadBalance: 随机选取提供者策略,Dubbo的默认负载均衡策略
- RoundRobin LoadBalance: 轮循选取提供者策略
- LeastActive LoadBalance: 最少活跃调用策略
每个服务维护一个活跃数计数器。当A机器开始处理请求,该计数器加1,此时A还未处理完成 - ConsistentHash LoadBalance:一致性Hash,相同参数的请求总是发到同一提供者。
如果让你设计一个RPC框架,网络通信、代理机制、负载均衡等该如何设计?
目的是让服务A透明化 调用 服务B
按思路走,提供一个java接口,就可以直接调用到该接口的实现方了
1、走接口定义
2、定义调用的配置(如:超时等配置)
3、需要一个注册中心,将服务发现和维护起来,提供给注册和发现,可以选zookeeper,或则用eureka注册中心, 或则自己写一个
4、实现java动态代理
5、走负载均衡策略
6、远程调用的网络框架,用netty或则用web容器(jetty,tomcat等也行)
7、定义数据传输的序列化协议
dubbo 异步调用
配置好 ,
@Reference(async=true)
Future<String> barFuture = RpcContext.getContext().getFuture();
Dubbo 有哪些注册中心?
-
Zookeeper 注册中心
-
Redis 注册中心
-
dubbo与zookeeper的注册的节点目录
- /dubbo主目录
- /com.yym.service.TestService
- /providers
- /configurators
- /routers
- /consumers
- /com.yym.service.TestService
- /dubbo主目录
有一个根节点dubbo,然后下面挂接口,接口下有提供方列表,消费方列表,配置信息
消费和提供列表,节点名很长,包含协议版本,地址,方法
Dubbo Monitor 实现原理?
Consumer 端在发起调用之前会先走 filter 链;provider 端在接收到请求时也是先走 filter 链,然后才进行真正的业务逻辑处理。默认情况下,在 consumer 和 provider 的 filter 链中都会有 Monitorfilter。
Dubbo 服务治理
Dubbo的集群容错方案有哪些?
- Failover Cluster:失败自动切换,当出现失败,重试其它服务器。
通常用于读操作或幂等性的写操作,但重试会带来更长延迟。(默认策略) - Failfast Cluster:快速失败,只发起一次调用,失败立即报错。
通常用于非幂等性的写操作,比如新增记录。 - Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
- Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
- Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2″ 来设置最大并行数。
- Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。
默认的容错方案是 Failover Cluster。
dubbo
超时重试-300ms
重试机制-retries
服务降级-mock
Dubbo 支持哪些序列化方式?
序列化:将对象转化为二进制数据
1、默认使用dubbo协议
https://www.cnblogs.com/duanxz/p/3555876.html
基于hessian做为序列化,采用tcp协议,hessian二进制序列化,使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高,消费者比提供者个数多
- 消费者比提供者个数多,单一消费者无法压满提供者
1个服务提供者需要20个服务消费者才能压满网卡 - 为什么不能传大包
因dubbo协议采用单一长连接(单个连接获取的带宽一般是限制的,没有多个连接能有的带宽多) - 为什么使用单一连接
保证单一消费者不会压死提供者,
长连接,减少连接握手验证等,
并使用异步IO,复用线程池,
-
- 常规普通的RPC业务调用适合,数据量少,传输更快
2、rmi协议,
基于java二进制序列化,多个短连接,参数及返回值需实现 Serializable 接口
- 传入传出参数包大小混合,可传文件,
- 常规远程服务方法调用,与原生RMI服务互操作
多个短连接,可以拥有更多的带宽,适合数据结构复制或大量数据的传输时效率最快
3、hessian 协议
Hessian 协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现
采用HTTP协议传输,Hessian二进制序列化
多连接的短连接,传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件(使用于页面传输,文件传输)
4、http协议
提供给浏览器等其他服务接入的http协议服务,表单序列化
5、webservice
http,多短连接,SOAP文本序列化 ,系统集成,跨语言调用。
6、thrift
跨语言提供,很多其他语言会用该协议
7、memcached
8、redis
9、RestFull
dubbo mock 服务降级
当调用异常时,如果没有实现mock降级处理,就会抛出RpcException异常
以下是出现降级的情况
- 超时降级
- 失败次数降级
- 限流降级
- 故障降级
dubbo没有熔断机制,只能通过限流机制。
- 客户端限流
信号量限流 (通过统计的方式)
连接数限流 (socket->tcp) - 服务端限流
线程池限流 (隔离手段)
信号量限流 (非隔离手段)
接收数限流 (socket->tcp)
Dubbo如何优雅的下线服务?
通过runtime钩子Runtime.addShutdownHook(Thread hook),
ProtocolConfig.destroyAll();
13 RpcContext是在什么维度传递的(消费者 传给 提供者 拼多多面试题)?
RpcContext内部的实现是一个 ThreadLocal.
private static final ThreadLocal LOCAL = new ThreadLocal() {
@Override
protected RpcContext initialValue() {
return new RpcContext();
}
};
在业务中可以通过如下隐式传参
RpcContext.getContext().setAttachment(“name”, “小明”);
RpcContext.getContext().setAttachment(“sex”, “男”);
然后调用provider时会经过ContextFilter获取这些传过来的隐样传参数据,并设置到自己的RpcContext中。
dubbo的zookeeper注册中心挂了
优先订阅注册中心获取服务提供者,如果注册中心访问异常,获取本地缓存的服务提供者。