你遇到过这样的场景吗?硬件升级,需要更换高端机;对于网络重新规划,需要将几台服务器调整到机架;当服务器宕机时,需要重新部署以恢复服务;...更具体地说,如上图:数据库更改了一个ip。这时候连接数据库的upstream往往需要修改配置重启。如果数据库的上游调用者很多,就会有很多调用者改配置重启。每次换ip的成本往往很高。常见痛点。从A(数据库更改ip)的调整来看,配合修改调整的是BCDE(配置重启)。BCDE很郁闷:改ip的是你,怎么配合重启的是我?从根本上说,这是一个“架构耦合”的问题,是架构设计中“反向依赖”的问题。本文将讨论架构设计中常见的“反向依赖”设计以及相应的优化方案。希望对大家有所帮助。启发。如何找到不合理的“反向依赖”耦合?方法论:变更方为A,协调方为BCDE。(或者需求者是A,而改变者是BCDE。)画外音:想“你是改IP的,我是配合重启的”这样更好记住。如果这种情况在系统中经常出现,就是“反向依赖”的一个特点,往往在架构上还有优化的空间。场景一:公共库导致耦合。s1/s2/s3这三个服务通过一个公共库biz.jar实现了一段业务逻辑。其实s1/s2/s3都是通过biz.jar间接耦合在一起的。某业务s1修改了一段公共代码,导致影响其他业务s2/s3结构不合理。优化方案一:垂直业务拆分。如果biz.jar中实现的逻辑“业务特性”很强,可以拆分成biz1.jar/biz2.jar/biz3.jar来解耦s1/s2/s3。这样,任何业务变更只会影响自己,不会影响他人。优化方案二:面向服务。如果biz.jar中实现的逻辑“业务通用性”强,可以将biz.jar优化为biz.service服务,实现s1/s2/s3的解耦。面向服务后,通过接口自动化回归测试可以更好的保证兼容性。基础服务的抽象是一个共同的关注点,也是系统解耦的共同解决方案。场景二:服务化不完善导致耦合。服务化是解决“业务共性”组件库带来的系统耦合的常用方案之一,但如果服务不彻底,服务本身也很容易成为业务耦合点。不完全服务化导致的业务耦合的典型特征是公共服务中包含大量“根据不同业务执行不同个性分支”的代码。switch(biz-type)casebiz-1:exec1casebiz-2:exec2casebiz-3:exec3...该架构下,biz-1/biz-2/biz-3有个别业务需求,可能导致代码修改通用biz-service使其成为研发瓶颈,架构也不合理。优化方案:业务特征代码上浮,业务通用代码下沉,完成解耦。将switchcase中的业务特性代码放到业务层实现,让biz-1/biz-2/biz-3有个性化的业务需求,升级各自的业务系统。场景三:notify实现不合理导致的耦合。在《究竟什么时候该使用MQ?》一文中,有一种业务场景。消息发送者不关注消息接收者的执行结果。如果使用调用来实现通知,消息发送者和消息接收者将被耦合。如何添加消息接收者biz-4,你会发现修改代码的是消息发送者,添加对biz-4的调用是极其不合理的。优化方案:通过MQ实现解耦。消息发送者上层发布消息到MQ,消息接收者从MQ订阅。对于任何新的消息消费,上层不需要修改代码。场景四:配置中的ip导致上下游耦合。即在《出处》给出的例子中,更改下游服务的IP可能会导致多个服务调用者修改配置并重启。上下游通过ip配置间接耦合在一起,架构不合理。优化方案:下行连接使用内网域名,不使用ip。如果在配置中使用内网域名进行下游连接,当下游服务或数据库变更IP时,只需要在运维层面将内网域名指向新的IP,然后将原有的切断即可和旧连接统一,连接可以自动切换到新ip。这个过程不需要所有upstream配合,很帅气,强烈推荐!总结一下如何发现系统架构中不合理的“反向依赖”设计?变更方为A,合作方为BCDE;需求方为A,变更方为BCDE;这时候往往可以对架构进行解耦优化。如何优化常见的反向依赖?(1)公共库导致耦合。优化一:如果公库是业务特征代码,则对公库进行垂直拆分。优化二:如果公共库是普通业务代码,进行面向服务的下沉抽象。(2)服务化不完善导致耦合。特点:该服务包含大量“根据不同业务执行不同个性分支”的代码。优化方案:在业务层实现个性化代码,让服务更彻底、更纯粹。(3)notify实现不合理导致的耦合。特点:调用者不关注执行结果,通过调用实现通知,增加新的订阅者,发布者是修改代码的人。优化方案:通过MQ解耦。(4)配置中的ip导致上下游耦合。Feature:多个upstream需要修改配置重启。优化方案:使用内网域名代替内网ip,使用“修改DNS指向,统一切断旧连接”的方式切换上游无任何意义。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
