在RPC(远程过程调用)系统中,采用枚举类型的运用,固然增进了代码的可读性和可维护性,然然而在多服务环境中,对枚举类型的更新和兼容性调整可能带来一些问题。

一处线上异常

1
2
3
4
com.alibaba.com.caucho.hessian.io.HessianFieldException: com.tem.car.domestic.dto.order.OrderDto.hubsCode: java.lang.reflect.InvocationTargetException
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:168)
Caused by: java.lang.IllegalArgumentException: No enum constant com.xxx.ztrip
at java.lang.Enum.valueOf(Enum.java:238)

A在调用B服务的dubbo接口时,由于B服务中新增了OriginType枚举类型,名为ztrip,而A服务未及时升级相应版本,导致整个接口出现异常。

如何解决这一问题?

既然我们已找出问题的根源,解决起来也并非难事,只需将A服务中的相关jar包版本升级即可。

这种问题的解决方案有哪些?

方案一、维持现状,遇到问题解决问题
方案二、当枚举类型增加常量时,需将所有依赖该枚举的服务进行升级

即使确定了有哪些服务依赖了此枚举,修改和发布版本的成本对许多团队来说仍是难以承受的。

方案三、

在RPC中避免使用枚举类型,而仅采用基本类型(如字符串),以杜绝此类异常的发生。
尽管该方案可规避异常,却也丧失了使用枚举类型的益处。那是否可以将将基本类型转换为枚举类型的逻辑置于A服务中呢?
很明显,此举是可行的,然而问题又回到了原点,A服务仍无法使用新添加的常量,若进行强制转换仍会引发程序异常。或许可以在转换过程中加入降级逻辑,当遭遇新常量时采取降级方案。具体如何降级,请由A服务开发人员衡量新枚举的重要性。

总结

本文分析了在RPC系统中使用枚举类型所引发的同步问题,并通过一个具体例子展示了服务间枚举不同步可能导致的异常。文章重点推荐了第三种解决方案:避免在RPC接口中使用枚举类型,改用基本类型如字符串,并在必要时进行枚举转换,同时引入降级逻辑处理新常量。这种方法既减少了因枚举不同步引发的问题,又保持了代码的灵活性和可维护性。