服务化最佳实践

一、分包分发

建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。

异常声明处理是服务调用中不可缺少的部分。通常服务提供方定义明细业务错误异常码,调用方进行捕获处理。进一步的异常规约我们稍后会具体说明。

二、接口粒度

接口粒度:服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题。也就是说同一个操作功能场景尽可能囊括到一个服务里,减少调用关联方。

抽象:服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。

三、服务版本

如果可能,有必要细粒度版本化到服务接口级别,以更好的控制服务迭代升级。

建议使用两位版本号,因为第三位版本号通常表示兼容升级,只有不兼容时才需要变更服务版本。

当不兼容时,先升级一半提供者为新版本,再将消费者全部升为新版本,然后将剩下的一半提供者升为新版本。

四、升级兼容性

除非是新的功能服务接口,旧的服务升级必须处理接口的向后兼容性。

接口增加参数或者返回值增加字段一般可以兼容,涉及修改或者删除则及枚举类型使用时,则需要通过版本号升级处理。

枚举值:

如果是完备集,可以用 Enum,比如:ENABLEDISABLE

如果是业务种类,以后明显会有类型增加,不建议用 Enum,可以用 String 代替。

如果是在返回值中用了 Enum,并新增了 Enum 值,建议先升级服务消费方,这样服务提供方不会返回新值。

如果是在传入参数中用了 Enum,并新增了 Enum 值,建议先升级服务提供方,这样服务消费方不会传入新值。

五、序列化

服务参数及返回值建议使用 POJO 对象,即通过 settergetter 方法表示属性的对象。

服务参数及返回值都必须是传值调用,而不能是传引用调用,消费方和提供方的参数或返回值引用并不是同一个,只是值相同。

六、关于调用异常

建议使用异常汇报错误,而不是返回错误码,异常信息能携带更多信息,并且语义更友好。

如果担心性能问题,在必要时,可以通过 override 掉异常类的 fillInStackTrace() 方法为空方法,使其不拷贝栈信息。

查询方法不建议抛出受检异常,否则调用方在查询时将过多的 try...catch,并且不能进行有效处理。

服务提供方不应将 DAO 或 SQL 等异常抛给消费方,应在服务实现中对消费方不关心的异常进行包装,否则可能出现消费方无法反序列化相应异常。

七、参数检查过滤

调用方及服务方都应该对输入参数进行校验。可以通过统一的拦截方式处理。

如通过检查空值、参数长度等进行过滤,减少不必要的调用资源消耗及异常隐患,

八、附加订阅

 

posted @ 2020-06-07 16:26  WindWant  阅读(285)  评论(0编辑  收藏  举报
文章精选列表