背景
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
架构
节点角色说明
节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器
调用关系说明
服务消费方
注解
服务提供方
在需要暴露服务的类上使用注解
服务消费方
在需要暴露服务的类上使用注解
协议
dubbo://
Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低
特性
缺省协议,使用基于 mina 1.1.7 和 hessian 3.2.1 的 tbremoting 交互。
连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO 异步传输(NIO)
序列化:Hessian 二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
约束
参数及返回值需实现 Serializable 接口
参数及返回值不能自定义实现 List, Map, Number, Date, Calendar 等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。
配置
配置协议:
设置服务协议:
多端口:
rmi://
RMI 协议采用 JDK 标准的 java.rmi.* 实现,采用阻塞式短连接和 JDK 标准序列化方式。
特性
连接个数:多连接
连接方式:短连接
传输协议:TCP
传输方式:同步传输
序列化:Java 标准二进制序列化
适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
适用场景:常规远程服务方法调用,与原生RMI服务互操作
约束
参数及返回值需实现 Serializable 接口
dubbo 配置中的超时时间对 RMI 无效,需使用 java 启动参数设置:-Dsun.rmi.transport.tcp.responseTimeout=3000,参见下面的 RMI 配置
hessian://
Hessian协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。
Dubbo 的 Hessian 协议可以和原生 Hessian 服务互操作,即:
提供者用 Dubbo 的 Hessian 协议暴露服务,消费者直接用标准 Hessian 接口调用
或者提供方用标准 Hessian 暴露服务,消费方用 Dubbo 的 Hessian 协议调用。
特性
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
适用场景:页面传输,文件传输,或与原生hessian服务互操作
依赖
com.caucho
hessian
4.0.7
约束
参数及返回值需实现 Serializable 接口
参数及返回值不能自定义实现 List, Map, Number, Date, Calendar 等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。
配置
定义 hessian 协议:
设置默认协议:
设置 service 协议:
多端口:
http://
基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现
特性
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:表单序列化
适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
适用场景:需同时给应用程序和浏览器 JS 使用的服务。
约束
参数及返回值需符合Bean 规范
webservice://
基于 WebService 的远程调用协议,基于 Apache CXF 的 frontend-simple 和 transports-http 实现 。
可以和原生 WebService 服务互操作,即:
提供者用 Dubbo 的 WebService 协议暴露服务,消费者直接用标准 WebService 接口调用,
或者提供方用标准 WebService 暴露服务,消费方用 Dubbo 的 WebService 协议调用。
依赖
org.apache.cxf
cxf-rt-frontend-simple
2.6.1
org.apache.cxf
cxf-rt-transports-http
2.6.1
特性
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:SOAP 文本序列化
适用场景:系统集成,跨语言调用
约束
参数及返回值需实现 Serializable 接口
参数尽量使用基本类型和 POJO
注册中心
zookeeper 注册中心
Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用
支持以下功能:
当提供者出现断电等异常停机时,注册中心能自动删除提供者信息
当注册中心重启时,能自动恢复注册数据,以及订阅请求
当会话过期时,能自动恢复注册数据,以及订阅请求
当设置
可通过
可通过
支持 * 号通配符
配置
Zookeeper 单机配置:
或:
Zookeeper 集群配置: Multicast 注册中心 Redis 注册中心 服务监控 在服务提供方通过telnet命令监控服务 回声测试 DUBBO常用配置 多协议暴露服务 多注册中心 不同服务使用不同注册中心 多注册中心引用 服务分组( 一个接口多实现 ) 多版本 结果缓存 服务上下文信息 服务提供方 通过RpcContext可以进行隐式传参 异步调用 步骤二、编写服务提供者 本地伪装 dubbo过滤器 通过@Service(filter = “”)指定使用过滤器!! 集群容错 负载均衡 常见问题 说说dubbo的实现原理? 你们dubbo使用的是什么注册中心?除了这个还有哪些注册中心?
或:
Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。
组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255
配置
或
基于 Redis实现的注册中心。
使用 Redis 的 Key/Map 结构存储数据结构:
主 Key 为服务名和类型
Map 中的 Key 为 URL 地址
Map 中的 Value 为过期时间,用于判断脏数据,脏数据由监控中心删除
使用 Redis 的 Publish/Subscribe 事件通知数据变更:
通过事件的值区分事件类型:register, unregister, subscribe, unsubscribe
普通消费者直接订阅指定服务提供者的 Key,只会收到指定服务的 register, unregister 事件
监控中心通过 psubscribe 功能订阅 /dubbo/*,会收到所有服务的所有变更事件
调用过程:
配置
或
或
或
选项
可通过
可通过
failover: 只写入和读取任意一台,失败时重试另一台,需要服务器端自行配置数据同步
replicate: 在客户端同时写入所有服务器,只读取单台,服务器端不需要同步,注册中心集群增大,性能压力也会更大
Simple 注册中心
Simple 注册中心本身就是一个普通的 Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致。
配置
将 Simple 注册中心暴露成 Dubbo 服务:
引用 Simple Registry 服务:
或者:
或者:
部署服务管理中心
其实管理中心就是一个web应用,部署到tomcat即可。
使用
telnet localhost 20880
命令
ls
ls: 显示服务列表
ls -l: 显示服务详细信息列表
ls XxxService: 显示服务的方法列表
ls -l XxxService: 显示服务的方法详细信息列表
ps
ps: 显示服务端口列表
ps -l: 显示服务地址列表
ps 20880: 显示端口上的连接信息
ps -l 20880: 显示端口上的连接详细信息
cd
cd XxxService: 改变缺省服务,当设置了缺省服务,凡是需要输入服务名作为参数的命令,都可以省略服务参数
cd /: 取消缺省服务
pwd
pwd: 显示当前缺省服务
trace
trace XxxService: 跟踪 1 次服务任意方法的调用情况
trace XxxService 10: 跟踪 10 次服务任意方法的调用情况
trace XxxService xxxMethod: 跟踪 1 次服务方法的调用情况
trace XxxService xxxMethod 10: 跟踪 10 次服务方法的调用情况
count
count XxxService: 统计 1 次服务任意方法的调用情况
count XxxService 10: 统计 10 次服务任意方法的调用情况
count XxxService xxxMethod: 统计 1 次服务方法的调用情况
count XxxService xxxMethod 10: 统计 10 次服务方法的调用情况
invoke
invoke XxxService.xxxMethod({“prop”: “value”}): 调用服务的方法
invoke xxxMethod({“prop”: “value”}): 调用服务的方法(自动查找包含此方法的服务)
status
status: 显示汇总状态,该状态将汇总所有资源的状态,当全部 OK 时则显示 OK,只要有一个 ERROR 则显示 ERROR,只要有一个 WARN 则显示 WARN
status -l: 显示状态列表
log
log debug: 修改 dubbo logger 的日志级别
log 100: 查看 file logger 的最后 100 字符的日志
help
help: 显示 telnet 命帮助信息
help xxx: 显示xxx命令的详细帮助信息
clear
clear: 清除屏幕上的内容
clear 100: 清除屏幕上的指定行数的内容
exit
exit: 退出当前 telnet 命令行
回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。
所有服务自动实现 EchoService 接口,只需将任意服务引用强制转型为 EchoService,即可使用。
Spring 配置:
代码:
// 远程服务引用
MemberService memberService = ctx.getBean(“memberService”);
EchoService echoService = (EchoService) memberService; // 强制转型为EchoService
// 回声测试可用性
String status = echoService.$echo(“OK”);
assert(status.equals(“OK”));
直连提供者
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。
通过 XML 配置
如果是线上需求需要点对点,可在 dubbo:reference 中配置 url 指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:
多协议
Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
不同服务不同协议
不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议
Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的。
多注册中心注册服务
比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。
比如:CRM 有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。
比如:CRM 需同时调用中文站和国际站的 PC2 服务,PC2 在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。
当一个接口有多种实现时,可以用 group区分。
服务提供
服务引用
任意组引用
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:
在低压力时间段,先升级一半提供者为新版本
再将所有消费者升级为新版本
然后将剩下的一半提供者升级为新版本
老版本服务提供者配置:
新版本服务提供者配置:
老版本服务消费者配置:
新版本服务消费者配置:
如果不需要区分版本,可以按照以下的方式配置 :
缓存的好处不用多说,在传统的业务开发中,引入缓存可以帮助减轻数据库的压力,在分布式的系统中,引入缓存有两种方式,第一种是在调用者,也就是消费者端引入缓存,如果能够命中缓存,则默认读取缓存中的内容,不需要再进行远程调用,这样就减少了一次IO 请求,也能减少服务提供者的压力;第二种就是在服务提供者提供缓存,同样的请求,把对请求的结果缓存在某个地方,比如Redis,或者java内存中,亦或者第三方的内存容器里,当数据库有更新的时候,同步更新内存,当新的请求在缓存中没有命中的时候,就会击穿缓存落到数据库实例上。
以上就是缓存设计的基本也是最简单的实现方式,不过如何提高缓存的命中率,有很多的算法,有Least Frequently Used(LFU),LeastRecently User(LRU),First in First out(FIFO)等等的算法。
Dubbo也支持缓,Dubbo 提供声明式缓存,并且是在服务消费者实现了缓存,因为Dubbo是一个纯粹的服务调用框架,所以它并没有实现高性能高命中的缓存策略,其实也没有办法实现,因为没有具体的业务场景,如何提高缓存命中率,跟业务是息息相关的,哪些是热点数据,在具体业务中才会知道,所以Dubbo只提供了三种缓存方案.
lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。
threadlocal 当前线程缓存,比如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。
jcache 与 JSR107 集成,可以桥接各种缓存实现
配置
RpcContext服务上下文记录的是当前服务调用过程中所需的环境信息
RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求时,RpcContext的状态都会变化。比如:A调用B,B调用C,则B机器上,在B调用C之前,RpcContext记录的是A调用B的信息,在B调用C之后,RpcContext记录的是B调用C的信息。
服务消费方
基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对于多线程开销较小。
延迟暴露
如果你的服务需要预热时间,比如初始化缓存数据,等待相关资源就位等等,可以使用delay进行延迟暴露。
并发与连接控制(限流)
https://blog.csdn.net/tianyaleixiaowu/article/details/74942405
Dubbo可以对服务的连接和并发数量进行控制。如下:
服务降级
什么是服务降级?当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
本地存根
https://www.cnblogs.com/hzhuxin/p/8250602.html
步骤一、编写服务接口类步骤三、配置服务提供者
步骤四、编写服务消费者
步骤五、编写本地存根类
https://blog.csdn.net/xingfeichen/article/details/80584636
编写本地伪装类Mock,然后在@Reference(mock = “mock类的全路径”)!!
在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。
各节点关系:
这里的 Invoker 是 Provider 的一个可调用 Service 的抽象,Invoker 封装了 Provider 地址及 Service 接口信息
Directory 代表多个 Invoker,可以把它看成 List ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选
集群容错模式
可以自行扩展集群容错策略
Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
重试次数配置如下:
或
或
dubbo:reference
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
集群模式配置
按照以下示例在服务提供方和消费方配置集群模式
或
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用。
可以自行扩展负载均衡策略。
https://blog.csdn.net/lihao21/article/details/54695471
负载均衡策略
Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
• 轮循,按公约后的权重设置轮循比率。
• 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
• 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
• 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
• 一致性 Hash,相同参数的请求总是发到同一提供者。
• 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
• 缺省只对第一个参数 Hash,如果要修改,请配置
• 缺省用 160 份虚拟节点,如果要修改,请配置
配置
服务端服务级别
客户端服务级别
服务端方法级别
客户端方法级别
问题:
dubbo作用?
提供RPC远程服务调用方案,实现不同系统之间的通信的,解决分布式部署,soa服务治理解决方案
zookeeper
注册中心挂掉怎么办 ?
服务提供方与服务消费方的通信协议??
服务提供者挂掉怎么办??