本篇一句话总结:Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能。
正文开始:
上面这几个问题,是每个刚接触 Dubbo的人都想知道的。下面小兵综合自己的理解和使用情况,在分布式专题里总结一篇关于 Dubbo的内容。全文看完,我们对 Dubbo也有一定的了解了。
总结一句话,就是:
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能。
从这句话我们可以知道 Dubbo的基本定位是RPC框架,另外Dubbo也作为一个分布式服务治理框架,除了能够提供通用RPC框架的远程方法调用功能外,还能提供负载均衡、服务注册与发现等功能。
Java实现系统间的通信
RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。
RPC是一种思想,不是指某种具体的技术。 它的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制让使用者不必显式的区分本地调用和远程调用。常见 RPC 技术和框架有:RMI、Spring RMI、WebService、HTTP、Hessian、Dubbo等。RMI、HTTP、Hessian我们都比较熟悉了,他们用起来也比较简单。实际上在大规模服务化之前,应用可能只是通过RMI或者Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
但是如果只是简单地配置URL来处理应用与应用之间的远程调用,当远程调用交互越来越多时,URL配置会变得非常庞大,不利于管理,F5硬件负载均衡器的单点压力也越来越大。这个时候将配置URL这一部分功能抽出来作为一个服务注册中心,会更加清晰合理。服务注册中心的一个功能,就是能够自动理清应用间的依赖关系。通过在接收方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
另外,不同的服务、同一个服务在不同的时间需要的机器支持可能都是不同的,这个服务需要多少机器支撑?什么时候该加机
器?如何监控各个服务的调用量、响应时间,是需要考虑的。对这些有了清晰的了解之后,才可以更有效率的利用硬件设备,节省成本。
以12306系统为例,平日里的访问量和春运时的访问量是完全不同的。硬件设备容量不足,必然导致春运时系统崩溃,而保证了春运时的硬件设备,在平日里访问量剧减,又浪费了成本。这些都需要一个解决方案来动态的、流动性的调度各个服务。
dubbo就是其中一种解决方案,也是dubbo出现的原因。
我们先看一下Dubbo的架构图:
节点角色说明:
调用过程说明:
那么,我们究竟是在什么地方使用到的 Dubbo 呢?大家请看下面的流程图:
简单来说,用户发送的请求转交给 Nginx,然后 Nginx 决定将请求发送那个服务器(此处为 Tomcat),然后 Tomcat 将请求发送给 Dubbo,由它来决定继续调用哪个 service 层去数据库读取数据。
相信大家对于 Dubbo 作用于何处应该有个大体的了解了。(好像所有RPC框架都是这个流程。。)
下面我们一起来用 Dubbo来实现下面的小目标。
(终于要回到我们熟悉的代码部分了,Code Time Begin !)
小目标:对基于远程通信技术(Dubbo技术)的编程有初步的了解。具体需求如下:
1)从消费端(Consumer)把“Hello, I am xxx. Here is Dubbo Consumer.”作为参数调用服务提供端的远程方法;
2)从服务提供端(Provider)读取该参数,并返回消息:“Hello, xxx, nice to meet you! Here is Dubbo Provider.”
我们可以按照以下步骤实现上述需求:
一、定义统一的Api接口
首先我们创建一个公用项目dubbo-api,此项目为Consumer、Provider项目提供接口,保证生产者和消费者所使用的接口统一。我们在 dubbo-api 项目中创建包 com.jvxb.test.dubbo.api,并添加 HelloDubboService 接口。
public interface HelloDubboService {
String helloDubbo(String requestMsg);
}
二、服务端实现接口
import com.jvxb.test.dubbo.api.HelloDubboService;
import org.springframework.stereotype.Service;
@Service("helloDubboService")
public class HelloDubboServiceImpl implements HelloDubboService {
@Override
public String helloDubbo(String requestMsg) {
System.out.println("服务端收到客户端信息:" + requestMsg);
return "Hello, jvxb, nice to meet you! Here is Dubbo Server.";
}
}
三、将服务端实现的接口注册到服务中心
接口实现类添加后,我们需要将其注册到注册中心,只有这样,其他应用才有可能请求到,接下来我们在 src / main / resources 下创建 provider.xml 文件,用于配置dubbo服务端注册,代码如下:
3.1 此时服务端pom.xml中要先引入dubbo 和 zookeeper的依赖。
com.jvxb.test
dubbo-api
0.0.1-SNAPSHOT
com.alibaba
dubbo
2.5.3
org.springframework
spring
com.github.sgroschupf
zkclient
0.1
3.2 在provider.xml中注册提供的服务
3.3 在启动类DubboProviderApplication上添加注解
四、消费端通过注册中心引用接口
4.1 此时消费端pom.xml中要先引入dubbo 和 zookeeper的依赖。(同服务端,此处略)
4.2 在 consumer.xml中获取注册的服务
4.3 在启动类DubboConsumerApplication上添加注解
关于dubbo的配置文件其它参数,可参考:dubbo 配置文件详解
五、测试
5.1 在客户端添加controller,使用从注册中心获取的服务
@RestController
public class ConsumerControllerTest {
@Autowired
private HelloDubboService helloDubboService;
@RequestMapping("helloDubbo")
public String helloDubbo(){
String response = helloDubboService.helloDubbo("Hello, I am jvxb. Here is Dubbo Client.");
System.out.println(response);
return response;
}
}
5.2 启动服务端(可改为8081端口),启动客户端(还是默认的8080端口)
启动过程有两个点值得关注一下:主机绑定、服务注册与发现
5.3 访问客户端的测试接口(helloDubbo),查看结果。
通过以上的实例可以看到,通过简单的配置,dubbo就能够实现远程方法调用,即完成了它作为RPC框架的基本功能。并且通过zookeeper,dubbo可以在服务端启动时,就自动将服务端暴露的服务注册到注册中心(服务注册),在服务消费者在启动后就可以向注册中心订阅想要的服务(服务发现)。所以我们说“Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能”,其中的“是一款RPC框架”、“提供面向接口的远程方法调用”、“服务自动注册和发现”也就不难理解了。
在分析dubbo的集群容错前,先了解什么是容错机制?容错机制指的是某种系统控制在一 定范围内的一种允许或包容犯错情况的发生,举个简单例 子,我们在电脑上运行一个程序,有时候会出现无响应的情况,然后系统会弹出一个提示框让我们选择,是立即结 束还是继续等待,然后根据我们的选择执行对应的操作, 这就是“容错”。
在分布式架构下,网络、硬件、应用都可能发生故障,由 于各个服务之间可能存在依赖关系,如果一条链路中的其 中一个节点出现故障,将会导致雪崩效应。为了减少某一 个节点故障的影响范围,所以我们才需要去构建容错服务(这里要说明一点,容错机制仅仅是处理节点故障的一种机制), 来优雅的处理这种中断的响应结果 。
Dubbo提供了6种容错机制,分别如下
配置方式如下,通过指定cluster方式,配置指定的容错方案
配置的优先级别
客户端会优于服务端,这里还可以细化,可以细化到方法级别
1. 方法级优先,接口级次之,全局配置再次之。
2. 如果级别一样,则消费方优先,提供方次之
其中,服务提供方配置,通过URL经由注册中心传递给消费方
什么应该配置在客户端,什么应该配置在服务端,retires、loadBlance、cluster(客户端)、timeout(服务端)
以 timeout 为例,建议由服务提供方设置超时,因为一个方法需要执行多长 时间,服务提供方更清楚,如果一个消费方同时引用多个 服务,就不需要关心每个服务的超时设置。
我们说“Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能”,其中的“集群容错”也就不难理解了。
我们说“Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能”,其中的“是一款RPC框架”、“提供面向接口的远程方法调用”、“服务自动注册和发现”通过上面的例子我们已经解释了,下面我们看看Dubbo是如何实现负载均衡的。
Dubbo内置了4种负载均衡策略:
如果不指定负载均衡,默认使用随机负载均衡。我们也可以根据自己的需要,显式指定一个负载均衡。 可以在多个地方类来配置负载均衡,比如 Provider 端,Consumer端,服务级别,方法级别等。
服务端服务级别
该服务的所有方法都使用roundrobin负载均衡。
客户端服务级别
该服务的所有方法都使用roundrobin负载均衡。
服务端方法级别
只有该服务的hello方法使用roundrobin负载均衡。
客户端方法级别
只有该服务的hello方法使用roundrobin负载均衡。
和Dubbo其他的配置类似,多个配置是有覆盖关系的:
方法级优先,接口级次之,全局配置再次之。
如果级别一样,则消费方优先,提供方次之。
所以,上面4种配置的优先级是:
客户端方法级别配置。
客户端接口级别配置。
服务端方法级别配置。
服务端接口级别配置。
Dubbo的4种负载均衡的实现,大多数情况下能满足要求。有时候,因为业务的需要,我们也可以实现自己的负载均衡策略。此处不再扩展。
1.复制我们的dubbo-provider项目,改名为dubbo-provider2,并修改其中的server-port为8082和dubbo协议端口号为20881。(模拟两个服务)
2.修改两个provider项目HelloDubboServiceImpl的实现类,标识是20880还是20881的服务器。
public String helloDubbo(String requestMsg) {
System.out.println("服务端(20881)收到客户端信息:" + requestMsg);
return "Hello, jvxb, nice to meet you! Here is Dubbo Server(20881).";
}
3.在客户端的 consumer.xml下,引用服务时使用轮询算法,即reference的loadbalance为轮询roundrobin,来使消费机轮询调用不同的服务机,使程序在单点崩溃的情况下能做合理的负载均衡。
4.测试:连续访问客户端的测试接口(helloDubbo),查看结果。
我们说“Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用、集群容错和负载均衡、以及服务自动注册和发现的功能”,其中的“负载均衡”也就不难理解了。
降级的目的是为了保证核心服务可用。
降级可以有几个层面的分类: 自动降级和人工降级; 按 照功能可以分为:读服务降级和写服务降级;
dubbo的降级方式: Mock 机制
首先我们在客户端添加一个TestMock类,实现HelloDubboService接口,配置文件主要内容如上,可以看到我这里的配置相对第一点客户端的配置添加了几个参数 timeout、failover、mock。这里主要是看mock和timeout配置,因为我们是要去验证mock机制,failover是集群容错的配置,配置好之后,先发布服务端的服务,然后运行客户端的App.java。在控制台我们可以看到打印结果,系统繁忙,这个结果说明,我们客户端远程调用服务超时等报错时,是走到了Mock里,此时我们可以做其它处理。
实现步骤如下:
1、在client端创建一个TestMock类,实现对应HelloDubboService的接口(需要对哪个接口进行 mock,就实现哪个), 名称必须以Mock结尾。
public class TestMock implements HelloDubboService {
@Override
public String helloDubbo(String requestMsg) {
return "系统繁忙!";
}
}
2、在client端的consumer.xml配置文件中,添加如下配置,增加一 个mock属性指向创建的TestMock,并模拟错误(设置 timeout),模拟超时异常(timeout设为1,)
3、运行测试代码即可访问到TestMock这个类。
4、然后我们再验证,将超时间加大,设置为100,再运行,此时就不会报错,
5、就会正常输出服务的返回值,输出结果如下
即dubbo通过Mock机制也是很方便地实现了服务降级。