前不久,我写了一篇《Fabric教程》,简单来讲,它是一个用 Python 开发的轻量级的远程系统管理工具,在远程登陆服务器、执行 Shell 命令、批量管理服务器、远程部署等场景中,十分好用。shell
Fabric 2 是其最新的大版本,跟早前的 Fabric 1 有挺大的不一样,更加好用了,可是没填上的坑也挺多的……服务器
本文继续来聊聊 Fabric,不过我不想再面面俱到了,而是专一于这一个话题:它是如何实现对批量服务器的串行/并发管理的?网络
(友情提示:为了有更好的阅读体验,若是你还不了解 Fabric 的基础用法,建议先阅读前面的教程。)数据结构
Fabric 经过 Group 来组合多台服务器。区别在于由 fabric.group.Group 基类(父类)派生出的两个子类:多线程
下面先看看这个基类:并发
我把一些没用的信息折叠了,比较值得注意的内容有:app
有了这个基类,接下来就要看 SerialGroup 和 ThreadingGroup 的具体实现了。工具
SerialGroup 类很简单,只实现了一个 run() 方法。由于类在初始化时为全部 host 创建了链接并且存了起来,因此这里只需用 for 循环依次取出,再执行 Connection 的 run() 方法。线程
这里能够看到一种很是实用的开发技巧: 建立类时,让它继承内置的数据结构(如 list、dict), 这样能够直接使用 self.append()、self.extend()、self.update() 等方法把关键的信息存到“自身”,再到取出时则“for xxx in self”,这样就免了建立临时的 list 或 dict,也省得要在参数中传来传去。blog
GroupResult 和 GroupException 是对执行结果和异常的处理,不是咱们关注的重点,这里略过。
接下来看看 ThreadingGroup,它也只有一个 run() 方法:
ExceptionHandlingThread 是一个继承了 threading.Thread 的类,这是一种建立多线程的方式。每一个线程执行的方法主要作两件事:执行 connection 的 run() 方法,以及将执行成功的结果存入队列中。
接下来再分别把执行成功的结果与出异常的结果都存入到 results 中。
因此,Fabric 是使用了 threading 多线程的方式来实现并发。网络请求是 IO 密集型的,使用多线程是不错的方式。
至此,对于咱们在开头提的问题,就有了一个初步的答案:Fabric 封装了两种 Group 来批量管理服务器,其中串行方式就是用了简单的 for 循环,而并发方式使用了 threading 多线程方式。
可是,经过分析这两种 Group 的实现代码(以及使用的实践),咱们也能够发现 Fabric 的缺陷:
这几个问题在 Fabric 的 Github issue 中,被不一样的人反复提出,可是尚未获得很好的回应……
言归正传,本文主要分析了 Fabric 在批量管理服务器时的实现方案,阅读其源码,能够了解到串行/并发典型场景的用法,以及类定义、类继承、多线程、异常处理等内容,最后,咱们还揭示出了它的几个特性缺陷。
感谢阅读。最后,附上 Fabric 教程:https://mp.weixin.qq.com/s/UHtPaxO2ojql5ps4hTn3Vg