zoukankan      html  css  js  c++  java
  • 使用Dubbo、JSF等RPC框架时,对于异常的处理

    无论是Dubbo还是JSF等RPC框架,一般都会把接口分为2部分:

    1,服务端(provider)

    2,客户端(consumer)

    由于,客户端与服务端可能不在同一个应用中,所以客户端一般在调用服务端的接口时,通常会返回一个结果实体,来标明这一次请求操作是否成功。

    例如:

      

    public class BaseResultDto<T> {
    
        /**
         * 是否操作成功
         */
        private boolean success;
    
        /**
         * 提示信息
         */
        private String msg;
        /**
         * 操作结果
         */
        private T result;
    }

    客户端在拿到这个实体后,可以明确得知,这一次操作是否成功。

    但是防御式编程中,我们应该对一切未知的接口都持有怀疑态度,况且不怕一万就怕万一:“如果服务端出现异常怎么办?”

    网上有2中答案:

      1,直接将异常抛出去,经过RPC序列化后,客户端进行展示。

      2,不抛异常出去,服务端进行全方位拦截,拦截到后,通过BaseResultDto,告诉客户端现在服务端出现异常了。

    但是各自的缺点很明显:

      1,服务端与客户端,很可能不在同一个应用中,所以各自会依赖不同的jar包,比方说:服务端抛出了个spring的duplicateKeyException,但是客户端并没用引用spring的相关jar包,这样就会导致:抛出异常后,由于客户端没有依赖这个类,最终抛出个ClassNotDefError,注意是Error不是Exception。如果客户端只对Exception进行捕获的话,会导致直接抛到最顶层。可能日志、重试等都没了。

      2,全方位拦截后,可能返回的结果中只会告诉客户端:“系统出现异常”,无法准确通过日志去定位问题。

    最终解决方案:

      将2者折中处理,服务端全方位进行拦截,如果出现异常后,把异常信息转换成字符串,然后把异常信息返回到客户端中:

      

    public class BaseResultDto<T> {
    
    	/**
    	 * 是否操作成功
    	 */
    	private boolean success;
    
    	/**
    	 * 提示信息
    	 */
    	private String msg;
    	/**
    	 * 操作结果
    	 */
    	private T result;
    
    	/**
    	 * 异常堆栈信息
    	 */
    	private String errorTrace;
    }
    

      errorTrace就是存储异常对战信息的属性,这样如果客户端检测到success为false,这样就可以直接把errorTrace打到log中,方便定位问题。

  • 相关阅读:
    BUAA OO 2019 第三单元作业总结
    OpenJML入门
    BUAA OO 2019 第二单元作业总结
    BUAA OO 2019 第一单元作业总结
    Spring MVC原理
    Spring AOP原理
    Spring DI原理
    Spring IOC原理分析
    观察者模式
    装饰模式
  • 原文地址:https://www.cnblogs.com/FranklinD/p/7242624.html
Copyright © 2011-2022 走看看