1.为什么需要dubbo
dubbo不仅仅是一个RPC框架,还是一个服务治理框架
远程通信背景
技术架构的发展从单体到分布式,是一种顺势而为的架构演进,和传统的单体架构相比,分布式多了一个远程服务之间的通信
不管是 soa还是微服务,他们本质上都是对于业务服务的提炼和使用。强调一个服务通常以独立的形式存在。各个服务之间通过网络调用。远程服务之间的如何相互调用才是实现分布式的关键因素
在远程通信这个领域,其实有很多的技术,比如 Java 的 RMI、WebService、Hessian、Dubbo等 RPC 框架,现在我们接触得比较多的应该就是 RPC 框架 Dubbo 以及应用协议 Http
RPC 的底层原理,服务与服务之间的调用无非就是跨进程通信而已,我们可以使用 socket 来实现通信,我们也可以使用nio 来实现高性能通信
如果我们自己开发一个网络通信,需要考虑到
- 底层网络通信协议的处理
- 序列化和反序列化的处理工作
但是这些工作本身应该是通用的,应该是一个中间件服务。为整个公司提供远程通信的服务。而不应该由业务开发人员来自己去实现,所以才有了这样的 rpc 框架,使得我们调用远程方法时就像调用本地方法那么简单,不需要关心底层的通信逻辑
服务治理
到目前为止,还只是满足了通信的基础需求,但是当开始大规模的服务化以后,远程通信带来的弊端就越来越明显了。比如说
- 服务链路变长了,如何实现对服务链路的跟踪和监控呢?
- 服务的大规模集群使得服务之间需要依赖第三方注册中心来解决服务的发现和服务的感知问题
- 服务通信之间的异常,需要有一种保护机制防止一个节点故障引发大规模的系统故障,所以要有容错机制
- 服务大规模集群会使得客户端需要引入负载均衡机制去实现请求分发,传统的 RPC 技术在这样的场景中显得力不从心,因此很多企业开始研发自己的RPC框架,比如阿里的HSF、Dubbo;、京东的 JSF 框架、当当的 dubbox、蚂蚁金服的 sofa 等等
服务治理主要就是针对大规模服务化以后,服务之间的路由、负载均衡、容错机制、服务降级这些问题的解决方案,而 Dubbo 就实现了这些功能
dubbo
Dubbo提供的基本功能是服务的集群治理,其基本结构图如下:
- Provider:暴露服务的服务提供方
- Consumer:调用远程服务的服务消费方
- Registry:服务注册与发现的注册中心
- Monitor:统计服务的调用次数和调用时间的监控中心
- Container:服务运行容器
服务运行过程:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用
6.监控中心 : 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
Dubbo可以动态升级扩展服务提供者和注册中心集群,并且可以实现动态部署
Dubbo的用法:
服务提供方:
remote-provider.xml:
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="hello-world-app" />
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" />
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl" />
服务消费方:
remote-consumer.xml:
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-helloworld-app" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" />
服务消费方的行为是:
首先使用dubbo的格式引用一个远程服务,并且定义其id,然后声明一个bean,这个bean使用了定义的远程引用
cmd管理本地dubbo服务
使用命令:
telnet localhost 20880
就可以进入dubbo中,使用dubbo命令就可以查看节点,例如:
ls : 查看服务提供者信息
PROVIDER:
com.gupaoedu.dubbo.IPayService
ls -l : 查看服务提供者详细信息
PROVIDER:
com.gupaoedu.dubbo.IPayService -> published: Y
cd IPayService :进入到指定的服务中
在服务中使用ls,可以查看当前服务的情况:
Use default service IPayService.
com.gupaoedu.dubbo.IPayService (as provider):
pay
dubbo常用配置
1.多版本支持
dubbo是基于url的,因此所有的配置都会在url上有对应的体现
2.主机绑定(绑定IP地址)
dubbo服务的IP地址,也就是dubbo的服务在注册中心里面对应的url中的IP地址部分,如下所示:
dubbo://192.168.1.116:20880/xxxxxx/IHelloServer
读取host:
- NetUtils.isInvalidLocalHost(host)从配置文件中读取host
- host = InetAddress.getLocalHost().getHostAddress();
默认端口:
dubbo:20880
rmi:1099
http:80
hessian:80
webService:80
3.集群容错
dubbo提供6种容错机制
- failsafe :失败安全,把错误吞掉(记录日志)
- failover :(默认) 重试其他服务器,retries 重试,默认次数:2
- failfast :快速失败,失败立马报错
- failback :失败自动恢复,记录失败定时重发
- forking forks :设置并行数
- broadcast:广播,任意一台报错,则执行的方法报错(测试常用)
配置方式:
<dubbo:reference id="gpHelloService"
interface="com.gupaoedu.dubbo.IGpHello"
protocol="dubbo" cluster="failsafe"/>
4.服务降级
容错是降级的一种机制
降级的目的是保证核心服务可用
比如购物车,支付这些核心的服务是不可能降级的,那么可以被降级的就是一些不太核心的服务
自动降级、手动降级、限流降级
自动降级提供一些默认数据来兜底
手动降级就是关闭一些非核心业务
降级的方式:mock
<dubbo:reference id="gpHelloService"
interface="com.gupaoedu.dubbo.IGpHello"
protocol="dubbo" mock="com.test.Mock"/>
mock不影响对服务端的正常访问,但是当服务端出错的时候,某些容错机制和mock可能有冲突的
5.配置优先级别
<dubbo:reference id="gpHelloService" interface="com.gupaoedu.dubbo.IGpHello"
protocol="dubbo"timeout="50"/>
假如客户端和服务端都配置了过期时间timeout,那么到底使用的哪个呢
1、方法级别优先,然后是接口,最后是全局
2、如果级别是一样的,那么客户端的配置优于服务端
哪些配置应该放在服务端,哪些放在客户端
很简单服务端了解的就放在服务端,例如一个服务方法的调用,这个方法需要执行多长时间,可以提供多大的吞吐量,服务端是比客户端清楚的,那让服务端来配置方法的过期时间,客户端就不需要考虑这个问题了
而对于容错机制,这个方法出错需要做什么,采取什么策略,应该是客户端把握的事情
6.什么是SPI
通过SPI的方式我们可以很方便的开发我们自己的扩展
什么意思呢?
例如java的API定义了访问数据库的方式,oracle和MySQL都根据java的API规范进行了自己的实现,我们在使用的时候只需要依赖对应的实现就可以使用特定的数据库提供的功能,同理当我们想要自己实现某个规范的时候我们也可以通过SPI的方法来进行自己的扩展
步骤:(spring的规范)
META-INF/service/接口全路径文件(填写对应的实现类)
Dubbo的SPI规范:
META-INF/dubbo; META-INF/internal; ?META-INF/services