Sersync二次编译与使用(一)

Linux系统 gongyj 1952℃ 已收录 0评论

Sersync 是金山逍遥网技术支持部平台组周洋,开发的一款基于 inotify + rsync 的大量文件的多服务器自动同步程序,目前已开源,开源协议为 New BSD License。

原理:

  使用 Linux 2.6 内核的 inotify 监控 Linux 文件系统事件,被监听目录下如果有文件发生修改,sersync 将通过内核自动捕获到事件,并将该文件利用 rsync 同步到多台远程服务器。sersync 仅仅同步发生增、删、改事件的单个文件或目录,不像rsync镜像同步那样需要比对双方服务器整个目录下数千万的文件,并且支持多线程同步,因此效率非常高。

sersync1.jpg

sersync主要用于服务器同步,web镜像等功能。基于boost1.43.0,inotify api,rsync command.开发。目前使用的比较多的同步解决方案是inotify-tools+rsync ,另外一个是google开源项目Openduckbill(依赖于inotify- tools),这两个都是基于脚本语言编写的。相比较上面两个项目,本项目优点是:

1、sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤(详细见附录,这个过滤脚本程序没有实现),所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。

2、相比较上面两个项目,sersync配置起来很简单,其中bin目录下已经有基本上静态编译的2进制文件(分为32版本,与64位版本),配合bin目录下的xml配置文件直接使用即可。

3、另外本项目相比较其他脚本开源项目,使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态。

4、本项目有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步。

5、本项目自带crontab功能,只需在xml配置文件中开启,即可按您的要求,隔一段时间整体同步一次。无需再额外配置crontab功能。

6、本项目socket与http插件扩展,满足您二次开发的需要。

摘自:https://code.google.com/p/sersync/

基本架构:

sersync2.png

设计简析:

如上图所示,线程组线程是等待线程队列的守护线程,当队列中有数据的时候,线程组守护线程逐个唤醒,当队列中inotify事件交多的时候就会被全部唤醒一起工作。这样设计的目的是能够同时处理多个inotify事件,重发利用服务器的并发能力(核数*2+2)。

之所以称之为线程组线程,是因为每个线程在工作的时候,会根据服务器的数量建立子线程,子线程可以保证所有的文件与各个服务器同时同步,当要同步的文件较大的时候,这样设计可以保证各个远程服务器可以同时获得要同步的文件。

服务线程的作用有三个,首先是处理同步失败的文件,将这些文件再次同步,对于再次同步失败的文件会生成rsync_fail_log.sh脚本,记录失败的事件。同时每隔10个小时执行脚本一次,同时清空脚本。服务线程的第三个作用是crontab功能,可以每隔一定时间,将所有路径整体同步一次。

过滤队列的建立是为了过滤短时间内产生的重复的inotify信息,例如在删除文件夹得时候,inotify就会同时产生删除文件夹里的文件与删除文件夹得事件,通过过滤队列当删除文件夹事件产生的时候,会将之前加入队列的删除文件的事件全部过滤掉,这样只产生一条事件减轻了同步的负担。同时对于修改文件的操作的时候,会产生临时文件与重复操作。

举例:

当我们在vi的一个test文件,进行wq操作的时候会产生如下事件:

sersync3.png


即使把"."开头与"~"结尾的世界过滤了,对于test文件仍旧有3次操作,分别是删除,创建与保存,通过过滤队列,就只剩下一个事件,一定程度上也提高了效率。

过滤队列第二个作用,即当你在本机删除目录的时候,假设你删除一个有5个文件的目录,inotify会产生6个事件,分别是5个文件删除事件,和一个删除目录事件,如果使用过滤队列,正常情况下会只产生一个删除目录的事件,大大减少了rsync通信次数。(当然,这不是绝对的。如果这6个事件分多次读到进入队列,那么可能还没来得及过滤,就已经被同步线程从队列中取走同步了。但一定程度上可以减少删除文件夹得同步通信次数)。

过滤队列的第三个作用,可以过滤监控目录下的文件夹,如果不想同步目录下的一些文件夹,或者一些后缀的文件。对于不需监控的子文件夹,在inotify启动时候remove掉监控,对于不需监控子文件,产生的文件事件就会从在入同步队列前过滤掉。如果使用rsync用–exclude, 这样虽然也可以过滤,但还是与rsync守护进程进行了一次交互。

一、二次编译

因为某些安全需求,所以需要rsync使用ssh模式进行传输。虽然sersync已经支持了这种传输模式,但遗憾的是,周洋似乎没有考虑到线上环境基于安全考虑,一般ssh都使用了非22端口,造成sersync在ssh非默认端口下,不能使用。

sersync已经很久没有跟新了,本来想联系周洋,让他修改一下,但未能得到回应,只好自己动手,修改源代码,重新编译编译源代码。说干就干,先下载并分析代码,然后看懂代码并找到要修改的文件。

从Google Code中下载源码包与二进制包进行分析

源码包:https://sersync.googlecode.com/files/sersync2.5_source.tar.gz

二进制包:https://sersync.googlecode.com/files/sersync2.5.4_64bit_binary_stable_final.tar.gz

打开配置文件confxml.xml,找到以下几行

vim confxml.xml
29 <rsync>
30    <commonParams params="-artuz"/>
31    <auth start="false" users="root" passwordfile="/etc/rsync.pas"/>
32    <userDefinedPort start="false" port="874"/><!-- port=874 -->
33    <timeout start="false" time="100"/><!-- timeout=100 -->
34    <ssh start="false"/>
35 </rsync>

在34行,我们可以发现ssh启用与否,默认是关闭的。大家都是知道,所有服务都会有一个默认端口,如果没有指定端口,就是默认端口,如果要使用其它端口,那么我们必须要指定端口号。很显然这行没有设置端口的参数,如果我们模仿上边的写法,给他加上port参数,那么也不会生效,因为程序根本不会加载这个参数。如果想让我们增加的参数生效,就必须要修改源代码,重新编译成二进制。

按照这个思路,我们就要看懂源代码,然后找到ssh功能部分的代码,并改造它重新编译。经过分析查找,我们可以确定,FileSynchronize.cpp就是我们要修改的文件,打开查看一下这个文件

133    temp = xNode.getChildNode("rsync").getChildNode("ssh").getAttribute("start");
134    if ( temp == "true" ) ssh = " -e ssh ";

以上2行,就是ssh模式的关键部分,修改思路有一下2种:

1、写死参数,指定一个端口,如1503

temp = xNode.getChildNode("rsync").getChildNode("ssh").getAttribute("start");
if ( temp == "true" ) ssh = " -e 'ssh -p 1503' ";

直接替换ssh双引号中的内容,这样简单,配置文件也不需要在修改就可以使用新的端口,但缺点就是不能随意修改,如有变更,就的重新编译。

2、传参形式,动态修改端口

    temp = xNode.getChildNode("rsync").getChildNode("ssh").getAttribute("start");
    if (temp == "true") {
         string d = xNode.getChildNode("rsync").getChildNode("ssh").getAttribute("port");
         ssh = " -e 'ssh -p " + d + "'" + " ";
     }

重新构造一个参数d,并从配置文件port中传入数据,这样就可以在配置文件中,任意的去定义端口了,接下来编译就可以了。

二、搭建编译环境

软件及系统环境都不能使用太新的版本,sersync 依赖的环境都是比较旧的,环境不符合的话,是无法编译的,会报错。如果一定要使用新版的话,那需要大量的修改源代码。在 centos 6 下,旧的软件无法编译安装,而新版的软件,虽然可以正常使用,但无法编译sersync,所以编译环境使用以下版本的软件搭建环境。

1、首先安装相关依赖软件包

yum install -y gcc gcc-c++ python python-devel zlib zlib-devel bzip2 bzip2-devel openmpi openmpi-devel

如不需要mpi,可以忽略系统提示

然后下载安装boost c++库。

可以到官方下载,也可以从如下地址下载,使用前安装boost依赖库,icu用来解决编码问题。

 https://johntech-resource.googlecode.com/files/icu4c-4_0_1-src.tgz

 http://johntech-resource.googlecode.com/files/boost_1_44_0.tar.bz2

下载完后,到软件所在目录开始安装

cd /usr/local/src/
tar zxvf icu4c-4_0_1-src.tgz
cd icu/source
./configure --prefix=/usr
make && make install

下面开始编译boost c++库

cd /usr/local/src/
tar jxvf boost_1_44_0.tar.bz2
cd boost_1_44_0
./bootstrap.sh
./bjam -sHAVE_ICU=1
./bjam install

新安装的文件会被安装到/usr/local的相应目录下。这个目录会在netbeans项目中配置,其它IDE环境配置方式请参考IDE相应文档。

下载安装NETBEANS开发环境,请注意下载c/c++版本。

下载地址:http://netbeans.org/downloads/index.html

由于NetBeans需要java环境运行,所以我们先配置jdk,然后在安装

mkdir /usr/java
tar xf jdk-7u76-linux-x64.gz  -C /usr/java
vim /etc/profile
export JAVA_HOME=/usr/java/jdk1.7.0_76
export JAVA_BIN=/usr/java/jdk1.7.0_76/bin
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH
source /etc/profile
java -version
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)

2、开始安装NetBeans

chmod +x netbeans-7.0-ml-cpp-linux.sh 
./netbeans-7.0-ml-cpp-linux.sh

操作过程如以下图片所示:

NetBeans1.png


NetBeans2.png


NetBeans3.png


NetBeans4.png


NetBeans5.png


NetBeans6.png

到这里安装过程就完成了,然后启动 NetBeans IDE 7.0,开始编译源代码。

编译过程的操作方法如下列图片所示:

NetBeans7.png


NetBeans8.png

把修改好的源代码放到下边的目录中

NetBeans9.png

Makefile文件自己重写也可以,这是编译源代码的方法,我这里就是用源码里文件来编译。

NetBeans10.png


NetBeans11.png


NetBeans12.png


NetBeans14.png


NetBeans15.png

系统会自动清理/root/sersync2/build/Release/目录和/root/sersync2/dist/Release/GNU-Linux-x86/sersync2文件,然后重新生成。

sersync2_news.png


sersync2_news2.png

这样就编译成功了,现在就可以配置是用了。关于如何配置使用的方法,将会在下一篇文章中,做详细的说明。




本站文章如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权,转载请注明转自:http://blog.chopmoon.com/favorites/209.html
喜欢 (0)
发表我的评论
取消评论

表情 代码 贴图 加粗 链接 私信 删除线 签到

Hi,请填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
正在加载中……