RPC调用异常行为与处理方案总结
背景
在使用IAcsClient或者dubbo进行rpc调用时, 异常情况总是不可避免的.
这里总结下各种异常, 以及对应的表现形式与处理方式.
异常总结
| 错误分类 | 错误细分 | IAcsClient | Dubbo | 
|---|---|---|---|
| 客户端异常 | 客户端网络无连接, 闪断等 | 
- IAcsClient 抛出ClientException异常
 |com.aliyuncs.exceptions.ClientException: SDK.ServerUnreachable : Server unreachable: connection
- 抛出RpcException异常:
 |
 |
|  | SDK参数缺失错误等 |
- IAcsClient 抛出ClientException异常
 |com.aliyuncs.exceptions.ClientException: SDK.InvalidProfile : No active profile found.
- 不会有该场景, 因为dubbo调用没有SDK
 |
 | 服务端异常 | 服务端限流, 处理超时 |
- IAcsClient 抛出ServerException异常
 | |
 | | 业务异常, 例如请求参数错误, SPOT价格设置过低等 |
- IAcsClient 抛出ClientException异常
- 注意ServerException是ClientException的子类
 |
- 不抛异常, 返回 PlainResult
 |
 |
|  | 服务端未提供该服务 |
- IAcsClient抛出ClientException异常
 |com.aliyuncs.exceptions.ClientException: InvalidVersion : Specified parameter Version is not valid. RequestId : xxx com.aliyuncs.exceptions.ClientException: InvalidAction.NotFound : Specified api is not found, please check your url and method. RequestId : xxx
- 抛出RpcException异常: 
 |com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method xxx in the service xxx. No provider available for the service xxx from registry xxx
 | 其他异常 | | IAcsClient正常返回. 返回对象里:
 AcsResponse有requestId, 但返回结果为空, success=false
 啥时候会有这种异常? | |
异常处理
IAcsClient异常处理
所以针对IAcsClient, 可以按照如下方式进行异常处理:
try {
    ecsInnerClient.getAcsResponse(req);
}
catch (ServerException e) {
     // client调用超时, 被服务端限流等, 都会抛出异常, 走到这里, 需要后续降级到库存缓存实现.
     listResourceResponse.setSuccess(Boolean.FALSE);
     log.error("DescribeResourceAllocation ServerException. request: {}", JSON.toJSONString(req), e);
 } catch (ClientException e) {
     // SPOT价格不满足, 客户端传入参数有错误, 等业务异常, 走到这里, 无需后续降级到库存缓存实现.
     listResourceResponse.setSuccess(Boolean.TRUE);
     log.error("DescribeResourceAllocation ClientException. request: {}", JSON.toJSONString(req), e);
 }