一、Inotify介绍:
Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除、读、写和卸载操作等。您还可以跟踪活动的源头和目标等细节。
使用 inotify 很简单:创建一个文件描述符,附加一个或多个监视器(一个监视器 是一个路径和一组事件),然后使用 read 方法从描述符获取事件。read 并不会用光整个周期,它在事件发生之前是被阻塞的。
内核版本不低于 2.6.13,系统就支持 inotify。 同时可以查看内核参数
[[email protected] inotify]# cd /proc/sys/fs/inotify/
[[email protected] inotify]# ll
total 0
-rw-r--r-- 1 root root 0 Aug 29 17:20 max_queued_events
-rw-r--r-- 1 root root 0 Aug 29 17:20 max_user_instances
-rw-r--r-- 1 root root 0 Aug 29 17:20 max_user_watches
[[email protected] inotify]# cat *
16384
128
8192
notify-tools
是为linux下inotify文件监控工具提供的一套c的开发接口库函数,同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件。
inotify-tools是用c编写的,除了要求内核支持inotify外,不依赖于其他。inotify-tools提供两种工具,一是
inotifywait,它是用来监控文件或目录的变化,二是inotifywatch,它是用来统计文件系统访问的次数。现在介绍一下它的使用方法。
查看notify-tools信息: https://github.com/rvoicilas/inotify-tools/wiki
结合rsync进行测试,脚本如下:
#!/bin/sh
cmd=`which inotifywait`
$cmd -mrq --timefmt "%F %T" --format "%T %f" -e create,close_write,attrib /data | while read date time file
do
cd /data && rsync -azv $file [email protected]::data --password-file=/etc/rsyncd.pass
done
注:加上delete事件会导致删除同步错误,提示文件不存在,故删除事件单独启个脚本进程。
性能测试:
针对大量的小文件 ,同步小文件太慢,直接同步目录
10-100k的小文件,并发达到200-300,需要对内核三个参数进行调优
max_queued_events: 320000 max_user_watches:5000000
二、sersync介绍:
sersync利用inotify与rsync对服务器进行实时同步,其中inotify用于监控文件系统事件,rsync是目前广泛使用的同步算法,其优点是只对文件不同的部分进行操作,所以其优势大大超过使用挂接文件系统的方式进行镜像同步。由金山的周洋开发完成,是目前使用较多的文件同步工具之一。该工具和其他的工具相比有如下优点:
- sersync是使用c++编写,由于只同步发生更改的文件,因此比其他同步工具更节约时间、带宽;
- 安装方便、配置简单;
- 使用多线程进行同步,能够保证多个服务器实时保持同步状态;
- 自带出错处理机制,通过失败队列对出错的文件重新出错,如果仍旧失败,则每10个小时对同步失败的文件重新同步;
- 自带crontab功能,只需在xml配置文件中开启,即可按您的要求,隔一段时间整体同步一次;
- 自带socket与http协议扩展,你可以方便的进行二次开发;
线程组线程是等待线程队列的守护线程,当队列中有数据的时候,线程组守护线程逐个唤醒,当队列中inotify事件交多的时候就会被全部唤醒一起工作。这样设计的目的是能够同时处理多个inotify事件,重发利用服务器的并发能力(核数*2+2)。
之所以称之为线程组线程,是因为每个线程在工作的时候,会根据服务器的数量建立子线程,子线程可以保证所有的文件与各个服务器同时同步,当要同步的文件较大的时候,这样设计可以保证各个远程服务器可以同时获得要同步的文件。
服务线程的作用有三个,首先是处理同步失败的文件,将这些文件
再次同步,对于再次同步失败的文件会生成rsync_fail_log.sh脚本,记录失败的事件。同时每隔10个小时执行脚本一次,同时清空脚本。服务
线程的第三个作用是crontab功能,可以每隔一定时间,将所有路径整体同步一次。
过滤队列的建立是为了过滤短时间内产生的重复的inotify信息,例如在删除文件夹得时候,inotify就会同时产生删除文件夹里的文件与删除文件夹
得事件,通过过滤队列当删除文件夹事件产生的时候,会将之前加入队列的删除文件的事件全部过滤掉,这样只产生一条事件减轻了同步的负担。同时对于修改文件
的操作的时候,会产生临时文件与重复操作。
配置文件说明:
下面做逐行的进行解释说明:
1、 <host hostip="localhost" port="8008"></host>
hostip与port是针对插件的保留字段,对于同步功能没有任何作用,保留默认即可。
2、filter文件过滤功能
对于sersync监控的文件,会默认过滤系统的临时文件(以“.”开头,以“~”结尾),除了这些文件外,可以自定义其他需要过滤的文件。
<filter start="true">
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="^info/*"></exclude>
<exclude expression="^static/*"></exclude>
<exclude expression="^APK/*"></exclude>
<exclude expression="^IOSIPA/*"></exclude>
</filter>
将start设置为 true,
在exclude标签中,填写正则表达式,默认给出两个例子分别是过滤以".gz"结尾的文件与过滤监控目录下的info路径(监控路径/info
/*),可以根据需要添加,但开启的时候,自己测试一下,正则表达式如果出现错误,控制台会有提示。相比较使用rsync
的exclude功能,被过滤的路径,不会加入监控,大大减少rsync的通讯量。
3、inotify监控参数设定(优化)
对于inotify监控参数可以进行设置,根据您项目的特点优化srsync。
<inotify>
<delete start="true"/>
<createFolder start="true"/>
<createFile start="false"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="true"/>
<modify start="true"/>
</inotify>
对于大多数应用,可以尝试把createFile(监控文件事件选项)设置为false来提高性能,减少 rsync通讯。因为拷贝文件到监控目录会产生create事件与close_write事件,所以如果关闭create事件,只监控文件拷贝结束时的事 件close_write,同样可以实现文件完整同步。
注意:强将createFolder保持为true,如果将createFolder设为false,则不会对产生的目录进行监控,该目录下的子文件与子目录也不会被监控。所以除非特殊需要,请开启。
默认情况下对创建文件(目录)事件与删除文件(目录)事件都进行监控,如果项目中不需要删除远程目标服务器的文件(目录),则可以将delete 参数设置为false,则不对删除事件进行监控。
4、失败日志脚步配置
<failLog path="/opt/sersync/log/rsync_fail_log.log" timeToExecute="60"/>
对于失败的传输,会进行重新传送,再次失败就会写入rsync_fail_log,然后每隔一段时间(timeToExecute进行设置)执行该脚本再次重新传送,然后清空该脚本。可以通过path来设置日志路径。
5、Crontab定期整体同步功能
<crontab start="false" schedule="24000"><!--600mins-->
<crontabfilter start="false">
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
crontab可以对监控路径与远程目标主机每隔一段时间进行一次整体同步,可能由于一些原因两次失败重传都失败了,这个时候如果开启了crontab功能,还可以进一步保证各个服务器文件一致,如果文件量比较大,crontab的时间间隔要设的大一些,否则可能增加通讯开销。schedule这个参数是设置crontab的时间间隔,默认是600分钟
如果开启了filter文件过滤功能,那么crontab整体同步也需要设置过滤,否则虽然实时同步的时候文件被过滤了,但crontab整体同步的时候如果不单独设置crontabfilter,还会将需过滤的文件同步到远程,crontab的过滤正则与filter过滤的不同,也给出了两个实例分别对应与过滤文件与目录。总之如果同时开启了filter与crontab,则要开启crontab的crontabfilter,并按示例设置使其与filter的过滤一一对应。
6、插件相关
<plugin start="false" name="command"/>
</sersync>
<plugin name="command">
<param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
<filter start="false">
<include expression="(.*)\.php"/>
<include expression="(.*)\.sh"/>
</filter>
</plugin>
<plugin name="socket">
<localpath watch="/opt/fileserver">
<deshost ip="192.168.100.160" port="8009"/>
</localpath>
</plugin>
<plugin name="refreshCDN">
<localpath watch="/data0/htdocs/cms.xoyo.com/site/">
<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
<sendurl base="http://pic.xoyo.com/cms"/>
<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
</localpath>
</plugin>
如上面的xml所示,其中plugin标签设置为true时候,在同步文件或路径到远程之后后,调用插件。通过name参数指定需要执行的插件。目前支持的有command refreshCDN socket http四种插件。http插件目前由于兼容性原因去除,以后会重新加入。
command插件当文件同步完成后,会调用command插件,如同步文件是test.php,则test.php文件在改动之后,调用rsync同步到远程服务器后,调用command插件,执行
/bin/sh test.php suffix>/dev/null 2>&1
如果suffix 设置了,则会放在inotify事件test.php之后
如果ignoreError为true,则会添加>/dev/null 2>&1
当然还可以设置command的filter,当filter为ture,include可以只对正则匹配到的文件,调用command。
刷新CDN插件“refreshCDN”,就在同步过程中将文件发送到目的服务器后刷新cdn接口。如果不想使用,则将start属性设为false即可。如果需要使用其他插件,则查看其他plugin标签,将插件名称改为 xml中其它插件的名称即可。
以下模块(refreshCDN http socket)可以单独使用,只需在命令行下使用-m 参数即可。如果需要作为插件与同步程序一起使用,见同步程序说明的插件配置。
该模块根据chinaCDN的协议,进行设计,当有文件产生的时候,就向cdn接口发送需要刷新的路径位置。刷新CDN模块需要配置的xml文件如下。
其中 localpath watch 是需要监控的目录。
cdnifo标签制定了cdn接口的域名,端口号,以及用户名与密码。
sendurl标签是需要刷新的url的前缀。
regexurl标签中的,regex属性为true时候,使用match属性的正则语句匹配inotify返回的路径信息,并将正则匹配到的部分作为url一部分,
举例:
如果产生文件事件为:/data0/htdoc/cms.88181.com/site/jx3.88181.com/image/a/123.txt
经过上面的match正则匹配后,最后刷新的路径是:
http://pic.88181.com/cms/jx3/a/123.txt;
如果regex属性为false,最后刷新的路径是
http://pic.88181.com/cms/jx3.88181.com/images/a/123.txt;