基于Inotify的文件监控,并实现rsync同步大量静态文件的解决方案,版本不断升级,目标“一台机器只运行一个实例,且只需要修改配置文件即可完成部署”
经过测试百万级文件夹监控初始化大概需要40mins,而且cpu及内存利用率都在可接受范围内。
当你有会生成大量静态文件,又使用了负载均衡,要把生产环境下的大量静态文件同步到多个web节点上,rsync是一个不错的同步选择,但你可能也遇到了和我一样的问题:rsync同步大量文件的耗时太长,和目录机的文件对比是一个不小的开销(原因大家可以商讨),而且很多时候可能只是更新的少量文件。这种情况下可能就让你的系统发布变的很慢。 这时本解决方案应用而生,采用基于linux内核的文件触发式系统(Inotify)并采用缓存更新队列,最后选择易于开发的Nodejs进行开发,并结合crontab模拟出小时间片断处理间隔,让同步方案可以在很小的时间间隔内完成同步,很大程度上保证了生成的静态文件同步到多个web节点的实时性。
- 操作系统 linux内核2.6.13(Inotify要求)
- nodejs (目前测试版本为0.10.7)
- rsync
- run.js为运行主程序,在crontab里配置定时任务(文件锁),并在run.js里多次处理,模拟出小时间片断处理。
- run.js首先采用文件锁机制运行监控
memoryWatcher.js
,小时间片断处理内存数据(由Inotify监控到的更改文件)并完成同步
config/index.js
为主配置文件- 详细配置说明请参考:
config/index.js
内容 config/callback.js
为监控文件更新并调用配置文件里的回调函数(可以是外部脚本)
- 查看是否支持inotify
ls /proc/sys/fs/inotify
- 查看操作系统位数(下载nodejs时要和位数对应)
getconf LONG_BIT
部署一定要保证关键文件及文件夹的读写权限
- 日志目录(config.logPath)
- 运行程序文件锁(crontab里的设置)
- 临时文件存放位置(config.copyToPath)
- rsync采用ssh认证码机制,一定要确保运行程序用户ssh已经认证
-
运行监控并实时同步
*/1 * * * * /usr/bin/node /tonny/nodejs/watcher/run.js > /tonny/log/crontab_run.log 2>&1
-
运行监控并调用配置回调
*/1 * * * * /usr/bin/flock -xn /var/run/watcherCallback.lock -c 'nohup /usr/local/bin/node /tonny/nodejs/watcherCallback.js >> /tonny/log/watcher/crontab_callback.log 2>&1 &'
confInotify.sh
自动写inotify的配置readdir.sh
遍历目录stopRun.sh
强制停run.js
的相关进程stopWatcher.sh
强制停memoryWatcher.js
的相关进程tryRestart.sh
目标机上定时检测是不是需要重启,强制停run.js
和memoryWatcher.js
的相关进程udateSource.sh
把源码同步到指定的部署机上tongji/logPath.js
输出配置文件里的日志目录tongji/isDeal.sh
查看监控目录下的文件的物理更新时间,监控到的时间及处理时间
- make: g++: Command not found
解决方案:apt-get install g++
-
无法创建监控
/proc/sys/fs/inotify/max_queued_events
/proc/sys/fs/inotify/max_user_watches 默认设置值太小
解决方案:用root用法配置crontab*/1 * * * * /home/sam/nodejs/watcher/shell/confInotify.sh
-
run.js一直处于运行状态
localhost不是所有电脑都有配置,可以用wget或curl模拟抓包看到效果,一直在重复连接
解决方案:配置config.host为'127.0.0.1' -
同步的时候一直报错(rsyncErr_日期.log)
解决方案:手动运行rsync命令,确定rsync运行正常;确保config/index.js
里rsync
配置项里的user
配置正常rsync.user在监控用户(crontab运行用户)和同步用户(rsync同步用户)不是同一个的时候设置【当两个用户不同时,监控用户需要有su到同步用户的权限】
node tool/getConfigFromFile.js
会把config/getConfigFromFile.js
里配置的shell文件提取在config
目录下生成
一个autoIndex.json
文件,config/index.js
配置文件会自动引用这个文件
此工具可文件其它人员进行维护,重新生成完后再调用node memoryWatcher.js reload
让监控进行重新配置即可
用户也可以用此工具快速地和现在用的rsync的shell脚本保持同步(可重新配置)
当shell文件有模糊配置的内容,如:
rsync -Wp /a/b*.shtml test@localhost:/a/
,这时tool/getConfigFromFile.js
会把带*
的内容过滤并输出用于提示用户,于此同时,程序会自动寻找一个文件名加.1
的特殊文件(原来文件为a.sh
,会去寻找a.sh.1
),这 里面要求有正确的配置,方便我的的脚本内容和监控同步保持一致。
addPathAPI.js给外部提供临时的更新文件目录的接口,用法如下:
node addPathAPI.js -f '/temp/data.txt' '/temp/data.txt1'
或 node addPathAPI.js -p "/a/b" "/a/1.txt|true"
a/b
表示目录
a/b|true
表示文件
文件内容格式(单条信息用,
号分隔),如:a/b,a/b/1|true