dubbo 是阿里巴巴旗下的一款 rpc 远程服务调用框架,承接过淘宝的双十一。后来被阿里巴巴开源。比如京东、当当开始使用dubbox 来进行分布式架构。 ( 钉钉 当当) Dubbo(读音 ˈ d ʌ b əʊ ]) 是阿里巴巴公司开源的一个高性能优秀的 服务框架 ,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 [1] Spring 框架无缝集成。Dubbo是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现2012年将 dubbo 开源, 2014 年阿里停止对 dubbo的维护。各大互联网厂商在dubbo 的基础上进行自己的维护,当当在dubbo 的基础上重新创建了分支进行维护,称为dubbox 。 2017 年杨勇在杭州的云溪大会宣布阿里巴巴重新对dubbo 进行维护。 2019年阿里巴巴宣布 将 dubbo 捐献给 apache 基金会。 dubbo 进入到 apach 的 孵化器。
目录
dubbo-admin/README_ZH.md at develop · apache/dubbo-admin · GitHub
dubbo的官网:文档 2.x | Apache Dubbo
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

当网站流量很小时,只需要一个应用,就将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架orm是关键--orm的对象关系映射,其中代表是Hibernate、和国内流行的半ORMmybatis框架
ORM框架:为了解决面型对象与关系数据库存在的互不匹配的现象的框架。
优点:在开发、部署、维护时成本较低
当访问量逐步增大,单一应用的增加机器带来的加速度越来越小(即所有请求都进入服务器,例如用户请求有10w、抢购请求90w,这个时候如果要进行对抢购请求调优,单一的增加机器其实用户请求(因为所有请求都进入服务器)也进行占用了机器,当访问量逐步增大的时候,也就使得单一的增加机器的加速度变小),提高效率的方法是将应用拆分成互不相关的几个应用以提高焦虑。此时用于加速前端页面开发的web框架是关键(MVC)
即 将图中的整个儿大应用:用户功能、订单功能以及商品功能拆分成一个一个的小应用,而且每个的小应用都是很完整的,比如说:用户小应用从页面Controller,到用户Service、再到用户Mapper,再到数据库都是完整的一套小系统,同时订单功能、商品功能也是一样。

这样的话如果 用户小应用的访问很多的时候,增加用户小应用的机器数量即可,这样就可以有效的通过增加机器来提高加速度

优点 对比单一应用框架提供并发能力
缺点 要求被拆分的功能必须互相独立,互不想干,随着功能的增加、交叉的功能越来越多
当垂直应用越来越多,应用之间交互是不可避免的,将核心业务抽取出来,作为独立的服务,逐步形参稳定的服务中心,是前端应用能更快的响应多变的市场需求。此时提高业务复用和整合的分布式服务框架是关键
优点 可以远程调用其他服务。有关系的服务也可以进行拆分,用于提高效率
缺点 服务之间的调用关系复杂
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加⼀个调度中⼼基于访问压⼒实时管理集群容量,提⾼集群利⽤率。此时,⽤于提⾼机器利⽤率的资源调度和治理中⼼(SOA)是关键。
核心是:资源调度和处理中心

在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,调用F5等硬件进行负载均衡。
当服务越来越多的时候,服务URL配置管理变得非常困难(硬编码问题--每次都要改动url地址) ,F5硬件负载均衡器的单点压力也越来越大。此时需要一个服务注册中心,动态地注册和发现服务,使得服务的位置透明。并通过在消费方获取服务提供方地址列表实现软均衡负载(可以布置多台解决高并发的问题)和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本(注册中心)
当进一步发展,服务间依赖关系变得错综复杂,甚至分不清那个应用在那个应用之前启动,架构师都不能完整的描述应用的框架关系。这时,需要自动画出应用键的依赖关系图,以帮助架构师理清关系。(监控中心)
接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支持?什么时候该加机器?为了解决这些问题,第一步,要将服务现在每天的调度量,响应时间,都统计出来,作为容量规划的参考指标。其次,要可以动态调整权重,在线上,将某台机器的权重一只哦加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阈值,记录此时的访问量,在以此访问量乘以机器数反推总容量 (监控中心的白名单、权重等)

以上是dubbo可以解决的需求


服务容器负责启动,加载,运行服务提供者。
服务提供者在启动的时候,向注册中心注册自己提供的服务。(服务名称和url)
服务消费者在启动的时候,向注册中心订阅自己需要的服务
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
服务消费者然后基于软负载均衡算法,选一台提供者进行调用,如果调用失败,在选另一台调用。
服务消费者和服务提供者,在内存中累计调用次数和时间,定时每分钟发送一次统计数据到监控中心
- 注册中心负责服务地址的注册和查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发其精气,压力较小
- 监控中心负责统计各服务调用次数、调用时间等,统计现在内存汇总后定时每分钟进行发送到监控中心服务器,并以报表进行展示
- 服务提供者向注册中心注册提供的服务,并汇报调用时间到监控中心,此时间不包括网络开销
- 服务消费者向注册中心获取服务提供者的地址列表,并根据负载均衡算法直接调用提供者,同时汇报调用时间到监控中心,此时间包括网络开销
- 注册中心,服务提供者,服务消费者三种之间均为长连接,监控中心除外
- 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者更新列表
- 注册中心和监控中心全部宕机,不影响已经运行的提供者和消费者,消费者在本地缓存了提供者列表
- 注册中心和监控中心都可选的,服务消费者可以直连服务提供者(N/A代表直连)
- 监控中心宕掉不影响使用,只是丢失部分采样数据(功能:监控数据)
- 数据库(注册中心)宕掉后,注册中心仍能通过缓存提供服务列表查询,不是不能注册新的服务
- 注册中心对等集群(有多个),任意一台宕掉后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍然能通过本地缓存进行通讯
- 服务提供者无状态,任意一台宕掉后,不影响使用(服务消费者会自动切换下一台服务提供者)
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
注册中心为对等集群,可动态增加机器部署实例,所以客户端将自动发现新的注册中心
服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者消息给消费者
当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力。下图是未来可能的一种架构
先搭建环境:首先RPC要实现远程服务调⽤,采⽤聚合⼯程
1.先创建父工程
pom.xml
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>com.sofwingroupId>
- <artifactId>spring-dubboartifactId>
- <version>1.0-SNAPSHOTversion>
- <modules>
- <module>spring-provedermodule>
- <module>spring-apimodule>
- <module>spring-consumermodule>
- <module> spring-proveder-centermodule>
-
- modules>
- <packaging>pompackaging>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.apache.dubbogroupId>
- <artifactId>dubboartifactId>
- <version>3.0.10version>
- dependency>
- dependencies>
- dependencyManagement>
-
- project>
2.spring-api模块 提供接口的
- package com.sofwin.service;
-
- /**
- * @author : wentao
- * @version : 1.0
- */
- public interface UserService {
-
- String getUser();
-
- }
服务端pom.xml
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>spring-dubboartifactId>
- <groupId>com.sofwingroupId>
- <version>1.0-SNAPSHOTversion>
- parent>
- <modelVersion>4.0.0modelVersion>
-
- <description>服务端description>
- <artifactId>spring-provederartifactId>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.dubbogroupId>
- <artifactId>dubboartifactId>
- dependency>
- <dependency>
- <groupId>com.sofwingroupId>
- <artifactId>spring-apiartifactId>
- <version>1.0-SNAPSHOTversion>
- dependency>
-
- dependencies>
-
- project>
服务端的service-api接口的实现类
- package com.sofwin.service.impl;
-
- import com.sofwin.service.UserService;
-
- /**
- * @author : wentao
- * @version : 1.0
- */
- public class UserServiceImpl implements UserService {
- public String getUser() {
-
- return "hello word 1-1"
- }
-
-
- }
服务端配置文件(关键)
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
-
- <bean id="userService" class="com.sofwin.service.impl.UserServiceImpl">bean>
-
-
- <dubbo:application name="proveder01">dubbo:application>
-
- <dubbo:registry address="N/A">dubbo:registry>
-
- <dubbo:protocol name="dubbo" port="20880">dubbo:protocol>
-
- <dubbo:service interface="com.sofwin.service.UserService" ref="userService">dubbo:service>
-
- beans>
开启服务(正常是通过tomcat来进行启动,这里测试我们就简单的写)
- package com;
-
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import java.io.IOException;
-
- /**
- * @author : wentao
- * @version : 1.0
- * 提供服务
- */
- public class App {
- public static void main(String[]args) throws IOException {
- ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
- context.start(); //启动容器
- System.in.read(); //让main方法阻塞 一直开启容器 提供服务
-
- }
- }
注意这个不是向之前是引入jar包,那样的形式是在同一台服务器的情况下,我们现在演示的情况是是服务提供者和服务消费者是不在同的服务器实现远程调用
服务消费者的pom.xml跟提供者是一样的
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
-
-
- <dubbo:application name="consumer01">dubbo:application>
-
- <dubbo:registry address="N/A" > dubbo:registry>
- <dubbo:protocol name="dubbo" port="20889">dubbo:protocol>
-
- <dubbo:reference id="userService" interface="com.sofwin.service.UserService" url="dubbo://127.0.0.1:20880" >dubbo:reference>
-
-
- beans>
- import com.sofwin.service.DtoService;
- import com.sofwin.service.ErrorService;
- import com.sofwin.service.PayService;
- import com.sofwin.service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import javax.sound.midi.Track;
- import java.io.IOException;
-
- /**
- * @author : wentao
- * @version : 1.0
- */
- public class AppConsumer {
- //实现远程的调用
- public static void main(String[]args) throws IOException {
- final ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
-
- UserService service =(UserService) context.getBean("userService");
- System.out.println(service.getUser());
-
-
- }
- }
1.在远程服务调用url存在当远程服务器地址发送改变的时候,服务就无法使用(我们设置死了)
2.因为规定了固定调用的url,而导致没有办法进行负载均衡
- <dependency>
- <groupId>org.apache.curatorgroupId>
- <artifactId>curator-frameworkartifactId>
- <version>5.2.1version>
- dependency>
- <dependency>
- <groupId>org.apache.curatorgroupId>
- <artifactId>curator-recipesartifactId>
- <version>5.2.1version>
- dependency>
- <dependency>
- <groupId>org.apache.curatorgroupId>
- <artifactId>curator-x-discoveryartifactId>
- <version>5.2.1version>
- dependency>
服务端
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
- <bean id="userService" class="com.sofwin.service.impl.UserServiceImpl">bean>
-
-
- <dubbo:application name="proveder01">dubbo:application>
-
- <dubbo:registry address="zookeeper://192.168.119.120:2181">dubbo:registry>
-
- <dubbo:protocol name="dubbo" port="20889">dubbo:protocol>
-
- <dubbo:service interface="com.sofwin.service.UserService" ref="userService" >dubbo:service>
-
- beans>
服务消费端
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
-
-
- <dubbo:application name="consumer01">dubbo:application>
-
- <dubbo:registry address="zookeeper://192.168.119.120:2181" >dubbo:registry>
- <dubbo:protocol name="dubbo" port="20889">dubbo:protocol>
-
-
-
-
- beans>
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random 随机调用
随机算法,存在服务堆积问题
随机,按权重设置随机概率(权重最大,访问概率越大)
可以设置在服务端、消费者、或者服务消费端的方法中
服务端:
- loadbalance 是设置什么形式的负载均衡 weight是权重
- <dubbo:service interface="..." loadbalance="random" weight=“200”/>
客户端
- loadbalance 是设置什么形式的负载均衡 weight是权重
- <dubbo:reference interface="..." loadbalance="random" weight=“200”/>
服务端方法
- <dubbo:service interface="...">
- <dubbo:method name="..." loadbalance="random"/>
- dubbo:service>
客户端方法
- <dubbo:reference interface="...">
- <dubbo:method name="..." loadbalance="random"/>
- dubbo:reference>
- loadbalance 是设置什么形式的负载均衡 weight是权重
- <dubbo:service interface="..." loadbalance="roundrobin" weight=“200”/>
- loadbalance 是设置什么形式的负载均衡 weight是权重
- <dubbo:service interface="..." loadbalance="leastactive" weight=“200”/>
不设置默认是对第一个参数进行一致性哈希计算
- loadbalance 是设置什么形式的负载均衡
- <dubbo:service interface="..." loadbalance="consistenthash " />
Dubbo缺省会在启动的时候检查依赖的服务是否可用,不可用会抛出异常,阻止spring
初始化完成,以便于上线的时候,能及时早发现问题 默认check=“true”
我们可以通过check=false来进行关闭检查。比如测试 测试的时候 服务端需要两个提供UserService的服务,但是服务消费者需要两个依赖userService 和roleService 这个时候就会进行依赖检查,报错,这个时候我们可以全部改成check=false
<dubbo:reference interface="com.foo.BarService" check="false" />
灰度发布(金丝雀发布),一般用于系统升级。在低压(访问数量小阶段),让部分消费者先调用新的提供者提供的服务(更新后的代码),其余消费者继续调用老的服务提供者(更新前的代码),在更新后的代码运行过程中出现问题,丢失掉少量的用户,如果没有问题,逐步让所有的消费者都去调用新的服务提供者
version配置来实现多版本控制
服务提供者
- <dubbo:service interface="com.sofwin.service.UserService"
- ref="userService" version="1.0">
- dubbo:service>
-
- <bean id="userService"class="com.sofwin.service.impl.UserServiceImpl">bean>
-
- <bean id="userServiceNew"class="com.sofwin.service.impl.UserServiceImplNew">bean>
-
- <dubbo:service
- interface="com.sofwin.service.UserService" ref="userServiceNew" version="1.1">
- dubbo:service>
服务消费者
-
- <dubbo:reference
- interface="com.sofwin.service.UserService" id="userService" check="false" timeout="10000" version="1.1">
- dubbo:reference>
服务分组的功能和版本控制的功能几乎一样,将version替代为group。目的不同。采用多版本控制的目的是为了升级,最终的目的是替代老版本。不同版本间不能互相调用。分组的目的是针对相同的接口给定不同的实现,这些实现是并存的,他们之间可以回想调用的
服务提供者
- <dubbo:service
- interface="com.sofwin.service.PayService" ref="alipayService" group="pay.alipay">
- dubbo:service>
-
- <dubbo:service
- interface="com.sofwin.service.PayService" ref="weChatPayService" group="pay.wechat">
- dubbo:service>
服务消费者
- <dubbo:reference
- interface="com.sofwin.service.PayService" id="payService1" group="pay.alipay">
- dubbo:reference>
-
- <dubbo:reference
- interface="com.sofwin.service.PayService" id="payService2" group="pay.wechat">
- dubbo:reference>
实现使用谁调用谁
dubbot缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器远大于服务提高自己机器数的情况
dubbo不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低
特性:
- 连接个数:单连接
- 连接方式:长连接
- 传输协议:TCP
- 传输方式:NIO异步传输
- 序列化:Hessian二进制序列化
- 使用范围:传入传出参数数据包较小(建议小于100k),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大 文件或超大字符
- 适用场景:常规的远程服务方法调用
注意:传输的时候实体类要进行系列化 ---实现Serializable接口

hessian协议底层采用http协议,采用servlet暴露服务
特性
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:http
- 传输方式:同步传输
- 序列化:Hessian二进制序列化
- 适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件
- 适用场景:页面传输,文件传输,或与原生hessian服务互相操作
超时时间: 请求时间+请求执行时间+响应时间
在服务消费者或者服务提供者端都可以设置timeout属性,当被调用的服务超出指定的时间,服务将不在等待,直接抛出异常

集群调用失败时,dubbo提供的容错方案,默认是失败就进行重试
集群容错只能应用在服务基本,不能应用在方法级别
在集群调用失败时,dubbo提供了多种容错方案,默认为failover 重试
常用的两种集群容错
失败自动切换,当出现失败,重试其他服务器。通常用于读操作,但重试会带来更大的延迟。可通过retries=“2” 来设置重试次数(不含第一次)
服务提供者
<dubbo:service cluster="failover" retries="2" />
服务消费者
<dubbo:reference cluster="failover" retries="2" />
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录
高并发的三种解决方案:降级、限流、缓存
当服务压力逐步递增,根据当前业务情况及限流的策略对一些服务进行降低服务级别的操作,目的是将这些服务所在的服务器的资源释放。比如:双十一客户不能查看历史订单信息和修改用户的个人资源。让这些服务器的资源释放,来用于抢购的功能进行提供服务。采用的方法就是服务降级。无法访问或不能修改
部分服务降级
全部服务降级
随机拒绝(春节抢票的,a 提示系统正忙,请重新抢票 b 可以正常抢到票 --保证服务器能正常使用,不让其访问量不超过阈值)
部分服务延迟(服务依然会执行,但是执行时间较长)

方法1
- <dubbo:reference interface="com.sofwin.service.PayService" id="payService1"
- group="pay.alipay" mock="return 网络不佳,请稍后访问" check="false">
- dubbo:reference>
方法2
- public class PayServiceMock implements
- PayService {
- public String pay() {
- return "服务不可⽤";
- }
- }
将mock改为true 或者实现类的全限定类名 都可以
- <dubbo:reference interface="com.sofwin.service.PayService" id="payService1"
- group="pay.alipay" mock="com.sofwin.service.PayServiceMock"
- check="false">
- dubbo:reference>
-
- 或者
-
- <dubbo:reference
- interface="com.sofwin.service.PayService" id="payService1" group="pay.alipay" mock="true"
- check="false">
- dubbo:reference>
用于现在并发量

consumer通过服务列表来调⽤provider,在调⽤过程中 consumer的调⽤次数和调⽤时间、provider被调⽤的次数和 时间都会被记⼊到监控中⼼中。提供了dubbo-admin,可以可视化的查看我们的监控中⼼的数据。
采⽤的vue+springboot前后端分离来构建 ⼯程托管在github上,可以使⽤git clone该⼯程的源码
中文文档
1. 下载代码: git clone https://github.com/apache/dubbo-admin.git
使用选择一个文件夹,进入cmd后执行上述命令将源码克隆到本地
2.在dubbo-admin-server/src/main/resources/application.properties 设置注册中心的配置

3.下载后进入cmd进行打包

输入 mvn clean package -Dmaven.test.skip=true 交过测试进行构建打包
4. 进入运行jar包 注意jar包的版本你们写自己的版本
cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar

出现这个代表运行成功
5. 后端运行完毕后 ,运行前端

进入ui文件后 进入cmd 执行 npm run dev

然后访问即可
默认账号密码就是这个
如果出现zookeeper无法连接的 --如下异常

可以在服务端和消费端设置
- <dubbo:registry address="zookeeper://192.168.119.120:2181" timeout="25000">
- <dubbo:parameter key="blockUntilConnectedWait" value="250">dubbo:parameter>
- dubbo:registry>
具体可以参考:springboot整合dubbo时连接zookeeper——天坑_夜尽天明~的博客-CSDN博客_dubbo连接本地zookeeper