上篇文章,我们介绍了如何利用Distcc来搭建分布式编译环境,但是Distcc的默认调度策略过于简单,并且并不合理。假如我们的配置是
export DISTCC_HOSTS="192.168.1.11 192.168.1.22 192.168.1.33"
那么Distcc会根据DISTCC_HOSTS中机器出现的先后顺序,来安排编译任务,越靠前的机器(比如这里的192.168.1.11)获得越多的任务,这显然是不科学的。
因此,我们可以利用Dmucs提供的调度策略,来优化我们的方案。它可以根据编译机的负载情况和硬件实力,来合理的调度资源。能者多劳嘛。
为了保证本文的完整性,我们还是不厌其烦地把我们的环境再交待下:
开发机(Client):这一台机器上有我们的项目、工程文件、代码,平时我们在这台机器上写代码,要编译的对象也在这台机器上。机器IP为192.168.1.99。
服务器(Server):负责编译的机器,一共有3台。IP分别为192.168.1.11,192.168.1.22,192.168.1.33。
调度器(Scheduler):调度程序Dmucs所在的机器,负责把编译任务合理的派发到编译机器(服务器)的编译程序上。IP为192.168.1.88。
服务器
1,安装gcc
sudo apt-get install gcc
2,安装Distcc
sudo apt-get install distcc
安装后可以得到两个二进制文件,distccd和distcc。前者主要负责网络数据处理,后者可以认为是g++的前端,调用g++进行编译。
3,配置Distcc
打开/etc/default/distcc
,设置如下配置项:
STARTDISTCC="true"
ALLOWEDNETS="127.0.0.1 192.168.1.0/24"
LISTENER="0.0.0.0"
第一行设置开机就启动distccd
第二行设置允许利用本机进行编译的开发机
第三行设置监听的网络
4,启动distccd
sudo service distcc start
经过以上配置,每次机器开机,都会自动运行distccd。
运行如下命令确认下:
ps -aux | grep distccd
如果看到类似的输出,说明distccd成功启动了。
distccd 3457 0.0 0.0 3260 144 ? SNs 23:33 0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10
distccd 3458 0.0 0.0 3260 144 ? SN 23:33 0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10
distccd 3461 0.0 0.0 3260 144 ? SN 23:33 0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10
5,安装Dmucs
首先,从这里下载最新版本的Dmucs。
安装也就是普通的configure
、make
和make install
,需要注意的是,执行make时,需要加上参数,例如:
make CPPFLAGS=-DSERVER_MACH_NAME=\\\"192.168.1.88\\\"
其中192.168.1.88是我们的调度器的机器IP,根据实际情况自行修改。服务器上的编译程序,需要把编译负载情况,发送给调度器上的调度程序,作为它调度时的参考信息。
如果您嫌这样麻烦,那么也可以在make的时候不指定选项,而是在安装后,打开/etc/default/dmucs
文件,设置如下字段:
USE_SERVER = 192.168.1.88
6,启动loadavg
loadavg是安装Dmucs后得到的一个二进制文件,它会定期发送服务器平均负载情况给调度器,供调度程序决策之用。
sudo loadavg -s 192.168.1.88 &
其中,192.168.1.88是调度程序所在机器的IP地址。
调度器
1,安装Dmucs
请参考上面的第5步。
2,配置服务器属性
在调度器的/usr/local/share/dmucs/
目录下,新建hosts-info文件,格式和内容如下:
#Format: machine number-of-cpus power-index
192.168.1.11 4 10
192.168.1.22 4 5
192.168.1.33 4 5
其中,power-index(必须大于等于1)表示了这台机器的战斗力,值越高代表性能越强,分到的编译任务也越多。能者多劳嘛。
3,启动调度程序
命令为:
sudo service dmucs start
开发机
1,安装Distcc
当然啦,我们假设您的开发机上已经安装gcc了。
2,安装Dmucs
请参考上面的第5步。
3,应用Distcc和Dmucs
应用Distcc和Dmucs来编译代码有几种方法:
方法一:修改makefile中的CXX的值
将makefile文件中的这一行
CXX = g++
改为
CXX = gethost distcc g++
然后运行make -j18
即可。这里的18,为所有服务器的CPU Cores的数量乘以1.5。上面有3台服务器,每台有4核,因此这里设置为18。
为了获得最优值,很可能需要反复实验、测试。这里的gethost是DMUCS里的一个组件。
方法二:修改configure文件
如果您的makefile文件由automake产生,那么在运行./configure
时得加上参数,变为:
./configure --CXX=gethost distcc g++
那么生成的makefile文件将自动使用Distcc和Dmucs了。
附录:调度策略
根据文档,Dmucs的调度策略是:
1,Dmucs会维护几个列表(原文为tier,表示等级、阶梯),每个列表对应一个power-index,具有相同power-index值的机器会在同一个列表中。因此,上面三台服务器,192.168.1.22和192.168.1.33会在同一个列表里,192.168.1.11在一个列表里。
2,每次获得编译任务请求时,Dmucs会优先从高power-index对应的列表里随机选一台机器。
3,如果Dmucs获知某台机器的平均负载过高(回忆下,该信息是服务器上的loadavg进程发过来的),那么会把该机器放到低一级的power-index对应的列表里。例如,192.168.1.11会被“下放”到power-index为5对应的列表里。
4,如果某台机器的平均负载过高超过五分钟,那么该机器会被暂时雪藏,不会给它分发编译任务,直到它的负载下降到正常水平。