Dubbo高性能Java RPC框架

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_36279318/article/details/83341038

一、初识Zookeeper

二、Dubbo(Dubbo官网

1.简介

Apache Dubbo  是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

2.Dubbo的功能

  • 面向接口代理的高性能RPC调用

  • 服务自动注册与发现

  • 运行期流量调度

  • 智能负载均衡

  • 高度可扩展能力

  • 可视化的服务治理与运维

3.dubbo管理控制台安装

1.下载incubator-dubbo-ops

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服务降级(服务降级介绍)

参考:服务降级,服务熔断,服务限流等慨念

服务降级

概念:服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

  • 服务接口拒绝服务:页面能访问,但是添加删除提示服务器繁忙。页面内容也可在Varnish或CDN内获取。
  • 页面拒绝服务:页面提示由于服务繁忙此服务暂停。跳转到varnish或nginx的一个静态页面。
  • 延迟持久化:页面访问照常,但是涉及记录变更,会提示稍晚能看到结果,将数据记录到异步队列或log,服务恢复后执行。
  • 随机拒绝服务:服务接口随机拒绝服务,让用户重试,目前较少有人采用。因为用户体验不佳。

服务熔断

概念:如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。

熔断设计 

三个模块:熔断请求判断算法、熔断恢复机制、熔断报警

  • 熔断请求判断机制算法:使用无锁循环队列计数,每个熔断器默认维护10个bucket,每1秒一个bucket,每个blucket记录请求的成功、失败、超时、拒绝的状态,默认错误超过50%且10秒内超过20个请求进行中断拦截。
  • 熔断恢复:对于被熔断的请求,每隔5s允许部分请求通过,若请求都是健康的(RT<250ms)则对请求健康恢复。
  • 熔断报警:对于熔断的请求打日志,异常请求超过某些设定则报警

服务限流

概念:限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。

服务降级的方法:

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"));

其中:

  1. mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  2. 还可以改为 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();//在控制台按任意键退出
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_36279318/article/details/83341038