关于dubbo的服务降级

一、dubbo降级服务    

dubbo开发中,可能由于服务没有启动或者网络不通,调用中会出现RpcException,也就是远程调用失败。如果是服务启动顺序的问题,可能加工check="false"的配置可以得到很好的解决。但是,如果是服务宕掉或者并发数太高导致的RpcException该如何处理?

经过过12306抢票的人应该经常会遇到这个问题:在抢票高峰的时候,明明票还有,但是查询出来的列表却是为空的(如果没票列表也应该会呈现);等高峰过后再查询,列表又恢复正常。个人猜测应该是查询过程中出现了问题,要么超时,要么网络问题导致查询失败采用的服务降级处理。所以,最终呈现给用户的并不是内部系统出错之类的提示,而是一个空的列表。好了,言归正传,在dubbo中想实现服务降级,需要怎么样做可以实现?

查看dubbo的官方文档,可以发现有个mock的配置,mock只在出现非业务异常(比如超时,网络异常等)时执行。mock的配置支持两种,一种为boolean值,默认的为false。如果配置为true,则缺省使用mock类名,即类名+Mock后缀;另外一种则是配置"return null",可以很简单的忽略掉异常。

二、结合dubbo的例子

说明下面将通过一个例子进行说明:

/**接口定义*/
public interface IUser {
 
    public void addUser(User u);
     
    public User getUserById(int id);
     
}
 
/**实现类*/
public class UserImpl implements IUser {
     
    private static List<User> USER_LIST = new ArrayList<User>();
     
    static{
        for(int i=0;i<10;i++){
            User u = new User();
            u.setAddress("address"+i);
            u.setId(i);
            u.setName("name"+i);
             
            USER_LIST.add(u);
        }
    }
     
    public void addUser(User u) {
        USER_LIST.add(u);
        System.out.println("total:"+USER_LIST.size());
    }
 
    public User getUserById(int id) {
        for(int i=0;i<USER_LIST.size();i++){
            if(USER_LIST.get(i).getId() == id){
                return USER_LIST.get(i);
            }
        }
        return null;
    }
}

dubbo-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="hello-world-app" />

	<!-- 使用multicast广播注册中心暴露服务地址 -->
	<dubbo:registry address="zookeeper://127.0.0.1:2181" />

	<!-- 用dubbo协议在20880端口暴露服务 -->
	<dubbo:protocol name="dubbo" port="20880" />

	<!-- 声明需要暴露的服务接口 -->
	<dubbo:service interface="com.zzq.test.iface.IUser" ref="userImpl" timeout="10000" />

	<!-- 和本地bean一样实现服务 -->
	<bean id="userImpl" class="com.zzq.test.ifaceimpl.UserImpl" />

</beans>

调用方的配置:

<?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"  />
 
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
 
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="iUser" interface="com.zzq.test.iface.IUser"  timeout="10000" check="false" mock="return null">
    </dubbo:reference>
 
</beans>

调用的测试代码:

public static void main(String[] args) throws Exception{
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:dubbo-consumer.xml"});
	    context.start();
	    
	    IUser iUser = (IUser)context.getBean("iUser");
	    User u = new User();
	    u.setAddress("aaa");
	    u.setId(311);
	    u.setName("n3");
	    iUser.addUser(u);
	    System.out.println(iUser.getUserById(1));
	}

通过测试,如果服务启动,则程序按照预期的运行正常;如果服务没启动,则此时运行程序,程序并未报错,打印出null。

三、思考

通过以上的例子可以知道,通过mock的配置,可以很好的实现dubbo服务降级。但是,仔细查看上面的例子会发现,IUser本身定义了两个接口,一个是新增用户,一个是根据id查询用户信息。对于根据id查询用户信息,在调用失败的时候返回null很好理解,可能是由于验证失败或者记录删除了,但是对于新增用户,可能就需要抛出具体的业务信息,否则程序无法处理后续的业务,包括页面弹出”添加成功“或者列表刷新的时候无法查看到最新的记录,这样体验将会非常不好。所以,如果要有较好的区分,可以通过以下的方式,可以更好的实现降级:

(1)将接口进行归类,查询类和变更操作类:对于查询的分为一个接口类,变更的归类为其他的接口类,这样对于查询的可以使用mock="return null"进行降级操作;对于变更类的,可以仍旧使用try……catch进行异常捕获处理;

(2)配置mock="true",同时mock实现接口,接口名要注意命名规范:接口名+Mock后缀。此时如果调用失败会调用Mock实现。mock实现需要保证有无参的构造方法。

配置mock="true"的情况,对于上面的例子即在IUser的同个路径下,添加类IUserMock,实现如下:

public class IUserMock implements IUser {

	@Override
	public void addUser(User u) {
		throw new RuntimeException("add user fail!");
	}

	@Override
	public User getUserById(int id) {
		return null;
	}

}
时间: 2024-10-12 20:27:49

关于dubbo的服务降级的相关文章

dubbo之服务降级

向注册中心写入动态配置覆盖规则:(通过由监控中心或治理中心的页面完成) RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"))

大厂必会考题:Dubbo+微服务+ZooKeeper+kafka+Linux等(附答案)

24道常见Elasticsearch 面试题(截取部分) 1.客户端在和集群连接时,如何选择特定的节点执行请求的? 2.详细描述一下 Elasticsearch 索引文档的过程. 3.详细描述一下 Elasticsearch 更新和删除文档的过程. 4.详细描述一下 Elasticsearch 搜索的过程. 5.在 Elasticsearch 中,是怎么根据一个词找到对应的倒排索引的? 6.Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法? 7.对于 GC 方面,在使用

dubbo服务降级(1)

1. 在 dubbo 管理控制台配置服务降级 上图的配置含义是:consumer 调用 com.zhang.HelloService 的方法时,直接返回 null,不发起远程调用. 实际操作是:在 zk 的 /dubbo/com.zhang.HelloService/configurators 节点中添加了 override. override://0.0.0.0/com.zhang.HelloService?category=configurators&dynamic=false&gro

Dubbo服务降级

当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或简单处理,从而释放服务器资源以保证核心业务正常运作或高效运作. 可以通过服务降级功能临时屏蔽某个出错的非关键服务并定义降级后的返回策略. Dubbo支持两种服务降级策略 1).mock=force:return+null 表示服务消费者对该服务方法的调用都直接返回null值,不发起远程调用,用于屏蔽不重要的服务不可用时的影响. eg:在dubbo-admin中 首页->服务治理->消费者->某服务.点击屏蔽

分布式的几件小事(六)dubbo如何做服务治理、服务降级以及重试

1.服务治理 服务治理主要作用是改变运行时服务的行为和选址逻辑,达到限流,权重配置等目的. ①调用链路自动生成 一个大型的分布式系统,会由大量的服务组成,那么这些服务之间的依赖关系和调用链路会很复杂,这就需要dubbo对多个服务之间的调用自动记录下来,生成一张图,显示出来. ②服务反复问压力以及时长统计 需要自动统计各个接口和服务之间的调用次数以及访问延时,而且要分成两个级别.一个级别是接口粒度,就是每个服务的每个接口每天被调用多少次,TP50,TP90,TP99,三个档次的请求延时分别是多少:

服务降级

服务降级经验总结 服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行. 服务降级方式: 服务接口拒绝服务:无用户特定信息,页面能访问,但是添加删除提示服务器繁忙.页面内容也可在Varnish或CDN内获取. 页面拒绝服务:页面提示由于服务繁忙此服务暂停.跳转到varnish或nginx的一个静态页面. 延迟持久化:页面访问照常,但是涉及记录变更,会提示稍晚能看到结果,将数据记录到异步队列或log,服务恢复后执行. 随

Dubbo分布式服务子系统的划分

一.划分子系统的策略 按照系统的业务模块的独立性划分 二.划分时服务子系统的数量的控制 过多:可能划分过细,破坏业务子系统的独立性,部署维护工作量大,独立进程占用内存多 过少:没能很好的解耦,开发维护不好分工,升级维护影响面大 三.服务子系统划分要注意的地方 3.1 不要出现A服务中的SQL需要链接查询到B服务中的表等情况,这样在A服务与B服务进行垂直拆库时就会出错       eg:服务虽然拆分了,但是还是用的同一个数据库 3.2  服务子系统间避免出现环状的依赖调用        eg:A服

谈谈我对服务熔断、服务降级的理解

伴随着微服务架构被宣传得如火如荼,一些概念也被推到了我们面前(管你接受不接受),其实大多数概念以前就有,但很少被提的这么频繁(现在好像不提及都不好意思交流了).想起有人总结的一句话,微服务架构的特点就是:“一解释就懂,一问就不知,一讨论就吵架”. 其实对老外的总结能力一直特别崇拜,Kevin Kelly.Martin Fowler.Werner Vogels……,都是著名的“演讲家”.正好这段时间看了些微服务.容器的相关资料,也在我们新一代产品中进行了部分实践,回过头来,再来谈谈对一些概念的理解

SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)

1.概念:Hystrix 熔断机制 2.具体内容 所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢? 当现在服务的提供方出现了问题之后整个的程序将出现错误的信息显示,而这个时候如果不想出现这样的错误信息,而希望替换为一个错误时的内容. 一个服务挂了后续的服务跟着不能用了,这就是雪崩效应 对于熔断技术的实现需要考虑以下几种情况: · 出现错误之后可以 fallback 错误的处理信息: · 如果要结合 Feign