Dubbo高性能Java RPC框架
一、初识Zookeeper
二、Dubbo(Dubbo官网)
1.简介
Apache Dubbo 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
2.Dubbo的功能
-
面向接口代理的高性能RPC调用
-
服务自动注册与发现
-
运行期流量调度
-
智能负载均衡
-
高度可扩展能力
-
可视化的服务治理与运维
3.dubbo管理控制台安装
2.把dubbo-admin项目打成jar包
3.运行dubbo-admin-0.0.1-SNAPSHOT.jar
4.项目运行在Tomcat上服务器上端口号7001,访问http://localhost:7001/
用户: root, 密码: root 或者 用户: guest, 密码: guest ↩︎
4.服务超时
服务超时:消费端向服务端发起请求,服务端没有及时响应从而报异常!
解决办法:建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。
<!--1.在服务端配置全局变量值timeout="5000,所有的provider服务在5s内不响应不报异常-->
<dubbo:provider timeout="5000" check="true" async="false"
retries="1" protocol="dubbo" threadpool="fixed" threads="500" accepts="500"/>
配置属性详解
1.timeout="5000":服务超时时间(单位为毫秒),客户端在调用该dubbo服务时会启动超时检测,如果达到5秒就会报超时异常,超时异常后客户端会尝试1次调用,不管失败与否都返回。
2.check="true":系统在启动时就会去检查对应的dubbo服务,不存在就报错导致启动失败,所以如果设置为true,就必须确保该服务提供者一定要在该应用启动之前启动,否则就会启动失败。
3.async="false":表明该服务是同步调用而不是异步调用。
4.retries="1" :重试一次,也就是最多尝试2次,如果失败就抛出异常!
5.protocol="dubbo":协议名称
6.threadpool="fixed":线程池类型,可选:fixed/cached
7.threads="500":服务接口最大能同时使用线程池中的500个线程
8.accepts="500":服务提供者最大可接受连500接数
5.重试机制
dubbo在调用服务不成功时,默认会重试2次,dubbo的路由机制,会把超时的请求路由到其他机器上,而不是本机尝试,所以 dubbo的重试机器也能一定程度的保证服务的质量,但是如果不合理的配置重试次数,当失败时会进行重试多次,这样在某个时间点出现性能问题,调用方再连续重复调用,系统请求变为正常值的retries倍,系统压力会大增,容易引起服务雪崩,需要根据业务情况规划好如何进行异常处理,何时进行重试。
<!--重试机制一般配合timeout使用,通常我们不需要重试,因为重试增加系统压力-->
<dubbo:provider timeout="60000" retries="0"/>
6.dubbo服务降级(服务降级介绍)
服务降级的方法:
1.在dubbo-admin中手动配置服务降级
2.dubbo提供了mock配置,可以很好的实现dubbo服务降级
向注册中心写入动态配置覆盖规则:
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
其中:
- mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
- 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
7.dubbo服务容错(和Spring Cloud断路器原理一样)
在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。
服务容错案例:Spring应用快速集成Dubbo + Hystrix
集群容错机制:
提供了六种集群容错机制,包括Failover(失败自动切换,尝试其他服务器)、Failfast(失败立即抛出异常)、Failsafe(失败忽略异常)、Failback(失败自动恢复,记录日志并定时重试)、Forking(并行调用多个服务,一个成功立即返回)、Broadcast(广播调用所有提供者,任意一个报错则报错);
Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
重试次数配置如下:
<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
集群模式配置
按照以下示例在服务提供方和消费方配置集群模式
<dubbo:service cluster="failsafe" />
或
<dubbo:reference cluster="failsafe" />
8.dubbo实现各服务之间的调用案例
项目结构
项目依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
1.将远程服务抽取为dubbo-api
public interface DemoService {
public String sayHello(String name);
}
2.服务提供者
DemoServiceImpl.java
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello" + name;
}
}
ProviderApplication.java
public class ProviderApplication {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml");
context.start();
System.out.println("服务已经启动!");
System.in.read();//在控制台按任意键退出
}
}
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-provider" />
<!--连接监控中心-->
<!--<dubbo:monitor protocol="registry" />-->
<!--使用zookeeper服务中心注册服务,要先启动zookeeper
register:false代表只订阅,不注册
subscribe:false代表只注册,不订阅
check:false代表注册中心不存在时,不报错,意思是不校验错误
address:配置zookeeper的ip和端口号,集群用逗号隔开
-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" subscribe="false" check="false" />
<!--用dubbo协议在20880端口暴露服务-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--要注册的服务接口-->
<dubbo:service interface="com.wang.api.DemoService" ref="demoService" />
<!--实现接口的实现类-->
<bean id="demoService" class="com.wang.provider.DemoServiceImpl"/>
</beans>
3.服务消费者
comsumer.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-consumer"/>
<!--向注册中心订阅服务,由zookeeper定时推送-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--引用已经注册的服务-->
<dubbo:reference id="demoService" interface="com.wang.api.DemoService"/>
</beans>
ConsumerApplication.java
public class ConsumerApplication {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml");
context.start();
System.out.println("消费端接收服务。。。。。。。。");
DemoService demoService = (DemoService) context.getBean("demoService");
String hello = demoService.sayHello("--World");
System.in.read();//在控制台按任意键退出
}
}