一、Inotify介绍:
Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除、读、写和卸载操作等。您还可以跟踪活动的源头和目标等细节。
使用 inotify 很简单:创建一个文件描述符,附加一个或多个监视器(一个监视器 是一个路径和一组事件),然后使用 read 方法从描述符获取事件。read 并不会用光整个周期,它在事件发生之前是被阻塞的。
内核版本不低于 2.6.13,系统就支持 inotify。 同时可以查看内核参数
[root@localhost inotify]# cd /proc/sys/fs/inotify/
[root@localhost 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
[root@localhost 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;
三、inotify及sersync压力测试
环境介绍:
172.16.171.100 测试客户机、nfs客户端
172.16.171.110 inotify、sersync端 、nfs服务端
172.16.171.120 rsync服务端
均为CentOS release 6.6 64位系统,4核2G
1、测试脚本介绍:
[root@openstack-nova test]# ll
total 61680
-rw-r--r--. 1 root root 1024000 Aug 30 11:27 1000k.txt
-rw-r--r--. 1 root root 102400 Aug 30 11:27 100k.txt
-rw-r--r--. 1 root root 10240 Aug 30 10:28 10k.txt
-rw-r--r--. 1 root root 10240000 Aug 30 11:39 10m.txt
-rw-r--r--. 1 root root 512000 Aug 30 11:27 500k.txt
-rw-r--r--. 1 root root 51200 Aug 30 10:28 50k.txt
-rw-r--r--. 1 root root 51200000 Aug 30 11:39 50m.txt
-rwxr-xr-x. 1 root root 313 Aug 30 11:09 test.sh
cat test.sh
#!/bin/sh
count=20
a=1
name=$1
num=$2
file=$3
while [ "$a" -le "$num" ]
do
for ((i=1;i<=$count;i++))
do
[ ! -e /cms/$name/$i ] && /bin/mkdir /cms/$name/$i
/bin/cp ${file}.txt /cms/$name/$i/${file}_`echo $(date)$RANDOM | md5sum | cut -c 1-8`.txt
done
a=`expr $a + 1`
sleep 1
done
2、针对sersync目录进行10K、500K、1000K、10M测试,测试命令如下:
sh test.sh sersync 20 10k
sh test.sh sersync 20 500k
sh test.sh sersync 20 1000k
sh test.sh sersync 20 10m
172.16.171.110(sersync端)和172.16.171.120(rsync)端查看统计命令:
while true; do tree sersync/ | wc -l; sleep 1 ;done | tee -a sersync.log
结果如下:
id | s(10k) | r(10k) | s(500k) | r(500k) | s(1m) | r(1m) | s(10m) | r(10m) |
1 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
2 | 43 | 36 | 43 | 39 | 43 | 14 | 21 | 11 |
3 | 63 | 53 | 63 | 54 | 43 | 43 | 43 | 30 |
4 | 78 | 63 | 78 | 63 | 63 | 63 | 45 | 43 |
5 | 83 | 83 | 83 | 83 | 83 | 83 | 59 | 51 |
6 | 103 | 103 | 103 | 103 | 103 | 98 | 63 | 63 |
7 | 123 | 123 | 123 | 123 | 123 | 110 | 70 | 64 |
8 | 143 | 143 | 143 | 143 | 125 | 123 | 74 | 69 |
9 | 163 | 153 | 163 | 153 | 143 | 143 | 74 | 71 |
10 | 182 | 163 | 172 | 163 | 163 | 163 | 75 | 73 |
11 | 183 | 183 | 183 | 183 | 183 | 183 | 77 | 73 |
12 | 203 | 203 | 203 | 203 | 203 | 193 | 77 | 76 |
13 | 223 | 223 | 223 | 223 | 214 | 203 | 78 | 77 |
14 | 243 | 243 | 243 | 235 | 223 | 223 | 80 | 83 |
15 | 263 | 253 | 259 | 247 | 243 | 243 | 82 | 83 |
16 | 283 | 263 | 263 | 263 | 263 | 258 | 83 | 84 |
17 | 284 | 283 | 283 | 283 | 281 | 266 | 88 | 85 |
18 | 303 | 303 | 303 | 303 | 283 | 283 | 90 | 88 |
19 | 323 | 323 | 323 | 323 | 303 | 303 | 94 | 90 |
20 | 343 | 343 | 343 | 333 | 323 | 323 | 99 | 95 |
21 | 363 | 359 | 348 | 343 | 343 | 333 | 100 | 96 |
22 | 383 | 372 | 363 | 363 | 352 | 343 | 100 | 99 |
23 | 392 | 383 | 383 | 383 | 363 | 363 | 102 | 100 |
24 | 403 | 403 | 403 | 403 | 383 | 383 | 103 | 103 |
25 | 423 | 423 | 423 | 416 | 403 | 399 | 109 | 103 |
26 | 423 | 421 | 408 | 112 | 106 | |||
27 | 423 | 423 | 115 | 107 |
从统计结束来看:
在172.16.171.110上直接生成文件
文件大小在1M之内的小文件,同步效率在秒级。
10M的大文件sersync端使用了126秒,rsync端同步完成共使用了161秒。
在172.16.171.100上以nfs挂载,并批量生成文件进行测试。
10K文件使用28-29秒,500K文件使用45秒,1M文件使用70秒,10M文件使用279秒,同步完成使用281秒
3、针对inotify目录进行10K、500K、1000K、10M测试,测试命令如下:
sh test.sh inotify 20 10k
sh test.sh inotify 20 500k
sh test.sh inotify 20 1000k
sh test.sh inotify 20 10m
172.16.171.110(inotify端)和172.16.171.120(rsync)端查看统计命令:
while true; do tree inotify/ | wc -l; sleep 1 ;done | tee -a inotify.log
结果如下:
id | s(10k) | r(10k) | s(500k) | r(500k) | s(1m) | r(1m) | s(10m) | r(10m) |
1 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
2 | 43 | 43 | 43 | 43 | 43 | 37 | 43 | 8 |
3 | 63 | 63 | 63 | 56 | 63 | 54 | 48 | 29 |
4 | 83 | 82 | 80 | 63 | 83 | 66 | 63 | 32 |
5 | 83 | 83 | 83 | 83 | 84 | 83 | 77 | 37 |
6 | 103 | 103 | 103 | 103 | 103 | 103 | 80 | 42 |
7 | 123 | 123 | 123 | 123 | 123 | 123 | 83 | 43 |
8 | 143 | 143 | 143 | 143 | 143 | 137 | 103 | 43 |
9 | 163 | 163 | 163 | 156 | 163 | 150 | 110 | 44 |
10 | 183 | 172 | 171 | 166 | 176 | 166 | 115 | 47 |
11 | 186 | 183 | 183 | 183 | 183 | 183 | 117 | 47 |
12 | 203 | 203 | 203 | 203 | 203 | 203 | 123 | 47 |
13 | 223 | 223 | 223 | 223 | 223 | 223 | 123 | 48 |
14 | 243 | 243 | 243 | 241 | 243 | 236 | 124 | 54 |
15 | 263 | 263 | 263 | 247 | 259 | 245 | 125 | 58 |
16 | 283 | 271 | 264 | 263 | 263 | 263 | 136 | 63 |
17 | 288 | 286 | 283 | 283 | 283 | 283 | 136 | 64 |
18 | 303 | 303 | 303 | 303 | 303 | 301 | 139 | 64 |
19 | 323 | 323 | 323 | 323 | 323 | 313 | 140 | 64 |
20 | 343 | 343 | 343 | 336 | 333 | 323 | 143 | 64 |
21 | 363 | 363 | 355 | 346 | 343 | 343 | 143 | 66 |
22 | 383 | 383 | 363 | 363 | 363 | 363 | 143 | 71 |
23 | 394 | 393 | 383 | 383 | 383 | 378 | 150 | 72 |
24 | 403 | 403 | 403 | 403 | 403 | 391 | 158 | 72 |
25 | 423 | 423 | 423 | 421 | 414 | 405 | 160 | 72 |
26 | 423 | 423 | 423 | 163 | 72 |
从统计结束来看:
在172.16.171.110上直接生成文件
文件大小在1M之内的小文件,同步效率在秒级,和sersync效率不相上下。
10M的大文件inotify端使用了103秒,rsync端同步完成使用了410秒,要远远超过sersync。
在172.16.171.100上以nfs挂载,并批量生成文件进行测试。
10K文件使用28-29秒,500K文件使用41秒,1M文件使用50秒,10M文件使用210秒,同步完成使用216秒
总结:当并发大量生成大文件时,sersync因多线程效率会高点,当并发量一般时,感觉inotify效率更高点。