dubbo 用户手册初读

dubbo 用户手册初读

参考:dubbo 用户手册官方地址

需求

  • 服务注册管理,提供负载均衡和故障转移;
  • 自动治理服务间的依赖关系;
  • 动态扩容;

架构

  • 注册中心和消费者、服务提供者之间是长连接,消费者和提供者与监控中心间使用短连接;
  • 每分钟同步一次监控数据到监控中心;

快速启动

  • 疑问:一个服务可以是提供者也可以是消费者,如果没有提供 dubbo:protocol 配置,即没有使用dubbo协议暴露端口,那肯定不是提供者?
  • 疑问:使用multicast广播注册中心作为服务发现地址,写死的配置如何避免注册中心单点故障,如果需要调整注册中心地址怎么办?
    • multicast广播注册中心适用于开发测试环境,优点是无需安装注册中心服务,缺点是依赖于网络路由,跨机房有风险;

依赖

  • 疑问:依赖于spring,如果应用中spring使用其他版本会不会有冲突?
  • 疑问:理论上说可以不依赖任何第三方包,要如何配置,有何缺点?

策略选择成熟度

  1. 注册中心
    • zookeeper,推荐,使用广,依赖于zk的稳定性
    • redis,支持基于客户端双写的方式,性能高
    • multicast,无需安装,去中心化,依赖于网络拓扑,适用于开发测试环境
    • simple,没有集群支持,可能单点故障,试用
  2. 远程调用协议
    • dubbo协议,推荐,NIO复用长连接,连接池并发处理,减少握手次数,加大并发效率较高,缺点是单个连接传输大文件时会成为瓶颈;
    • Rmi协议,基于TCP,可与原生RMI互操作,偶尔会连接失败,需要重建stub;
    • Hession协议,基于http,可以原生hession互操作,需要hession.jar支持,http短连接消耗大;
  3. NIO框架
    • netty,推荐,性能好
    • Mina,老牌框架,稳定
  4. 序列化
    • Hession序列化,推荐,性能较好,多语言支持,缺点是Hession各版本间可能存在兼容问题,dubbo使用hessian3.2.1;
    • dubbo序列化,不传送pojo信息,在大量pojo需要传输时性能较好,缺点是当参数对象增加字段时,需要外部文件声明;
    • json序列化,纯文本,跨语言,缺省采用FastJson解析,缺点是性能相对较差;
    • java序列化,原生支持,缺点是性能较差;
  5. java代理
    • Javassist代理,推荐,通过字节码生成代理类,代替反射,性能好,缺点是依赖于javassist.jar,perm内存配置大一些,如128M;
    • java代理,jdk原生支持,性能较差;
  6. 集群模式
    • Failover 集群,失败自动切换,读操作时推荐,缺点是重试会增加延迟;
    • Failfast 集群,快速失败,只发起一次,失败立即报错,适合非幂等的写操作,缺点是如果有机器正在重启,可能会发生调用失败;
    • Failsafe 集群,失败安全,出现失败时直接忽略,适用于收集日志等,缺点是会丢消息;
    • Failback 集群,失败自动恢复,后台记录失败请求定时重发,适用于消息通知等,缺点是不可靠,重启丢失;
    • Forking 集群,并行调用多个服务器,一个成功即可,适用于实时要求高的请求,缺点是会浪费资源;
    • Broadcast 集群,广播调用所有提供者,有一个失败即报错,适用于更新本地服务状态,如本地日志或缓存等,速度慢;
  7. 负载均衡策略
    • 随机,推荐,按照权重设置随机比例,缺点是重试时可能造成瞬间的压力不均;
    • 轮询,按照公约后权重设置轮询比例,缺点是存在慢的机器积累请求的问题,极端情况下会出现雪崩现象;
    • 最少活跃调用数,使慢的机器收到更少请求,缺点是不支持权重;
    • 一致性hash,相同参数总是发到同一个提供者,如果提供者挂了,通过虚拟节点分摊到其他提供者,缺点是压力不均;
  8. 路由规则
    • 条件路由,推荐,基于条件判断的路由,简单易用,缺点是复杂场景下很难使用条件描述;
    • 脚本路由,基于脚本,功能强大,缺点是有可能成为后门;
  9. java容器
    • spring容器,推荐,自动加载META-INF/spring下的配置文件;
    • Jetty容器,启动内嵌的Jetty,缺点是大量访问页面时,会影响服务器的线程和内存;
    • Log4j容器,自动配置log4j,自动按照进程划分目录,缺点是用户不能控制log4j的配置,不够灵活;

配置

  • dubbo:provider,dubbo:protocol 和 dubbo:service中某属性没有配置时,使用此缺省配置;
  • dubbo:consumer,dubbo:reference中某属性没有配置时,使用此缺省配置;
  • dubbo:reference,引用配置默认是延迟加载,即只有被注入到其他bean或者getbean时才会初始化,可以加上init=”true”表示立即加载;
  • 服务属性优先级,方法优于接口和全局,消费优于提供:消费方方法级>提供方方法级>消费方接口级>提供方方法级>消费方全局配置>提供方全局配置
  • 建议由服务提供方设置超时属性,因为服务提供方最清楚可能的消耗时间;
    dubbo-config

集群容错

dubbo集群筛选invoker

  • 如何选择到最终的提供方?

线程模型

dubbo调用模型

  • server收到请求后,是直接在IO线程中处理响应(A),还是提交到线程池中(B)?
  • 如果只是简单处理那A响应更快,因为省去了提交到B后的线程调度,但是如果这个请求要发起别的IO请求或者处理逻辑较慢,会导致接收不到其他请求;
  • Dispatcher 策略,all-所有消息都派发到线程池,direct-所有消息都在IO线程上直接执行,message-请求响应派发到线程池,连接断开时间、心跳检测等直接在IO线程执行,..
  • ThreadPool 策略,fixed-默认策略,固定线程池,不关闭一直持有,cached-缓存线程池,空闲一分后清理,limited-只增不减,防止大流量突袭造成性能问题;

回声测试

  • 用于检测服务是否可用,可用于监控等场景;
  • 所有暴露的服务均实现EchoService接口,直接强转后调用$echo方法判断即可;

本地存根

  • 适用于本地调用前后做ThreadLocal缓存、参数验证、失败后伪造容错数据等;
  • 讲proxy实例传递给Stub(Stub需包含可传入Proxy的构造方法);
  • <dubbo:service interface="com.foo.BarService" stub="com.foo.BarServiceStub" />

本地伪装

  • Mock,用于服务降级,是Stub的子集,只有在调用过程中出现RpcException时才执行,此时可返回失败提示信息而不是抛错,包含无参的构造方法;
  • <dubbo:service interface="com.foo.BarService" mock="com.foo.BarServiceMock" />

并发控制

  • 客户端或者服务端控制并发数量,executes-总的调用并发不能超过指定数量,actives-每个客户端的调用并发不能超过指定数量;

连接控制

  • 服务端连接控制,acceptes-接受的连接数不超过指定数量;
  • 客户端连接控制,conntections-使用的连接数不超过指定数量;

粘滞连接

  • 让调用者尽可能请求同一个提供者,除非该提供者挂了才换另一台;
  • <dubbo:protocol name="dubbo" sticky="true" /> 默认开启延迟连接以减少长连接数;
  • 疑问:只在dubbo协议下才有效?

令牌验证

  • 防止消费者绕过注册中心直接调用提供者;
  • 注册中心统一管理,灵活管理授权方式,不需要修改提供者;
  • 有随机token(UUID)和固定token(指定的)两种;
    dubbo token管理

路由规则

  • 支持条件路由和脚本路由,脚本路由更灵活,但是有后门的风险;
  • 可以实现黑白名单、读写分离(按照方法名路由)、重要应用隔离、分网段隔离等;

配置规则

  • 可以实现禁用提供者、调整权重、调整负载均衡策略、服务降级(临时屏蔽出错的非关键服务)等;

服务降级

  • 配置规则中的一种,用于降低服务不可用时对调用方的影响;
  • mock=force:return+null 在消费者方直接返回null,不发起调用;
  • mock=fail:return+null 失败后返回null;

优雅停机

  • 停机时,提供方不在接受新请求,等待已有请求运行完毕或超时,调用方不在发起新请求,或等待已有响应运行完毕或超时;
  • 原理是使用JDK的ShutdownHook,所以强制关闭(kill -9 PID)是不会触发的;

注册中心

ZooKeeper 注册中心

duoob zookeeper 注册中心存储结构

  • zk是一个树形的目录服务,支持消息订阅、推送,异常恢复等;
  • provider启动时将URL写入到 /dubbo/ServiceA/providers下;
  • consumer启动时订阅/dubbo/ServiceA/providers下的提供者地址,同时将URL写入到/dubbo/ServiceA/consumers下;
  • 监控中心启动时,订阅/dubbo/ServiceA下的所有提供者和消费者URL地址;
  • 提供者断电时,监控中心能自动删除提供者信息;
  • 注册中心重启时,自动恢复注册数据及订阅请求;
  • 支持订阅或注册失败时后台保存,定时重启;

在线运维

  • 同时支持telnet命令和http,支持查看服务提供者和消费者状态、服务上下线等;

最佳实践

分包
  • 接口、pojo、异常都放在api包中;
粒度
  • 服务接口尽可能大粒度,表示某一个功能而不是某一个功能的一个步骤,减少分布式事务的出现;
  • 使用表义的接口命名;
版本
  • 每个服务都要定义版本,建议两段版本号,第三段版本号只做兼容升级时使用;
  • 升级时先升一半提供者,再升所有消费者,最后升剩下的一半提供者;
  • 疑问:为什么?如果升级后的提供者有问题需要回滚,可以直接将消费者切换到使用旧版的提供者?
兼容性
  • 增加接口或pojo属性,可向后兼容,如果删除或更新,或者enum新增字段也不兼容,需变更版本号;
枚举值
  • 不建议使用肯定会扩展的字段作为enum,此时建议使用String;
  • 新增enum类型,如果是接口返回新增类型,先升级消费者,如果是接口入参新增类型,先升级提供者;
序列化
  • 所有服务参数和返回值都是值传递,不支持引用传递;
异常
  • 建议服务间使用异常而不是错误码;
  • 封装如dao、sql异常等,防止消费者序列化错误;
  • 如果出于性能优化考虑,重写异常的fillInStack方法,不填充后续异常堆栈;
  • 不建议抛出checked异常,消费者通常不知道如何处理;
调用
  • try...catch 应加在合适的回滚边界上,而不是只因为是dubbo服务就加;
  • 提供者方要进行参数校验,如果要提高性能,可以在api包中添加Stub完成校验;

推荐用法

  • 在Provider上多配置Consumer端属性,因为提供者对于服务性能参数配置更了解,如 timeout、loadbalance(默认random)、retry(默认2,即一共1+2=最多3次调用)、actives(消费者超过最大并发限制时新的调用请求进入WAIT,直到timeout);
  • 在Provider上多配置Provider端属性,如executes、threads(线程池大小);
  • 配置负责人(应用、服务、引用等),ower属性;
  • 配置dubbo缓存文件<dubbo:registry file="${user.home}/output/dubbo.cache"/>,用于注册中心挂掉时从缓存文件加载提供者列表,保证可用性,注意多进程使用不同的目录文件;
  • 监控配置,服务推荐使用固定端口,这样在注册中心挂掉后可以通过缓存文件保证可用性;
  • 推荐使用xml配置而不是properties
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值