Dubbo
一:什么是Dubbo
Dubbo是一个RPC框架;
执行流程为:
采用的协议:
1.Dubbo
1.1 Dubbo官方推荐的协议.
1.2 本质:使用NIO和线程池进行处理.
1.3 缺点:大文件传输时可能出现文件传输失败问题.
2.RMI
2.1 JDK提供的协议,远程方法调用协议.
2.2 缺点:偶尔连接失败.
2.3 优点:JDK原生,不需要进行额外配置(导入jar)
3.Hession
3.1 优点:基于http协议,http请求支持.
3.2 缺点:需要额外导入jar,并在短连接时性能低
特性:
面向接口代理的高性能RPC调用
提供高性能的给予代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节
服务自动注册与发现
支持多服务中心服务,服务上下线实时感知;
运行期流量调度
内置条件,脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能
智能负载均衡
内置各种负载均衡策略,智能感知下游节点的健康状态,显著减少调用延迟,提高系统吞吐量
高度可扩展能力
遵循微内核+插件设计原则,所有核心能力入Protocol、Transport、Serialization呗设计为拓展点,平等对待内置实现和第三方实现;
可视化的服务治理与运维
提供丰富服务治理,运维工具;随时查询服务元数据,服务健康状态及调用统计,实时下发路由策略,调整配置参数
Dubbo的架构设计:
服务提供者(Provider):
暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者(Consume):
调用远程服务的服务消费方,服务消费者启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
注册中心(Registry):
注册中心返回服务提供者地址表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor):
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
调用关系说明
·服务容器负责启动,加载,运行服务提供者。
·服务提供者在启动时,向注册中心注册自己提供的服务。
·服务消费者在启动时,向注册中心订阅自己所需的服务。
·注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
·服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者调用,如果调用失败,再选另一台。
·服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
运行原理:
0 启动容器,相当于在启动Dubbo的Provider
1 启动后会去注册中心进行注册.注册所有可以提供的服务列表
2 在Consumer启动后会去Registry中获取服务列表和Provider的地址.进行订阅.
3 当Provider有修改后,注册中心会把消息推送给Consummer
3.1 使用了观察者设计模式(又叫发布/订阅设计模式)
4 根据获取到的Provider地址,真实调用Provider中功能.
4.1 在Consumer方使用了代理设计模式.创建一个Provider方类的一个代理对象.通过代理对象获取Provider中真实功能,起到保护Provider真实功能的作用.
5 Consumer和Provider每隔1分钟向Monitor发送统计信息,统计信息包含,访问次数,频率等.
二:搭建Dubbo环境:
首先要配置zookeeper(包括监控中心和控制台)
Code(HelloWord-----javase----maven)
说明:
1.这里的三个模块都使用了jar包的形式(具体看需求)
2.包名取得有问题(pro和con中的service都是service,所以最好是有所区分)
(1)生产者
接口实现
package com.xpl.service; import com.xpl.model.User; import org.springframework.stereotype.Service; //spring的service注解 @Service public class GetUserImp implements GetUser { public String getUserById(int id) { return "徐沛蕾"; } }
main主方法
package com.xpl.com.xpl.main; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml"); cxt.start(); System.in.read(); } }
applicationContext.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" xmlns:dubbop="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"> <!--1.指定当前服务/应用的名字(最好是写项目名称)--> <dubbo:application name="dubboprovider"/> <!--2.指定注册中心的位置,zookeeper默认端口号为2181--> <!--方式一--> <dubbop:registry address="zookeeper://127.0.0.1:2181"/> <!--方式二--> <!--<dubbo:registry protocol="zookeeper" address="127.0.0:2181"/>--> <!--3.指定通信规则(通信协议和通信端口)--> <!--协议有多种,端口号为自己指定的不冲突即可--> <dubbo:protocol name="dubbo" port="20880"/> <!--4.暴露接口--> <!--将要暴露的接口的实现类注入到spring容器中--> <dubbo:service interface="com.xpl.service.GetUser" ref="getUserImp"/> <bean class="com.xpl.service.GetUserImp" id="getUserImp"/>
<!--配置监控中心-->
<!--方式一:-->
<!--<dubbo:monitor protocol="registry"/>-->
<!--方式二:-->
<dubbo:monitor address="127.0.0.1:7070"/>
</beans>
(2)消费者
接口实现
package com.xpl.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; //spring的service注解 @Service public class OrderServiceImp implements OrderService { @Autowired GetUser getUser; public String getNameByID(int id) { String name = getUser.getUserById(id); return name; } }
main主方法
package com.xpl.main; import com.xpl.service.OrderService; import com.xpl.service.OrderServiceImp; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml"); // OrderService bean = (OrderService) cxt.getBean("orderServiceImp"); OrderService bean = cxt.getBean(OrderService.class); String nameByID = bean.getNameByID(1); System.out.println(nameByID); System.in.read(); } }
applicationContext.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" xmlns:context="http://www.springframework.org/schema/context" xmlns:bean="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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--将加了注解的组件扫描进来--> <context:component-scan base-package="com.xpl.service"/> <!--1.指定当前服务/应用的名字(最好是写项目名称)--> <dubbo:application name="dubboconsumer"/> <!--订阅的服务地址--> <!--方式一--> <!--<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>--> <!--方式二:--> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <!--消费的服务就是provider中暴露的接口--> <dubbo:reference interface="com.xpl.service.GetUser" id="getUserImp"/>
<!--配置监控中心-->
<!--方式一:-->
<!--<dubbo:monitor protocol="registry"/>-->
<!--方式二:-->
<dubbo:monitor address="127.0.0.1:7070"/>
</beans>
(3)common
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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>DubboTest</artifactId> <groupId>com.xpl</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubboService</artifactId> <dependencies> <!--<artifactId>dubbo</artifactId>--> <!--<artifactId>zookeeper</artifactId>--> <!--<artifactId>zkclient</artifactId>--> <!--<artifactId>curator-recipes</artifactId>--> <!--这三个是生产者和消费者都需要引入的依赖生产和消费有需要引入service所以在service中引入--> <!--依赖一如方式一--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.11</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.1</version> </dependency> <!--依赖一如方式二--> <!--2.6.2版本以后引入这两个就可以了--> <!--<dependency>--> <!--<groupId>com.alibaba</groupId>--> <!--<artifactId>dubbo</artifactId>--> <!--<version>2.6.2</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.curator</groupId>--> <!--<artifactId>curator-framework</artifactId>--> <!--<version>2.12.0</version>--> <!--</dependency>--> </dependencies> </project>
service
package com.xpl.service; import com.xpl.model.User; /** * 提供一个获取User的接口 */ public interface GetUser { public String getUserById(int id); }
package com.xpl.service; import com.xpl.model.User; /** * 提供一个获取通过id获取name的接口 */ public interface OrderService { public String getNameByID(int id); }
model
package com.xpl.model; import java.io.Serializable; //implements Serializable 序列化 public class User implements Serializable { private int id; private String name; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", address='" + address + '\'' + '}'; } }
总结梳理:
1.首先是在一个Maven项目中创建多模块(生产者、消费者、公共模块)
2.公共模块提供生产者和消费者所需要的接口和公共使用的实体类,同时在pom模块中引入生产者和消费者所共同依赖的jar包
3.生产者将其注册到zookeeper中并暴露服务
4.生产者订阅zookeeper中的服务
5.注册服务主要分为:
注册的服务名称
所在注册中心的位置(注册中心的地址和端口号)
通信方式和端口
将实现类注入到spring容器中
暴露接口(上边注入到spring容器中的Bean对应的接口)
6.订阅服务主要分为
指定当前服务的名称
订阅服务在注册中心的地址(注册中心的地址和端口号)
消费的服务(就是自己需要代用的接口,也是提供者暴露的那个接口)
三、注解版