4、Dubbo消费端服务mock&降级策略原理

当我们聊服务消费端降级的时候时候,应该考虑哪些问题?

  • dubbo如何设置服务消费的降级策略?用到了那个类(保存到zookeeper的configurator节点下)?
  • dubbo的服务降级策略有哪些?
  • 如何使用dubbo的服务降级策略?

降级策略注册

当服务因为超时等某些原因不可用的时候,我们需要无服务设置降级策略;手动编写伪代码将服务降级信息注册到zookeeper;也可以通过配置mock参数的形式指定某个消费服务的mock策略,返回指定字符串,或者自定义mock处理类;

1、手动伪代码将服务降级注册到zk

/**
 * 注册服务降级策略到注册中心
 * @Param type 降级策略类型
 */
public static void mockResult(String type){
    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"));
}

2、配置mock参数指定返回字符串

<dubbo:reference id="xxService" check="false" interface="com.xx.XxService" timeout="3000" mock="return null" />

<dubbo:reference id="xxService2" check="false" interface="com.xx.XxService2" timeout="3000" mock="return 1234" />

timeout:超过该时间返回null 或者1234。
配置后启动即可,我们在服务提供者例 如 UserServiceImpl 中的 getUser 方法打个断点来模拟请求超时。

然后浏览器访问,断点不过,一致等待,当时间超过3秒,直接返回了空;ok! 这样我们就已经实现了一个简单的服务降级了 。

3、自定义服务降级方法实现类

<dubbo:reference id="xxService" check="false" interface="com.xx.XxService" timeout="3000" mock="true"/>

配置dubbo服务消费引用标签的mock参数值为true,同时定义服务名+Mock 的自定义类;这样在服务接口超时时,就会返回自定义的相应信息;

public class UserServiceMock implements UserService{
 
	public List<Article>getUserArticles(int uid){
		return null;
		
	}
	public List<User>getUser(String name){
		//throw new RuntimeException("服务降级-----");
		User user = new User();
		user.setUserName("服务降级啦");
		user.setUserAge("500");
		List<User> list = new ArrayList<User>();
		list.add(user);
		return list;
		
	}
}

4、通过admin管理平台手动配置服务降级策略

不论使用何种方式,最终降级策略会被注册到zk上的configurators节点下(假设使用zk注册中心),

  • mock值默认false:直接发起远程调用,无降级
  • mock值设置为force: 不发起远程调用,直接返回降级策略
  • mock值设置为fail: 发起远程调用,失败时return降级策略

服务消费端使用降级策略

服务消费端在MockClusterInvoker类的invoke()方法里使用降级策略并在DubboInvoker的invoke()方法里发起远程调用,所以服务降级是在消费端还没有发起远程调用时完成。

1、MockClusterInvoker代码

    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        Result result;
        // 获得 "mock" 配置项,有多种配置方式
        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
        //【第一种】无 mock
        if (value.length() == 0 || value.equalsIgnoreCase("false")) {
            // no mock
            // 调用原 Invoker ,发起 RPC 调用
            result = this.invoker.invoke(invocation);
        //【第二种】强制服务降级 https://dubbo.gitbooks.io/dubbo-user-book/demos/service-downgrade.html
        } else if (value.startsWith("force")) {
            if (logger.isWarnEnabled()) {
                logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
            }
            // force:direct mock
            // 直接调用 Mock Invoker ,执行本地 Mock 逻辑
            result = doMockInvoke(invocation, null);
        // 【第三种】失败服务降级 https://dubbo.gitbooks.io/dubbo-user-book/demos/service-downgrade.html
        } else {
            // fail-mock
            try {
                // 调用原 Invoker ,发起 RPC 调用
                result = this.invoker.invoke(invocation);
            } catch (RpcException e) {
                // 业务性异常,直接抛出
                if (e.isBiz()) {
                    throw e;
                } else {
                    if (logger.isWarnEnabled()) {
                        logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
                    }
                    // 失败后,调用 Mock Invoker ,执行本地 Mock 逻辑
                    result = doMockInvoke(invocation, e);
                }
            }
        }
        return result;
    }

directory.getUrl获取服务提供者的动态配置信息,含降级mock参数信息;之后判断三种mock值,决定是否执行降级策略;这里关注如果mock值为fail,如果远程调用失败,则返回降级策略,乳沟成功则代码会调用FailoverClusterInvokerd的doInvoke()方法发起远程调用;

发布了42 篇原创文章 · 获赞 6 · 访问量 2626

猜你喜欢

转载自blog.csdn.net/a1290123825/article/details/104888863