该文原创为新潮质量保障技术团队中的 “上进的中年软件测试从业者”,用于技术交流分享

本来这一期应该讲 Mock 功能的实现,但是这周刚好做了服务拆分的工作。个人觉得之前的内容都过于笼统,有的甚至缺失了一些关键步骤。本着负责任的态度,还是要提升一下内容的质量。刚好这周做的服务拆分功能新鲜出炉,很多坑都还记得,能够详细的跟大家介绍一下,这里只是单纯的服务拆分,与架构理念上的服务拆分不是一回事。

背景

首先先说一下背景,之前有提到过容器化部署,然后带来的一个很大的问题是不能解决发布分支的问题。目前测试部门只用了一个仓库,包含了三个部分,项目的自动化测试、公共工具以及公共工具下面的测试平台。这一堆揉到一起,没有办法让所有人遵循 feature->release-pre-master 的分支管理流程。为了更好遵循版本发布流程并与公司的发布规范一致,所以做了这次服务拆分。

拆分注意事项

• 确保工具库能为项目和测试平台提供服务。
•把测试平台独立出来。
• 所有的代码的提交记录要保留。
•对外无任何影响。

拆分代码库

如何保障代码迁移过程中提交记录不会丢失?假设以前只有一个代码库 git_a, 里面的代码结构为 AutoTest/Tools/TestPlatform, 我想把 Tools 和 TestPlatform 都独立出来到一个单独的 git 仓库,操作如下:
· 首先为 Tools 和 TestPlatform 创建单独的代码仓库,并且都 checkout 到一个文件夹下面,也就是这个文件夹包含 AutoTest、Tools、TestPlatform 这三个仓库。(这个很简单,直接在 gitlab 上面操作即可)

•在原来的 AutoTest 仓库里面执行如下命令:
◾git subtree split-P Tools/TestPlatform -b branch_for_testPlatform-new(这样就通过 subtree、split 功能把 Testplatform 代码独立到 branch_for_testPlatform-new 分支里面了)

•切换到 TestPlatform 仓库下面,执行如下的命令:
◾cd ../TestPlatform/
◾git pull ../Projectbranch_for_testPlatform-new
◾git push(这样就实现了把 TestPlatform 的代码从原来的仓库 push 到 Testplatform 新的仓库里面了)

•可以通过手动操作,把 TestPlatform 从原来的代码库删除,并 push。

•切换到原来的 AutoTest 仓库继续执行如下命令:
◾ git subtree split-P Tools -b branch_for_Tools-new

•切换到 Tools 仓库下面,执行如下命令:
◾ cd ../Tools/
◾git pull../Projectbranch_for_Tools-new
◾git push(这样就实现了把 Tools 的代码从原来的仓库迁移到新仓库里面了)

•可以通过手动操作,把 Tools 从原来的代码库删除,并 push。
Done

服务间调用选型

测试平台服务
测试平台之前就是走的 flask_admin,所以迁移过后还是不变,依然采用 flask_admin 的框架启动服务。
Done

工具类服务

flask
因为用过了 flask_admin 框架,所以这个地方还是想用同样的框架进行服务启动。服务启动后要把之前的写好的日志处理、http 请求处理、ssh 处理、XML 处理等直接把对象通过接口传给测试平台,选择了采用序列化和反序列化的方式进行。
服务端:

用户端:

这个时候发现了一个之前完全没考虑到的问题,反序列化之后,找不到模块????为什么????
原来是反序列化要成功,首先你本地有要对应的模块,才能反序列化。这就是个死循环了,我本地如果有的话,我还拆分服务干什么。

RPC
以前做的完全推翻,这个时候就需要找一种新的方案代替,刚好我对面是个前端大佬(这个时候不应该是后端大佬吗??),他告诉我可以采用 RPC 技术,把对象传递过去。如果我没理解错的话,JAVA 中采用 Dubbo 也是同样的逻辑,这里多说一句,其实技术多半都是相通的,也就是内功深了,招式只是表现形式。
然后就在网上搜索关于 pythonRPC 的框架,然后就发现了 xmlrpc 和 flask 自带的 RPC 框架(牛 X)。准备开始试验:
xmlrpc
服务端(网上截的图):

客户端(网上截的图):

然而让人崩溃的是,xmlrpc 只支持传输方法,并不支持类和属性。

rpyc
继续找,然后了找到了 python 的 rpyc 框架,最终实现功能。
服务端:

客户端:

•这里可以传递类、属性以及方法,通过 root.get_object 获取。
•如果双方都需要对彼此的属性进行修改需要设置 allow_all_attrs 为 True。
•如果允许任何开头的方法,需要设置 allow_public_attrs 为 True否则只允许exposed_开头的方法。
•rpyc 有内置的 dict、list,看上去与普通的 dict 和 list 没什么区别,但是这就遇到了一个坑,想用常规的 json.dumps 进行数据转换是行不通的,必须要通过自己重写的逻辑转换为常规的 dict 或者 list。

以上就完成了服务拆分,至于容器之间的服务调用这里就不说了。好在我们的虚拟团队还不是很大,所承载的责任也不是很重。所以有 1 天多的时间留给我专门来做这件事,而不会耽误什么。好在一切都恢复正常,也很久没有体验过这种肾上腺飙升的感觉。有个管理学的理论对人性的定义是,人总是希望能够提升自己直到自己不能胜任的位置,技术也是一样。或许一切都还来得及,把握当下,与你共勉。今天就介绍到这里,下一期还是要介绍一下 Mock 的实现,感谢大家的耐心阅读,下次见!


↙↙↙阅读原文可查看相关链接,并与作者交流