分布式系统下应更加注重软件的可测试性
单体应用下,软件的问题相对比较容易定位,从界面上就能看出来,不行的话加个断点调试、输出日志等方法很容易测试到。
如果使用测试驱动开发达到100%代码覆盖率,那么更是如虎添翼。
在分布式系统环境下,相对而言测试更加难一点。
名词解释
什么是分布式系统架构?
理论上说,客户机/服务器风格(C/S)就是一种最简单的分布式系统架构,C和S分布于不同的机器。
举个例子,一个windows桌面应用程序直接连接远程服务器的数据库,这就是一个最简单的分布式系统架构。形成两层架构。
然后升级一下,一个windows桌面应用程序调用远程服务器提供的WEB服务,然后WEB服务又连接到另一台数据库服务器。形成三层架构。
三层架构的分布式系统明显会更难测试一点。
假如需要观察日志,那么windows桌面应用程序有日志,WEB服务也有日志。
假如需要对windows桌面应用程序进行断电调试,WEB服务里的实现无法进入,需要那着参数到WEB服务测试。
如果我们把WEB服务替换为socket/wcf/dubbo等远程过程调用呢?还需要用第三方工具,或单独为服务开发测试小工具。
否则一旦到无法使用断点调试的环境中,无法满足可测试性。
技术发展历史来看,web服务逐渐取代socket套接字成为soa的主流,开销更小是一个原因,我想更重要的是它容易测试。
场景假设
假如我们服务选择用wcf/socket/MQ取代web服务,在生产环境部署时,系统联调业务走不通,界面弹出“提交失败”。
怎么办?首先我们就是看日志,一看应用程序日志记录调阅服务失败,那么问题就定位到了服务。
实际环境应该更加复杂,一般成规模的企业都会有企业服务总线(ESB)以及网关(api-gateway),假如这种环境下提示“提交失败”,一看日志调阅ESB or gateway失败,相对就迷惑一下,到底是ESB or gateway出问题了还是其代理的服务出问题了。这时ESB or gateway的可测试性就显得比较重要,如果它们会给出详细的异常日志,告诉你到底是代理的服务具体抛出的异常那么就能很快定位,如果只是给出调阅服务失败,那么就比较迷惑了。
如果调阅服务是成功的,并没有任何报错信息,但返回的结果不是我们预期想要的,怎么办?
这个时候在服务调阅日志前能够记录调阅服务的地址和参数就能帮助我们快速定位问题,减少互相扯皮的消耗(当然不是有意扯皮的)。
企业服务总线ESB与微服务架构
一套好的ESB产品能够将MQ/WEB服务等不同协议统一。再提供输入参数的测试界面的话,它还等于为wcf/socket/MQ提供了测试工具。
ESB支持异构环境中的服务、消息,以及基于事件的交互。所以好的ESB产品能够为SOA架构中的组件提供可测试性。
近年来dubbo/spring cloud等分布式框架比较流行,mq都有好几种协议了,加上zk/consul等服务注册中心,目前很多商业ESB产品主要是支持自家品牌的组件,对这些开源组件的支持并不够。
我们公司自研的ESB也跟不上潮流的步伐,甚至都不支持消息和事件交互。
而微服务架构强调使用单一协议。例如apache dubbo会使用它自己的协议搞一套生态环境,提供给异构系统不同开发语言的dubbo框架,所以其他的消息队列、网关、web服务的整合。spring cloud其实也是同样道理,只不过它提倡的单一协议是restful web api,然后用bus把消息队列抽象成一种类似观察者模式的事件交互,很多地方和ESB有着异曲同工之妙。
所以验证一套分布式框架的好坏,也是需要注重它是否带有测试工具的。例如swagger,dubbo的doe。
题外话,我个人之见
如果说ESB是纵向把分布式组件整合在一起,那么微服务就是更加注重横向扩容的、适用于规模更大的场景使用。
从技术上,很多人总是喜欢拿单体应用和微服务比较,其实从架构演化角度看以ESB为核心的SOA架构于微服务比较更为接近。
以业务为主的,并发量可以承受的,架构上选择ESB为核心的SOA比较合适,比如一些有窗口的办事单位(医院、行政服务中心),他们的窗口限定了并发量,就算有网上办事的途径也只是针对地区,局部系统做一下负载均衡就能处理。选择微服务架构,无疑是杀鸡用牛刀,无形之中增加了软件公司和客户的开发运维成本,况且这类企事业单位一般也无法提供微服务相应规模的服务器。
就算选择SOA而非微服务,也并不代表一定排斥使用Spring cloud等,因为Spring cloud是一套分布式框架,并不等于就是微服务。
结束语
本篇文章简单地讨论分布式系统下软件质量中的可测试性。