问题:一个RPC调用当遇到参数错误等问题时,是抛出一个Exception 还是返回 errorCode 呢?

  • 什么时候抛出异常?

异常就是我们认为在正常情况下不可能发生的问题,并且服务代码不知道如何去做处理。

如果发生的情况是可以预期的,那么就不应该抛出。

  • 抛出 checked 还是 unchecked 异常?

取决于客户端代码能够根据这个例外进行合理的解释。如果不知道如何处理,抛出 unchecked 。

结论:

是否抛出异常是取决于服务端代码能够进行合理的处理。

抛出什么类型的异常则取决于客户段代码能够进行合理的处理。

Exception 处理之最佳实践 :http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Robust Exception Handling:https://eli.thegreenplace.net/2008/08/21/robust-exception-handling/

阿里巴巴Java开发手册:https://yq.aliyun.com/attachment/download/?spm=5176.100239.blogcont69327.9.Zy97Qs&id=4942


异常原理:

  • 编程错误导致的异常:
  • 客户端代码错误导致的异常:
  • 资源失败导致的异常:

Java中有两类异常:

  • Checked Exception:都是Exception的子类;
  • Unchecked Exception:都是RuntimeException的子类,虽然RuntimeException也是Exception的子类,但是它们是特殊的。它们不能通过 Client code来解决。

设计异常的最佳实践

  1. 当要决定是采用 checked Exception 还是Unchecked Exception 的时候,要确认一个问题:如果异常一旦抛出,客户端会做怎么样的补救?
    • 如果客户端可以通过其他的方式恢复异常,那么这种异常就是 checked Exception。反之,就是Unchecked Exception。从使用上来讲,当异常出现的时候要做一些试图恢复它的操作而不要仅仅的打印它的信息。
  2. 保护封装性。不要让你抛出的checked Exception升级到较高的层次。也就是不要异常传递。
  3. 不要创建没有意义的异常。checked Exception应该让客户端从中拿到丰富的信息。

阿里巴巴Java开发手册:

在代码中使用“抛异常”还是“返回错误码”,对于公司外的 http/api 开放接口必须使用“错误码”;而应用内部推荐异常抛出;

跨应用间 RPC 调用优先考虑使用 Result 方式,封装 isSuccess()方法、“错误码”、“错误简短信息”。

说明:关于 RPC 方法返回方式使用 Result 方式的理由:

  1. 使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
  2. 如果不加栈信息,只是 new 自定义异常,加入自己的理解的 error message,对于调用

端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输 的性能损耗也是问题。