I是接口隔离原则,接口不应该设计的大而全,一个接口暴露出所有的功能,从而使得客户端依赖了自己不需要的接口或者接口的方法。而是应该讲接口进行细分和提取,而不应该将太过灵活的参数和变量混杂在一个接口中。
D是依赖倒置原则,A模块依赖于B模块,B模块有了修改,反而要改A,就是依赖的过于紧密的问题。这就是常说的,你变了,我没变,为啥我要改。如果基于抽象的接口编程,将修改隐藏在后面,则能够实现依赖的解耦。
以上是模块内部常见的设计原则,对于模块之间,则是对于云原生应用常说的十二要素原则。
十二要素原则详情可
八、有关配置文件
在代码仓库中,还需要管理的是配置文件,往往在src/main/resource下面。
配置的管理原来多使用profile进行管理,对于dev, test, production使用不同的配置文件。
然而当配置非常多的时候,比较的痛苦,而且配置不断的修改,每次上线各种配置需要仔细的核对,眼睛都花了,才敢上线。
我们可以将配置分为下面的三类:
内部配置项(启动后不变,改变需要重启)
集中配置项(配置中心,可动态下发)
外部配置项(外部依赖,和环境相关)
在梳理配置的时候,可以按着三类归类,分门别类管理。
在使用了容器之后,很多的内部配置项可固化在配置文件中,放在容器镜像中,需要启动的时候修改的,则通过环境变量,在启动容器的时候,在编排文件中进行修改。
依赖的内部服务的地址,在容器平台kubernetes里面,可以通过配置服务名进行服务发现,仅仅在配置文件中配置名称就可以了,不用配置真实的地址,kubernetes可以根据不同的环境,不同的namespace自动关联好,大大简化了配置。当然也可以用服务中心Dubbo和Springcloud做内部服务的相互发现。
依赖的外部服务的地址,例如mysql,redis等,往往不同的环境不同,也可以通过配置kubernetes外部服务名的方式进行,而不用一一核对,担心测试环境连上了生产环境的IP地址。
还有一些集中配置项,需要动态修改的,例如限流,降级的开关等,需要通过统一的配置中心进行管理。
九、有关数据库版本
代码可以很好的版本化,应用也可以用镜像进行原子化的升级和回滚。
唯一比较难做到的就是数据库如何版本化管理。
有一个开源工具 flyway 可以比较好的做这件事情。
在代码中,flyway需要有以下的结构:
在src/db/migration中有sql文件,命名规则,如:V1__2017_4_13.sql ,V开头+版本号+双下划线+描述,后缀为sql
增加flyway的java类,实现migration方法
在数据库中,flyway会自动增加SCHEME_VERSION表。
当服务启动的时候,java类的migration方法会被调用,它会按照指定路径中sql语句的版本号进行排序并且按照这个排序去执行,当每一个sql文件被执行后,元数据的表就会按照格式进行更新。
当服务重启的时候,Flyway 再次扫描sql的时候,它就会检查元数据表中迁移版本,如果要执行的迁移脚本的版本小于或者等于当前版本,Flyway将会忽略,不再重复执行。
但是flyway从来不解决数据库升级和回滚的代码兼容性问题。
太多的人问这个问题了,代码可以灰度发布,数据库咋灰度?代码升级了,发现不对可以回滚,数据库咋回滚。
如果可以停服的话,自然是使用数据库快照备份的方式进行回滚了。
如果不可以停服,没办法,只有在代码层面做兼容性。每次涉及数据库升级的都是大事情,代码当然应该有个开关,保证随时可以切回原来的逻辑。