事件经过:
    测试在做接口返回值回归的时候发现有接口返回的数据里面包含敏感字段,并有些接口返回的对象的泛型是DO,需要改为DTO,改完上线后没有通知引用方,但是二方包并没有发布,所以各个引用方还是正常部署,正常启动,5号当天交易系统发布时发现编译失败,原来二方包是当天才发布的(这里需要说明,引用的是snapshot版本,并且开发人员可以随时发布,每次修改的影响会在下次部署时生效),交易系统重新改了接口调用,将泛型改为DTO后上线,同时财务系统也做了这样的改动后上线,由于监控系统不完善,交易系统出现报错的点由刚好不会让用户感知,但是财务系统表现出来了,开始报大量的类转换异常,最后为了尽快将错误修复,交易系统和财务系统由将改动还原了回去,二方包也重新改回去,添加了新的方法返回DTO的泛型,重新上线然后问题解决。

    过程分析:
    1、最大的错误:修改了接口的签名,但是没有通知引用方,这个很严重,这个会直接导致引用方接口调用报错,并且接口签名应该不能进行更改,一旦上线了被引用了,即使通知了引用方,上线存在先后顺序,必然会出现一部分调用失败的,只能先将接口标记为废弃,后面等所有引用方都改过来之后再将废弃接口删除,减少代码污染。
    2、二方包的发布和引用snapshot版本,其实到底要不要引用snapshot版本,这个都有利弊吧,如果是一些兼容的升级,那是无关紧要的,当出现不兼容升级时,虽然使用正式版本也会存在需要引用方配合改动的情况,但是首先尽量不要搞不兼容升级,如果DTO需要修改字段类型,应该新起字段,如果方法需要改签名,要新增方法,不应该进行修改,不兼容升级的影响太大,并且无法绝对的同时上线。如果引用正式版本,虽然上面说的问题也存在,但是至少不会立即产生影响,至少能防止不小心发布的一些本身存在问题的二方包引起的问题。
    3、这里面存在的一个比较奇怪的问题,当部署发现问题的时候,提供者强调当时的改动已经上线,并且线上运行正常,到这里我们分析一下,接口原来的泛型是DO,各引用方也是使用的同样的方法签名进行调用,提供者改动之后上线,泛型变成了DTO,引用方方法还是原来的DO,这里通过dubbo调用序列化的时候,消费者收到DTO对象强转DO是能成功的,因为DTO继承了DO。当我们改完方法签名之后上线按说应该更加正常才对,但是问题出现了,开始报DO不能转换成DTO了,这里说明提供者方法的签名根本就没有改变,返回的对象的泛型还是DO,而我们的改成了DTO故而会出现转换失败,提供者还确定了一下部署的包到底是不是改动过之后的,结果是确实改过之后的,这里就存在矛盾,既然已经上线那就应该返回DTO,但是又说线上包里面确实是最新代码,这里没有继续深究,提供者急于修复问题,这里我推测要么线上机器没有全部部署,只是部署了一部分机器,而存在问题的也只是一部分机器,这里因为我没有权限,无法去验证这个答案。

    总结:
    1、已经发布的服务,一定不要改签名,可以通过提供新方法,将老方法标记为废弃的方式进行改造,避免对引用方的直接影响,然后通知到引用方进行改造。