什么是dubbo?
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。
Dubbo是阿里巴巴SOA服务化治理方案的核心框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
通俗来讲dubbo是一种服务与服务之间的通信方式,是为了解决分布式架构服务器所产生的一些问题的框架。
什么是分布式系统架构?
分布式架构的出现是为了解决在业务量与流量日益增长的情况下集中式系统的所产生的的种种弊端。
集中式系统:
由一台或多台服务器组成的中心节点,数据集中存储在这个中心节点中,并且整个系统的所有业务单元都集中部署在这个中心节点上,整个系统的所有功能均由其集中处理。其部署简单,不用考虑多个节点间的分布式协作问题。
集中式系统的问题:
- 随着业务量日益增长,项目中的代码越来越冗余繁琐,业务人员的变更导致代码也越来越难维护,最终就是项目十分的庞大并且繁杂,项目编译启动时间十分漫长,发布、测试麻烦。
- 随着流量和并发量的增长,单台服务器已无法满足峰值时的流量,我们就需要增加服务器和搭建集群以对抗峰值并发,但是日常并发量又十分浪费服务器资源
- 代码的重用性太低,例如查询用户的接口不仅仅当前项目需要使用,同样是我们维护的其他项目也想使用,但是如果是集中式系统,同样的代码我们就要重新写一份。
此时,分布式系统就应运而生,他是按照不同的模块,将一个项目拆分成多个子模块,每个模块之间可各自独立运行,每个模块负责一个功能点服务。各个模块之间的调用使用某种通信协议来完成,这就是dubbo框架的作用。分布式系统很好的解决了上面的问题,将项目变得十分的灵活。
但是分布式系统也会带来一些问题:
1、部署单个服务会比较快,但是如果一次部署需要多个服务,部署会变得复杂。
2、架构设计变得复杂、技术成本变高、学习难度增加。
3、服务越来越多,管理变得复杂。
4、服务与服务之间的通信变得复杂。
3、保证数据的一致性难度增加。
其中服务与服务之间的通信,我们是否可以使用常见的远程通信方式呢,比如:
1、Http
连接个数:多连接
连接方式:短连接
传输方式:同步
序列化格式:json
传输协议:HTTP
2、RMI
连接个数:多连接
连接方式:断连接
传输方式:同步
传输格式:JAVA标准二进制序列化。
传输协议:Socket
3、webservice
连接个数:多链接 连接方式:短连接
序列化格式:SOA文本序列化
传输协议:http传输方式:同步
4、Hessian
连接个数:多连接
连接方式:短连接
传输方式:同步
序列化格式:Hessian二进制格式
传输协议:HTTP
其实这些方式也可以请求调用到我们的服务模块,但是这些通信方式没有对分布式衍生的其他问题做处理,只是解决了通信的问题而已:
1、服务配置地址难维护
2、无法动态扩容
3、没有监控(调用量、响应时间、权重配置)
4、没有熔断机制
5、调用关系难维护
而dubbo采用的通信方式:
dubbo
连接个数:单链接(可设置多个连接)
连接方式:长连接
序列化格式:Hessian二进制格式(Hessian2)
传输协议:TCP
传输方式:NIO
就对上述的问题进行了解决。
那么,Dubbo能做什么?
1、透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2、软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3、服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
(1) 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。
(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。
其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
dubbo的使用(暂不使用注册中心)
新建一个maven项目,创建两个子模块,假定我们想要创建用户服务模块,所以我们需要一个user-api模块,提供用户服务所需的接口
Model
@Data
@ToString
public class User implements Serializable{
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
}
Service
public interface UserService {
User getUser(String name);
}
再创建一个服务的生产方,user-provider模块
引入dubbo的pom文件
<dependencies>
<dependency>
<artifactId>user-api</artifactId>
<groupId>com.lerning.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
</dependencies>
ServiceImpl实现UserSevice
public class UserServiceImpl implements UserService {
public User getUser(String name) {
System.out.println("调用服务成功");
User user =new User(222,name);
System.out.println(user.toString());
return user;
}
}
向dubbo注册服务,创建user-provider.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="dubbo-user" />
<dubbo:protocol name="dubbo"/>
<dubbo:registry address="N/A"/>
<dubbo:service interface="com.lerning.dubbo.user.api.service.UserService" class="com.lerning.dubbo.user.service.UserServiceImpl"/>
</beans>
创建启动类启动服务
public class UserProviderAapplication {
public static void main(String[] args) {
Main.main(args);
}
}
创建新的消费方项目,为user-consumer
引入dubbo与刚刚生产的user-api的pom文件(略。)
发现刚刚我们注册的服务,创建user-consumer.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="user-consumer"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:registry address="N/A"/>
<dubbo:reference interface="com.lerning.dubbo.user.api.service.UserService" id="userService" url="dubbo://192.168.30.1:20880/com.lerning.dubbo.user.api.service.UserService"/>
</beans>
创建启动类,测试dubbo服务
public class TestDubo {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("user-consumer.xml");
UserService userService=(UserService) context.getBean("userService");
User user=userService.getUser("duanpan");
System.out.println(user.toString());
}
}
启动,发现我们成功的取到了UserService,生成了User对象,并且服务生产方控制台也成功打印出了“调用服务成功”。