一、dubbo介绍
随着互联网的不断发展,网站的规模也越来越大,常规的垂直应用架构已经不能再满足开发的需求,分布式服务架构和流式计算架构已成为趋势。
单一应用架构:当网站流量很小时,只需要一个应用,将所有的功能都部署在一起,以减少部署节点个成本。
垂直应用架构:当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
分布式服务架构:当垂直应用越来越多,应用之间交互不可避免,将核心业务抽离出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
流式计算架构:当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需要增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
那什么是dubbo呢?dubbo是一个分布式服务架构,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。核心部分包含远程通信、集群容错、自动发现。
二、dubbo工作原理
(1) 连通性:
注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小
监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销
服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销
注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外
注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
注册中心和监控中心都是可选的,服务消费者可以直连服务提供者
(2) 健壮性:
监控中心宕掉不影响使用,只是丢失部分采样数据
数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
注册中心对等集群,任意一台宕掉后,将自动切换到另一台
注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
服务提供者无状态,任意一台宕掉后,不影响使用
服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
(3) 伸缩性:
注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心
服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者
三、dubbo应用
1、创建maven工程,创建实体类User和接口UserService。
1 //User实体类 2 public class User implements Serializable { 3 private int id; 4 private String name; 5 private int age; 6 7 public int getId() { 8 return id; 9 } 10 11 public void setId(int id) { 12 this.id = id; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 public int getAge() { 24 return age; 25 } 26 27 public void setAge(int age) { 28 this.age = age; 29 } 30 } 31 32 //接口UserService 33 public interface UserService { 34 //根据id查询User 35 User getUser(int id); 36 }
2、在已有工程的基础上,创建module,命名为dubboProvider,在pom.xml文件中导入坐标
1 <dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId>spring-context</artifactId> 4 <version>4.0.5.RELEASE</version> 5 </dependency> 6 7 <!--导入DubboDemo公共接口依赖--> 8 <dependency> 9 <groupId>com.demo.dubbo</groupId> 10 <artifactId>DubboDemo</artifactId> 11 <version>1.0-SNAPSHOT</version> 12 </dependency> 13 <!--导入dubbo依赖--> 14 <dependency> 15 <groupId>com.alibaba</groupId> 16 <artifactId>dubbo</artifactId> 17 <version>2.5.3</version> 18 </dependency> 19 <!--导入zookeeper依赖--> 20 <dependency> 21 <groupId>com.101tec</groupId> 22 <artifactId>zkclient</artifactId> 23 <version>0.10</version> 24 </dependency>
编写接口实现类UserServiceImpl.java。
1 public class UserServiceImpl implements UserService { 2 @Override 3 public User getUser(int id) { 4 User user = new User(); 5 switch (id){ 6 case 1: 7 user.setId(id); 8 user.setName("张"); 9 user.setAge(20); 10 break; 11 case 2: 12 user.setId(id); 13 user.setName("白"); 14 user.setAge(21); 15 break; 16 } 17 return user; 18 } 19 }
接着配置dubbo-user-consumer.xml。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!--服务提供者的信息如下--> <!-- provider's application name, used for tracing dependency relationship --> <!--服务提供者的应用名称--> <dubbo:application name="user-provider"/> <!-- use multicast registry center to export service --> <!--注册中心地址--> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <!-- use dubbo protocol to export service on port 20880 --> <!--协议及端口号--> <dubbo:protocol name="dubbo" port="20880"/> <!-- declare the service interface to be exported --> <!--指明提供服务的接口--> <dubbo:service interface="com.dubbo.service.UserService" ref="userService"/> <!-- service implementation, as same as regular local bean --> <!--服务实现类--> <bean id="userService" class="com.dubbo.service.impl.UserServiceImpl"/> </beans>
在test下创建ProviderMain.java测试类。
1 public class ProviderMain { 2 public static void main(String[] args) throws Exception{ 3 4 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-user-provider.xml"); 5 //加载 6 context.start(); 7 System.out.println("Provider started."); 8 //让程序阻塞 9 System.in.read(); // press any key to exit 10 } 11 }
然后启动zkServer.cmd,运行测试类,可以在控制台看到“Provider started.”,利用zookeeper工具可以看到生成的相应节点。
3、接下来创建消费者module,命名为:dubboConsumer,pom.xml需要导入的坐标和创建dubboProvider服务提供者module时导入的坐标一样,然后是配置dubbo-user-consumer.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!--消费者配置--> <!--消费者应用名--> <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion), don't set it same as provider --> <dubbo:application name="user-consumer"/> <!-- use multicast registry center to discover service --> <!--注册中心地址--> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <!-- generate proxy for the remote service, then demoService can be used in the same way as the local regular interface --> <!--远程服务代理--> <dubbo:reference id="userService" interface="com.dubbo.service.UserService"/> </beans>
编写ConsumerMain测试类
1 public class ConsumerMain { 2 public static void main(String[] args) throws Exception { 3 //消费者调用服务提供者 4 //获取返回数据 5 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-user-consumer.xml"); 6 //加载 7 context.start(); 8 //获取远程服务代理 9 // Obtaining a remote service proxy 10 UserService userService = (UserService)context.getBean("userService"); 11 // Executing remote methods 12 User user = userService.getUser(1); 13 // Display the call result 14 System.out.println(user.getName()); 15 } 16 }
在服务提供者启动的前提下,运行消费者测试类,即可在控制台获取到相应的信息。