文件同步
1.功能描述
能够配置监控多个目录下文件变化;slave节点同步master节点的文件;新节点上线或者感知到master变化,slave节点要主动向master节点进行一次全量同步(rsyn实际传输也只是变化的部分);master节点启动inotify监控,感知到文件变化,将变化消息通过mqtt topic通知到slave节点;slave节点收到文件变化消息,发起向master节点的一次同步连接
2.依赖模块
njet.conf:
helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;
helper rsync modules/njt_helper_rsync_module.so conf/rsync.conf;
njet_ctrl.conf:
load_module modules/njt_http_ctrl_request_forward_module.so;
3.指令说明
rsync.conf 样例 :
{
"log_file": "logs/rsync.log", #指定日志输出文件
#可配置rsync 日志级别
"log_level": "info", #日志级别(如 debug、info、warn、error),控制日志详细程度 默认为 info
#监控目录列表(不支持文件),必须为绝对路径
"watch_dirs": [
{
"ignore_files": [
"1.txt", #排除所有1.txt文件
"tmp1/tmp11", #排除tmp1/tmp11目录
"tmp1/*.doc", #排除tmp1/下所有.doc结尾的文件
"tmp1/abc.*" #排除tmp1/下所有abc.开始的文件
],
"identifier": "dir_name1", #监控目录标识,用于标识不同集群节点目录对应关系
"prefix": "/a/b", #必须是dir路径开始的前缀路径
"dir": "/a/b/c" #必须是绝对路径
},
{
"identifier": "dir_name2", #监控目录标识,用于标识不同集群节点目录对应关系
"prefix": "/e", #必须是dir路径开始的前缀路径
"dir": "/e/f/g" #必须是绝对路径
}
]
}
字段层级 | 字段名 | 是否必须 | 作用/为什么要配 | 如果不配会怎样 |
---|---|---|---|---|
全局 | log_file | 是 | 指定 rsync 日志写到哪里 | 启动报错:找不到日志路径 |
全局 | log_level | 否 | 控制日志详细程度(debug/info/warn/error) | 缺省 info,可运行但无法按需调级别 |
顶层 | watch_dirs | 是 | 声明需要监控/同步的目录列表 | 没任务可做 |
单条目录 | dir | 是 | 被监控的绝对路径 | 找不到目录,直接失败 |
单条目录 | prefix | 是 | 去掉公共前缀,生成 rsync 的相对路径 | 路径层级错乱,远端收到错误路径 |
单条目录 | identifier | 是 | 集群内统一标识,用于多节点目录映射 | 节点间无法匹配同一逻辑目录,同步失败或重复 |
单条目录 | ignore_files | 否 | 排除文件/目录的 glob 规则(–exclude) | 不排除任何文件,全部同步 |
支持文件忽略配置(不参与同步)
- 能够配置全局过滤(文件或者目录,后缀匹配模式,比如过滤b.txt, 则所有路径(包含子目录)以b.txt结尾的都会被过滤掉)
- 过滤支持简单的前缀通配符过滤(比如*.txt, 则过滤所有以.txt类型的文件)
- 过滤支持简单的后缀通配符过滤(比如abc.*, 则过滤所有abc.开头的文件)
- 符合过滤规则的文件不会进行同步,也不会被删除
4.配置样例
具体配置如下:
njet.conf 样例(master 和backup 节点相同配置):
helper broker modules/njt_helper_broker_module.so conf/mqtt.conf; #注意:此处配置需要加上conf/mqtt.conf,因为rpm 和deb 包安装时是不带这个conf/mqtt.conf的
helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;
helper rsync modules/njt_helper_rsync_module.so conf/rsync.conf;
load_module modules/njt_http_split_clients_2_module.so;
load_module modules/njt_agent_dynlog_module.so;
load_module modules/njt_http_dyn_bwlist_module.so;
load_module modules/njt_dyn_ssl_module.so;
load_module modules/njt_http_vtsc_module.so;
load_module modules/njt_http_location_module.so;
load_module modules/njt_range_module.so;
load_module modules/njt_http_dyn_range_module.so;
cluster_name njet;
node_name node156;
worker_processes auto;
error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
access_log off;
server {
listen 8100;
location / {
root html;
}
}
}
stream {
server {
listen 238.255.253.251:5557 udp;
gossip zone=test:1m heartbeat_timeout=100ms nodeclean_timeout=1s local_ip=192.168.40.156 sync_port=8873 ctrl_port=8811 bridge_port=1884;
}
}
njet_ctrl.conf(master 和backup 节点相同配置):
load_module modules/njt_http_sendmsg_module.so;
load_module modules/njt_ctrl_config_api_module.so;
load_module modules/njt_helper_health_check_module.so;
load_module modules/njt_http_upstream_api_module.so;
load_module modules/njt_http_location_api_module.so;
load_module modules/njt_doc_module.so;
load_module modules/njt_http_ctrl_request_forward_module.so;
error_log logs/error_ctrl.log error;
events {
worker_connections 1024;
}
http {
dyn_kv_conf conf/ctrl_kv.conf;
include mime.types;
access_log off;
server {
listen 8811;
location / {
return 200 "njet control panel\n";
}
location /api {
dyn_module_api;
}
location /doc {
doc_api;
}
location / {
root /home/limin/test_bridge/html;
index upload.html;
}
location /cluster_forward {
internal;
proxy_connect_timeout 1s;
proxy_read_timeout 2s;
proxy_send_timeout 2s;
proxy_pass http://${cluster_master_ip}:${cluster_master_ctrl_port}$request_uri;
}
}
}
Location 的名称 /cluster_forward 目前在代码中做subrequest 时hardcode 了, 不能改成其它名称。
变量 | 说明 | 作用域 |
---|---|---|
cluster_master_ip | 集群主节点IP | HTTP |
cluster_master_ctrl_port | 集群主节点控制面监听端口 | HTTP |
该配置的作用:用户在从节点上请求修改配置,从节点将原样转发到集群主节点,然后主节点处理请求并同步变更到所有从节点
conf/ctrl_kv.conf (master 和backup 节点相同配置):
topic /gossip/#
rsync.conf(master 和backup 节点相同配置,identifier相同,prefix和dir 可以不相同,这样可以实现多个节点的不同目录实现监控):
{
"log_level": "debug",
"log_file": "logs/rsync.log",
"watch_dirs": [
{
"identifier": "rsync1",
"prefix": "/home/limin/test_bridge",
"dir": "/home/limin/test_bridge/apigw_data"
},
{
"identifier": "rsync2",
"prefix": "/home/limin/test_bridge",
"dir": "/home/limin/test_bridge/watch_dir"
},
{
"identifier": "rsync3",
"prefix": "/home/limin/test_bridge/data/",
"dir": "/home/limin/test_bridge/data/file_upload"
},
{
"ignore_files": [
"4.txt",
"tmp4/tmp3/tmp4/tmp5/tmp6/*.doc",
"tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc",
"tmp4/abc.*",
"tmp4/tmp44"
],
"identifier": "rsync1",
"prefix": "/home/limin/test_bridge",
"dir": "/home/limin/test_bridge/tmp4"
}
]
}
master节点mqtt配置(明文配置)
#全局log配置
log_dest file logs/mosquitto.log
log_type debug
log_type information
log_type error
log_type warning
log_type notice
#全局其他配置
autosave_interval 1
autosave_on_changes true
persistence true
allow_anonymous true #允许匿名访问,后面的unix socket listen需要
persistence_location /home/limin/test_bridge/data/ #持久化数据路径
listener 0 /home/limin/test_bridge/data/mosquitto.sock
#ip 地址 server
listener 1884 192.168.40.156
#master节点也要配置bridge(固定的名字bridge-backup),inactive一定设置,初始启动的时候实际不进行连接
connection bridge-backup inactive
address 192.168.40.156:1884 #配置bridge ip,此处配置为本节点ip即可,初始化配置使用
topic /dyn/# both 0
topic /ins/# both 0
backup节点mqtt配置(明文配置):
log_dest file logs/mosquitto.log
log_type debug
log_type information
log_type error
log_type warning
log_type notice
autosave_interval 1
autosave_on_changes true
persistence true
allow_anonymous true
persistence_location /home/limin/test_bridge/data/
listener 0 /home/limin/test_bridge/data/mosquitto.sock
listener 1884 192.168.40.145
connection bridge-backup inactive
address 192.168.40.145:1884
topic /dyn/# both 0
topic /ins/# both 0
master节点mqtt配置(ssl证书):
#全局log配置
log_dest file logs/mosquitto.log
log_type debug
log_type information
log_type error
log_type warning
log_type notice
#全局其他配置
autosave_interval 1
autosave_on_changes true
persistence true
allow_anonymous true #允许匿名访问,后面的unix socket listen需要
persistence_location /root/bug/njet1.0/data/ #持久化数据路径
#下面是unix socket 的指令组
listener 0 /root/bug/njet1.0/data/mosquitto.sock
#下面是ip 端口配置组,以及配置证书
listener 1883 192.168.40.158
cafile /root/bug/njet1.0/cert/mqtt_ca.crt
certfile /root/bug/njet1.0/cert/mqtt_server.crt #服务端证书
keyfile /root/bug/njet1.0/cert/mqtt_server.key
require_certificate true #listener级别配置
use_identity_as_username true #listener级别配置
#下面是bridge 桥接配置组以及桥接使用的配置证书(固定的名字bridge-backup)
#master节点也要配置bridge,inactive一定设置,初始启动的时候实际不进行连接
connection bridge-backup inactive
address 192.168.40.158:1883 #ip也配置为初始得master节点ip即可
topic /dyn/# both 0
topic /ins/# both 0
bridge_insecure true
bridge_cafile /root/bug/njet1.0/cert/mqtt_ca.crt
bridge_certfile /root/bug/njet1.0/cert/mqtt_client.crt #客户端证书
bridge_keyfile /root/bug/njet1.0/cert/mqtt_client.key
backup节点mqtt配置(ssl证书):
#全局log配置
log_dest file logs/mosquitto.log
log_type debug
log_type information
log_type error
log_type warning
log_type notice
#全局配置
autosave_interval 1
autosave_on_changes true
persistence true
allow_anonymous true #允许匿名访问,后面的unix socket listen需要
persistence_location /root/bug/njet1.0/data/ #持久化数据路径
#下面是unix socket
listener 0 /root/bug/njet1.0/data/mosquitto.sock
#下面是ip 端口配置组,以及配置证书
listener 1883 192.168.40.156
cafile /root/bug/njet1.0/cert/mqtt_ca.crt
certfile /root/bug/njet1.0/cert/mqtt_server.crt #服务端证书
keyfile /root/bug/njet1.0/cert/mqtt_server.key
require_certificate true #listener级别配置
use_identity_as_username true #listener级别配置
#下面是bridge 桥接配置组以及桥接使用的配置证书(固定的名字bridge-backup)
connection bridge-backup inactive
address 192.168.40.158:1883
topic /dyn/# both 0
topic /ins/# both 0
bridge_insecure true
bridge_cafile /root/bug/njet1.0/cert/mqtt_ca.crt
bridge_certfile /root/bug/njet1.0/cert/mqtt_client.crt #客户端证书
bridge_keyfile /root/bug/njet1.0/cert/mqtt_client.key
5.调用样例
5.1 查看连接状态:
按顺序分别启动158,156和145 节点的njet,158 作为主节点,156和145 作为backup 节点,所以156 和145 连接158的1884端口
在156机器上查看连接状态
[root@CDN156 njet]# sudo netstat -anpl|grep 1884
tcp 0 0 192.168.40.156:1884 0.0.0.0:* LISTEN 2031/njet: copilot
tcp 0 0 192.168.40.156:46008 192.168.40.158:1884 ESTABLISHED 2031/njet: copilot
在145机器上查看连接状态
limin@ldap:~/test_bridge$ sudo netstat -anpl|grep 1884
tcp 0 0 192.168.40.145:1884 0.0.0.0:* LISTEN 14232/njet: copilot
tcp 2385 0 192.168.40.145:56040 192.168.40.158:1884 ESTABLISHED 14232/njet: copilot
在158机器上查看连接状态
[njet@k8s-master158 test_bridge]$ sudo netstat -anpl|grep 1884
tcp 0 0 192.168.40.158:1884 0.0.0.0:* LISTEN 15545/njet: copilot
tcp 0 0 192.168.40.158:1884 192.168.40.156:46008 ESTABLISHED 15545/njet: copilot
tcp 0 0 192.168.40.158:1884 192.168.40.145:56844 ESTABLISHED 15545/njet: copilot
5.2 文件同步
158 作为主节点,156和145 作为backup 节点
在备节点156上传文件:
[limin@CDN156 test_bridge]$ curl -F "file=@/usr/local/njet/conf/njet.conf" http://192.168.40.156:8081/api/v1/upload
{"code":200,"file":"a02aa67e47b73c80ac60b4bc6e5c2a7c.dat"}
请求先转发到主节点158 上,在主节点的data 目录下有上传的文件
158:
njet@k8s-master158 test_bridge]$ ll data/file_upload
总用量 40
-rw-------. 1 njet njet 1203 7月 2 15:05 a02aa67e47b73c80ac60b4bc6e5c2a7c.dat
请求由主节点同步到备节点156和145 上,在备节点的data 目录下同样有上传的文件:
156:
[limin@CDN156 test_bridge]$ ll data/file_upload
总用量 52
-rw------- 1 limin limin 1203 7月 2 15:05 a02aa67e47b73c80ac60b4bc6e5c2a7c.dat
145:
limin@ldap:~/test_bridge$ ll data/file_upload
-rw------- 1 limin limin 1203 Jul 2 15:05 a02aa67e47b73c80ac60b4bc6e5c2a7c.dat
5.3 忽略文件同步
主节点:
[limin@CDN156 test_bridge]$ tree tmp4
tmp4
├── 4.txt #符合规则 4.txt
├── abc.jpg #符合规则 tmp4/abc.*
├── abc.png #符合规则 tmp4/abc.*
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ ├── 1.doc #符合规则 tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc
│ ├── 2.doc #符合规则 tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc
│ ├── 3.doc #符合规则 tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc
│ ├── 4.doc #符合规则 tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc
│ ├── 4.txt #符合规则4.txt
│ ├── 5.doc #符合规则 tmp4/tmp22/tmp33/tmp44/tmp55/tmp66/*.doc
│ └── 5.txt
│── tmp3
│ └── tmp4
│ └── tmp5
│ └── tmp6
│ ├── 1.doc #符合规则 tmp4/tmp3/tmp4/tmp5/tmp6/*.doc
│ ├── 2.doc #符合规则 tmp4/tmp3/tmp4/tmp5/tmp6/*.doc
│ ├── 3.doc #符合规则 tmp4/tmp3/tmp4/tmp5/tmp6/*.doc
│ └── 4.txt #符合规则4.txt
└── tmp44 #符合规则 tmp4/tmp44
├── 1.txt
└── 4.txt
从节点145:
limin@ldap:~/test_bridge$ tree tmp4
tmp4
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6
从节点158:
[njet@k8s-master158 test_bridge]$ tree tmp4
tmp4
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6
Slave 节点添加master 节点不存在的文件,重新启动同步后,该文件由于不在master中存在,会自动删除掉:
limin@ldap:~/test_bridge$ mkdir tmp4/156.txt
limin@ldap:~/test_bridge$ tree tmp4
tmp4
├── 156.txt
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6
Slave 节点重启后:
limin@ldap:~/test_bridge$ tree tmp4
tmp4
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6
添加符合规则的文件,tmp1/1.txt, 重新启动同步后,由于符合过滤规则,该文件不会被同步,也不会被删除
vim tmp4/4.txt
添加后,从节点:
limin@ldap:~/test_bridge$ tree tmp4
tmp4
├── 4.txt
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6
Slave 节点重启后,由于符合过滤规则,该文件不会被同步,也不会被删除:
limin@ldap:~/test_bridge$ tree tmp4
tmp4
├── 4.txt #仍然存在
├── a.jpg
├── a.png
├── tmp22
│ └── tmp33
│ └── tmp44
│ └── tmp55
│ └── tmp66
│ └── 5.txt
└── tmp3
└── tmp4
└── tmp5
└── tmp6