Dubbo简介
Dubbo,相信做后端的同学应该都用过,或者有所耳闻。没错,我就是那个有所耳闻中的一员。
公司在好几年前实现了一套自己的RPC框架,所以也就没有机会使用市面上琳琅满目的RPC框架产品。
之所以想好好看看Dubbo,有以下几个原因
公司内部的框架一直在做迭代更新,配置越来越简洁,性能越来越好。但是作为使用者,它就像一个黑盒子,我们无法感知其内部的改动以及实现的原理
现在使用的框架,因为使用了thrift,让平时的开发显得格外的蹩脚,常常在各种model的转换中迷失自我,耗尽了耐心
阿里团队从去年开始重新维护Dubbo,并在春节之际进入Apache孵化器,在开源的道路上又猛跨一大步,其背后定然有我们值得学习借鉴的地方,更何况有阿里技术的背书
开源项目是很好的学习素材,希望借助学习Dubbo代码,了解序列化、分布式、网络通讯等方面的知识
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。
GitHub:https://github.com/apache/incubator-dubbo
官网:http://dubbo.apache.org/
中文用户手册:http://dubbo.io/books/dubbo-user-book/
HelloWorld之前的两个小问题
1.没有Dubbo之前,我们是什么样的工作方式
Dubbo代表的是一类RPC框架,类似的产品还有鼎鼎大名的gRPC。
没有Dubbo之前是什么样的,可以回想下我们学生时代做的项目。
一台电脑既是服务器又是客户端,估计当时也没有想过我调用的这个接口是哪台电脑上,我是不是可以多部署几台电脑,怎么样充分利用这几台电脑好让调用的效率更高。
因为即使想了,也搞不了,因为没钱!
即使我们在自己的PC上把项目做好了,需要部署到服务器上,那么我们只要记住那台服务器的IP,使用Socket通讯,就很简单的实现了服务的调用和通讯了。
2.Dubbo有什么用
接着学生时代的项目说,那时候我们做个图书管理系统,学籍管理系统,其访问量和并发量一般不会太高,准确说,是非常低。
但是如果还是一个服务端,大量的用户请求,达到高并发的场景,那么问题就来了,一台机子显然承受不住,这时候需要考虑分布式。
Dubbo的产生于微服务联系紧密,我们一方面想着借助微服务的思想,实现各个服务或者模块之间的解耦。那么我们另一方面就不能忽视服务之间的通讯,这时候Dubbo一类的RPC框架就应运而生。
我们需要考虑扩展性,比如为了防止访问过载,服务所在机器需要进行水平扩展,同时也要考虑不断增加的服务调用方。
我们需要考虑负载均衡,怎么样才能将服务集群的威力发挥到最大。
我们需要考虑如何自动的注册服务以及更新服务,如果做好异常情况下,比如注册中心宕机时,服务方和调用方之间的服务调用。
如此种种,都是催生Dubbo的重要因素。
HelloWorld的准备工作
打开命令行,执行git clone https://github.com/apache/incubator-dubbo.git命令,将远程项目拉到本地
导入项目进IDE,使用mvn clean compile在项目目录下编译
- 下载安装zookeeper,在命令行执行brew install zookeeper
相应的启动zk和关闭zk服务的命令分别是zkServer start和zkServer stop
运行HelloWorld
导入Dubbo项目并且完成编译后,可以看到Dubbo项目的目录结构如下
今天要介绍的是dubbo-demo,该子模块包括
dubbo-demo-api(提取出公共接口)
dubbo-demo-consumer(服务调用方)
dubbo-demo-provider(服务提供方)
dubbo-demo-api
该模块最核心的类就是DemoService接口,该接口只有一个方法sayHello
package com.alibaba.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}
这个接口是联系调用方和提供方的纽带。
dubbo-demo-consumer
该模块核心的类为Consumer,主要是一个main函数
public class Consumer {
public static void main(String[] args) {
//Prevent to get IPV6 address,this way only work in debug mode
//But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
while (true) {
try {
Thread.sleep(1000);
String hello = demoService.sayHello("world"); // call remote method
System.out.println(hello); // get result
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}
其主要功能是加载配置文件,用于寻找服务提供方所在的位置,拿到DemoService接口的实现类DemoServiceImpl,并调用其方法实现sayHello
dubbo-demo-provider
该模块包含了DemoService的实现类DemoServiceImpl,同时包含一个服务启动类Provider
public class Provider {
public static void main(String[] args) throws Exception {
//Prevent to get IPV6 address,this way only work in debug mode
//But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit
}
}
启动注册中心
因为调用方和服务提供方需要靠注册中心来联系,提供方将自己的服务登记到注册中心,调用方需要拉取可用的服务提供方的位置信息,比较常见的关系描述如下图所示
调用关系说明
服务容器负责启动,加载,运行服务提供者。
服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
鉴于Dubbo源码中,配置文件中的默认配置是multicast,但是我在运行的时候总是出现can't assign address的情况,所以改用zookeeper。
相应修改如下,在dubbo-demo-provider项目中,将dubbo-demo-provider.xml修改为
将dubbo-demo-consumer项目中的dubbo-demo-consumer.xml修改为
同时在命令行输入zkServer start启动zk
分别启动Proiver和Consumer
运行Provider类,将自己的服务接口对外开放
运行Consumer类,寻找服务提供方,并调用其接口实现
至此,对于Dubbo有了一个初步的认识并通过dubbo-demo项目了解Dubbo的运作模式。
网上找了一份PDF版的源码阅读心得,如果有需要,下方留下你的邮箱
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。