NiFi 起不来、登不上、节点被挤掉:一份按日志定位的排错清单
这是「NiFi 生产集群」系列的第 5 篇,也是这套环境从 2022 年上线到 2026 年,所有"救火"记录的汇总。
上一篇:FTP→HDFS 与 CSV→Parquet,附坏数据、漏文件与双写 下一篇:NiFi 集群长期运维:并发线程、content 仓库、日志与漏洞面
这一篇按"症状 → 日志关键字 → 根因 → 处置"组织。建议收藏当手册用:出问题时不用从头读,直接按报错里的关键字搜。
0. 先按这个顺序定位
NiFi 的报错有个特点:表层症状和根因往往隔了两三层。UI 打不开,可能是证书、可能是授权、可能是 ZK、也可能是 JVM 堆太小。先按下面的顺序排除,比乱翻日志快:
不在
在
不通
通
证书
登录失败
空白或403
超时或500
打不开/起不来
进程还在?
看 logs/nifi-app.log 最后 100 行
以及 nifi-bootstrap.log
9443 端口通?
看 Jetty 启动日志 / 端口占用
浏览器报错类型
keystore / truststore / CN
Kerberos / krb5.conf / 身份映射
authorizer / users.xml
JVM 堆 / 集群通信 / primary 负载
按关键字查下面章节
先记住三个"一定先看"的文件:
tail -200 /opt/nifi/logs/nifi-app.log # 主日志,启动失败看这里
tail -100 /opt/nifi/logs/nifi-user.log # 登录、授权失败看这里
tail -50 /opt/nifi/logs/nifi-bootstrap.log # 进程级失败(起不来、web server 没起来)看这里
0.1 六族分类:先判断是"哪一类身份错了"
几年下来我把这些故障归成六族,先归类再查细节,能省掉一半时间:
| 族 | 典型关键字 | 本质 | 本篇章节 |
|---|---|---|---|
| 文件族 | UninheritableFlowException、FlowSynchronizationException、partially updated | 节点本地的 flow 和集群不一致 | 1 |
| 配置族 | Invalid nifi.web.https configuration、Remote input HTTPS、BindException | nifi.properties / 端口写错 | 2 |
| 认证族 | Cannot locate KDC、Clock skew、Pre-authentication | Kerberos 层 | 3 |
| 节点身份族 | is already connected、not authorized to join the cluster | 节点身份重复或白名单缺失 | 4、5 |
| 容量族 | No space left、archive file size constraints、GC overhead limit | 磁盘 / 内存不够 | 10、11 |
| 主机族 | UnknownHostException、Permission denied(本地文件)、Socket closed | 主机侧的 hosts / 属主 / 内存 | 12、13 |
一个经验:只要日志里出现"身份"两个字相关的报错(节点身份、证书 DN、用户主体、flow 版本),就说明这台机器在集群眼里"是另一个人"或者"是另一个版本的自己"。这类问题的共同点是——日志不会告诉你哪一行错了,只会说"连不上""未授权""不能继承" 。
0.2 动手前先保留现场
排到一半最怕的事:一着急把 flow.xml.gz 删了,问题没解决,现场也没了。所以第一步永远是:
# 1) 打包日志和时间线(出了问题先做这个,30 秒)
tar czf /tmp/nifi-logs-$(date +%H%M).tar.gz -C /opt/nifi/logs .
# 2) 记下当前状态:进程、端口、节点在集群里的角色
ps -ef | grep -i nifi | grep -v grep
ss -lntp | grep -E '9443|11443|6342|10443'
grep -E 'nifi.cluster.is.node|nifi.cluster.node.address|nifi.state.management.embedded.zookeeper.start' /opt/nifi/conf/nifi.properties
先备份再动手,这条在删 flow 文件那一节尤其重要(见 1.4)。
1. 文件族:UninheritableFlowException 与其他三种 flow 报错
这是 25 台规模下最常见的一类,也是唯一一类大概率能靠删两个文件解决的。它值得放在第一位讲。
1.1 四种报错,同一件事
| 报错 | 完整片段 | 说明 |
|---|---|---|
| 本地 flow 与集群不同 | org.apache.nifi.controller.UninheritableFlowException: Failed to connect node to cluster because local flow is different than cluster flow. | 节点以为自己还是旧的 flow |
| 本地 flow 只更新了一半 | FlowSynchronizationException: Failed to connect node to cluster because local flow controller partially updated. Administrator should disconnect node and review flow for corruption. | 同步过程中断,本地 flow 是"半成品" |
| 集群 flow 无法被继承 | Proposed flow is not inheritable by the flow controller and cannot completely replace the current flow due to: Inheriting cluster's flow would mean removing connection with ID ... | 集群要下发的 flow 会删掉本地一条连接 |
| 不能删这个进程组 | java.lang.IllegalStateException: Cannot delete Process Group because OutPut Port 3f903d5e-... has at least one outgoing connection to a component outside of the Process Group. Delete this connection first | 拓扑结构冲突,通常跟在上面三条后面 |
同一时间,nifi-bootstrap.log 里往往还有一句看起来毫无关系的:
nifi.StdErr Failed to start web server: Already closed or has not been started
这句是结果不是原因:flow 没加载成功,Controller 没起来,Jetty 自然也就没起来。别去查 9443 端口。
1.2 根因
NiFi 集群的 flow 以 primary 节点为准,向下同步给其他节点。节点启动时会问一句"我这台本地的 flow 和集群的一样吗",三种情况会答"不一样":
- 节点离线期间集群改过 flow。停了三天,期间别人加了个处理器,本地的
flow.xml.gz还停在三天前。 - 节点在同步过程中被强杀。同步写到一半进程没了,本地留下一个"半个 flow",这就是
partially updated。 - 这台机器本来就是从别处拷过来的(整包拷贝),它自带的 flow 和当前集群没有任何关系。
1.3 处置:停服务 → 删两个文件 → 重启
# 1) 先停,必须先停
cd /opt/nifi/bin
sh nifi.sh stop
sh nifi.sh status # 确认真的停了,别在运行中删文件
# 2) 删掉本地 flow 缓存
cd /opt/nifi/conf
rm -rf flow.xml.gz
rm -rf flow.json.gz
# 3) 重启,节点会向 primary 重新拉一份 flow
cd /opt/nifi/bin
sh nifi.sh restart
启动后看日志,正常的顺序是:Flow Service started → Node connected → 集群页面里这台从 CONNECTING 变 ACTIVE。
为什么必须先停再删:NiFi 运行时会周期性地把内存里的 flow 写回 flow.xml.gz/flow.json.gz。你在它跑着的时候删,它几秒后又给你写回去一份同样坏的,等于白删——而且你会以为是"删了没用"。
1.4 什么时候不能删
primary 节点不能删。primary 的 flow 就是集群的权威版本,删了等于把整张数据流删掉,其他节点会跟着同步成空的。
删之前确认两件事:
# 1) 这台是不是 primary?(集群页面看节点列表,主节点有标记;或看日志)
grep -i 'primary' /opt/nifi/logs/nifi-app.log | tail -5
# 2) 最近有没有导出过 template?(跨集群恢复只认 template)
ls -lt /opt/nifi/conf/templates/ 2>/dev/null | head
单机模式(nifi.cluster.is.node=false)下同样不能删。这种环境里 flow.xml.gz 是唯一的数据流存储,删掉就是从零开始,只能靠之前导出的 template 重建。
1.5 预防
- 变更窗口内不要单独重启某一台。集群在改 flow 的时候重启节点,就是主动制造
partially updated。 - 每次大改动前导出 template(第 2 篇 3.1 有讲);
flow.json.gz顺手也进备份。 - 扩容/换证书这类需要长时间停机的操作,先停全部流程、再停节点(第 2 篇"扩容前,先把流程全停")。
2. 配置族:能起来但起不来
2.1 Invalid nifi.web.https configuration in nifi.properties
现象:nifi 起不来,启动后 1 分钟内自动挂掉。
日志:
java.lang.IllegalStateException: Invalid nifi.web.https configuration in nifi.properties
at org.apache.nifi.web.server.connector.FrameworkServerConnectorFactory.<init>(...)
Caused by: org.apache.nifi.security.util.TlsException: The truststore properties are not valid
at org.apache.nifi.security.util.SslContextFactory.getTrustManagers(...)
根因:开了 HTTPS(nifi.web.https.port 有值),但 nifi.security.truststore 路径/类型/口令任一为空或不对。
处置:两种方向,二选一。
A. 要 HTTPS(生产必须):把 nifi.properties 里这 7 项补齐,路径指向真实存在的 jks:
nifi.security.keystore=./conf/keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=<KEYSTORE_PASS>
nifi.security.keyPasswd=<KEYSTORE_PASS>
nifi.security.truststore=./conf/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=<KEYSTORE_PASS>
B. 只是本地试玩,不要 HTTPS:把上面 7 项全部置空,同时把 nifi.web.https.port 也置空、只留 nifi.web.http.port,重启即可。
注意:NiFi 1.15.3 之后,新建安全集群可以不用手工填这些值(UI 向导或 toolkit 会生成)。但从旧版本升级上来的实例仍然要求手工配齐,别被版本说明误导。
另一个隐蔽点:
nifi.security.keystorePasswd和nifi.security.keyPasswd是两个属性,很多模板里只写了一个。只写 keystore 口令不写 key 口令,某些版本的 JDK 会拒绝加载密钥。
2.2 Remote input HTTPS is enabled but nifi.web.https.port is not specified
现象:服务能起来,但前台打不开;或者改了 HTTP 之后启动直接报错。
日志:
Caused by: java.lang.RuntimeException: Remote input HTTPS is enabled but nifi.web.https.port is not specified.
at org.apache.nifi.util.NiFiProperties.getRemoteInputHttpPort(NiFiProperties.java:596)
at org.apache.nifi.controller.FlowController.<init>(FlowController.java:585)
根因:nifi.remote.input.secure=true(站点到站点走 HTTPS)时,NiFi 会校验 nifi.web.https.port 必须有值。你把 HTTPS 端口清了、只留 HTTP,矛盾就出来了。
处置:三种组合,别混。
| 场景 | remote.input.secure | web.https.port | remote.input.http.enabled |
|---|---|---|---|
| 全 HTTPS(生产) | true | 9443 | true |
| 全 HTTP(仅内网测试) | false | 空 | true |
| 不启用 HTTP 形式的 S2S | true | 9443 | false |
最常见的错法是"想退回 HTTP",只改了 nifi.web.*,忘了 nifi.remote.input.secure 还是 true。
2.3 BindException: Cannot assign requested address
现象:节点起不来,或者 ZK 起不来;日志里是一句很短的绑定失败。
日志:
Exception while listening to address nifi-node-07.example.com:3888,
java.net.BindException: Cannot assign requested address
根因:端口或者地址绑不上,三种可能:
- 端口被占了。ZK 的 3888 最常见——同一台机器上跑了别的 ZK,或者上次的进程没死干净。
server.N里写的主机名在本机解析不到。ZK 只会尝试绑定配置里写的那几个地址,hosts 里没有这个名字,就Cannot assign requested address。nifi.cluster.node.address写的主机名和本机实际主机名不一致,集群协议端口绑不上。
处置:
# 先看端口被谁占了
ss -lntp | grep -E '3888|2888|22181'
# 再看名字能不能解析
getent hosts nifi-node-01.example.com
# 三个 zk 节点的 myid 必须唯一,且和 server.N 对应
cat /opt/nifi/state/zookeeper/myid
grep '^server.' /opt/nifi/conf/zookeeper.properties
改完端口,别忘了 nifi.zookeeper.connect.string 要全集群同步改一遍,否则一半节点还在连旧端口。ZK 配置的细节在第 2 篇 3.5.1 节。
2.4 systemctl 托管 NiFi:握手失败和 6342 断开的真凶
这一条独立成节,因为它长得完全像证书问题,但证书一点问题都没有。
现象(一次集中爆发):
- 集群前台查询不正常,节点状态在 Connected / Not connected 之间抖;
- 节点间复制请求失败:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Failed to replicate request GET /nifi-api/flow/current-user ... to nifi-node-11.example.com:9443
- 负载均衡通道异常:
ConnectionLoadBalanceServer Failed to communicate over Channel /nifi-node-11.example.com:6342::...
java.net.SocketException: Socket closed
- 停止时补一句:
Controller hasn't terminated properly... Might need to kill the program manually.
排查:异常集中在一台节点上;查它的启动方式,发现是用 systemctl start nifi 拉起的(/usr/lib/systemd/system/nifi.service,里面带 Restart=always)。做了一次对照:
| 启动方式 | 结果 |
|---|---|
systemctl start nifi | 前台查询异常复现,节点状态抖动 |
/opt/nifi/bin/nifi.sh start | 前台恢复正常,节点全部 Connected |
根因:先别急着把它归成"systemd 有 bug"。合理的解释是启动环境不一致:nifi.sh 会读 conf/bootstrap.conf 并设置一套环境(JAVA_HOME、ulimit、pid 文件、日志重定向),systemd 走的是另一套(Environment=、KillMode=、TimeoutStopSec=);再加上 Restart=always,你在执行 nifi.sh stop 的时候 systemd 会把进程又拉起来,形成"半启动半停止"的抖动——握手失败和 6342 断开都是抖动期间的表象。
处置:
systemctl stop nifi
systemctl disable nifi
systemctl mask nifi # 防止被别的依赖或运维脚本再拉起来
/opt/nifi/bin/nifi.sh start
判断方法:
systemctl is-enabled nifi # enabled 就是有人在托管
ps -o cmd= -p $(pgrep -f 'nifi.Bootstrap' | head -1)
systemctl show nifi -p Restart,KillMode,TimeoutStopSec
如果确实必须用 systemd 托管:先把 nifi.sh 与 service 文件的环境差异对齐(JAVA_HOME、ulimit -n、LimitNOFILE、KillMode=process、TimeoutStopSec 放大到能优雅停机),在测试集群灰度通过后再上生产。不要在生产上边试边改。
3. 认证族:登不上
3.1 一张表看完 Kerberos 报错
| 日志关键字 | 根因 | 处置 |
|---|---|---|
Clock skew too great | 节点时间偏差 > 5 分钟 | chronyc sources -v,修时间同步 |
Server not found in Kerberos database | 主体名 / realm 写错,或 KDC 里没这个主体 | kadmin.local -q "listprincs" 核对 |
Pre-authentication information was invalid | 密码错 | 重设主体密码 |
GSS initiate failed / No valid credentials | keytab 路径 / 权限 / keytab 与主体不匹配 | kinit -kt <keytab> <principal> 手工验证 |
Cannot locate KDC | krb5.conf 丢了 realm/KDC 配置,或被别的文件覆盖 | 见 3.2,这是最凶的一个 |
| 登录页一直转圈 | Kerberos 认证成功但 users.xml 里没这个身份 | 见 7.1 |
手工验证 keytab 的标准三步:
klist -k /home/nifi/nifi.keytab # 看 keytab 里到底有哪些主体
kinit -kt /home/nifi/nifi.keytab nifi/nifi@EXAMPLE.COM
klist # 看票据是否拿到、realm 对不对
3.2 Cannot locate KDC:一个配置文件如何把整个集群拖下水
这是两年里我见过破坏力最大的单点故障,值得完整复盘一次。
现象(按时间顺序):
- 平台告警:某节点
/opt挂载点使用率 100%,触发阻断告警。 - 业务反馈:NiFi 集群登录不了。
- UI 提示:
The supplied username and password are not valid.——看起来像密码错了,其实不是。 - 后台:
nifi-app.log增长速度异常,几分钟就把/opt写满;日志里刷的是:
Caused by: sun.security.krb5.KrbException: Cannot locate KDC
java.lang.SecurityException: Cannot locate KDC
紧接着是大量 FlowFile 冲突、处理线程中断的日志(因为磁盘满了,什么也写不下去)。
根因链:
/etc/krb5.conf 被覆盖(少了 realm 与 KDC 地址)
↓
NiFi 无法向 KDC 认证,每次登录/每次票据续期都失败
↓
失败重试 + 每条都写 ERROR 堆栈 → 日志暴涨
↓
/opt 被写满 → 磁盘满 → NiFi 所有写操作失败 → 登录彻底不可用
注意这条链上的因果很容易看错:磁盘满不是根因,是结果。如果只清磁盘,半小时后还会满。
处置:
# 1) 先从一台正常节点取一份正确的 krb5.conf
scp nifi-node-01:/etc/krb5.conf /tmp/krb5.conf.good
diff /tmp/krb5.conf.good /etc/krb5.conf # 看清楚少的是什么
# 2) 全量比对,确认到底几台被改了
ansible -m shell -a 'md5sum /etc/krb5.conf' nifi -o
# 3) 回滚(copy 带 backup=yes,出问题还能翻回去)
ansible -b -m copy \
-a 'src=/tmp/krb5.conf.good dest=/etc/krb5.conf owner=root group=root mode=0644 backup=yes' nifi
# 4) 清掉被日志打满的目录,再确认认证
ansible -m shell -a 'df -h /opt' nifi -o
三条经验:
krb5.conf是集群里最脆的文件。它不属于 NiFi,任何装了 hadoop 客户端、任何配置管理脚本、任何人工"统一环境"的动作都可能覆盖它。我们后来把它和core-site.xml、hdfs-site.xml一起纳入了 md5 巡检。- 登录页说"用户名密码无效"时,先看 KDC 通不通,再看密码对不对。
kinit一次就知道答案。 - 日志速率本身要监控。正常几百行/分钟,故障时几万行/分钟;
/opt一定要单独看容量(第 6 篇有日志治理的配置)。
3.3 登录页报"用户名密码无效"的三层原因
这个提示是 NiFi 最会误导人的一句话,它对应三种完全不同的原因:
| 层 | 真实原因 | 怎么验证 |
|---|---|---|
| KDC | krb5.conf 错、KDC 不可达、时间偏差 | kinit <principal> 手工试 |
| 主体 | 主体口令被 -randkey 随机化了(用 xst 导 keytab 时没加 -norandkey) | kadmin.local -q "cpw <principal>" 重设已知口令 |
| 授权 | 认证过了,但 users.xml 里没有这个身份 | grep -i '<identity>' conf/users.xml |
第 2 种最容易踩:kadmin.local -q "xst -k nifi.keytab nifi/host" 默认会把主体口令随机掉,而 NiFi 的 Kerberos 登录页要的是"主体 + 密码",口令被随机掉之后 UI 就永远登不进去,但 keytab 是好的、服务端认证是通的。第 1 篇第 3 节提过这个参数。
4. 节点身份族:一直 CONNECTING / 被别的节点挤下线
4.1 现象
集群页面节点数不对;新起的节点把老节点顶成 DISCONNECTED;日志里节点反复注册、被拒绝、再注册。25 台的时候最难受——你根本分不清是哪台被顶了,只看得到节点数在 25 上下跳。
日志关键字:
Node ... is already connected
Unable to communicate with node ...
This node is not authorized to join the cluster
Received fatal alert: certificate_unknown
4.2 根因(按出现频率)
1)整包拷贝了老节点的安装目录(最常见)
conf/flow.json.gz、conf/nifi.properties、证书、state/ 一起被复制,新节点带着和老节点完全相同的身份注册。ZooKeeper 的节点表只认一个位置,后注册的把先注册的顶掉。
真实经过:第一次扩容为了省事,在老节点上 tar czf 打了整个 /opt/nifi 拷到新节点解压启动。新节点上线后,集群里原来一台老节点变成 DISCONNECTED——看起来像"新加入的把原有的挤掉了"。当时怀疑 tar 包里带了缓存或者某个唯一标识(flow、state、证书 DN 都在里面),没有逐项深究;换成官网原始安装包、全新解压、只拷配置模板之后,一次就加进去了。后续两轮扩容重复验证过这个结论。
处置:新节点用同版本安装包全新解压,只拷配置模板和 template,绝不拷 flow / state / 证书 / repository。详见第 2 篇 2.1。
2)只有部分节点重签了证书
双向 TLS,老节点 truststore 里没有新 CA,握手直接失败。
处置:全集群一起重签、一起分发(第 2 篇 3.2、3.3)。
3)Node Identity 不是全量
每个节点的 authorizers.xml 都要有全部节点的 DN,少一条就少一个能连进来的节点。
处置:补齐并 md5sum 校验所有节点一致(25 台时只能用脚本,见第 2 篇 3.6)。
4)DN 多/少一个空格
CN=host, OU=NIFI 与 CN=host,OU=NIFI 是两个身份。
处置:用证书 Owner 原样粘贴;或用 nifi.security.identity.mapping.* 做规范化(第 1 篇第 6 节)。
4.3 三分钟判定流程
# 1) 这台节点在集群里叫什么、连的哪个 primary
grep -E 'nifi.cluster.node.address|nifi.zookeeper.connect.string' /opt/nifi/conf/nifi.properties
# 2) 它的证书 DN 是什么
keytool -list -v -keystore /opt/nifi/conf/keystore.jks -storepass '<KEYSTORE_PASS>' | grep -m1 'Owner:'
# 3) authorizers.xml 里有没有这一条(注意空格)
grep -c 'Node Identity' /opt/nifi/conf/authorizers.xml
grep -F 'CN=nifi-node-04.example.com, OU=NIFI' /opt/nifi/conf/authorizers.xml
# 4) 和别的节点比一眼
md5sum /opt/nifi/conf/authorizers.xml
第 4 步的价值在于:25 台里只要有一台的 md5 和别的不一样,问题就在那台,不用猜。
5. 证书族
5.1 浏览器报"证书与主机名不匹配"
CN 是 FQDN,你却用 IP 访问。处置:统一用域名访问;或在证书里加 SAN(tls-toolkit 的 -n 传的是主机名,IP 访问本来就不该被支持)。
5.2 unable to find valid certification path
客户端(浏览器、curl、S2S 对端)不信任服务端证书。处置:把 CA 根证书(nifi-cert.pem)导入客户端信任库,或 curl 加 -k 临时验证。
5.3 certificate_unknown / handshake_failure:换了 keystore 没换 truststore
现象:节点之间互相报握手失败,集群页面节点陆续掉线;前台查询也开始异常。
日志:
WARN [Process Cluster Protocol Request-18] o.a.n.c.p.impl.SocketProtocolListener
Failed processing protocol message from nifi-node-07.example.com due to Received fatal alert: certificate_unknown
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Failed to replicate request GET /nifi-api/flow/current-user ... to ...:9443
根因:只换了 keystore.jks(节点自己的证书),truststore.jks 还是旧 CA;或者反过来,只有几台更新了 truststore。双向 TLS 里,任何一边的 truststore 缺了对方的 CA,握手就断。
处置:全量重签 + 全量分发 + 全量校验指纹(第 2 篇 3.3)。校验的输出必须是"只有一行、计数 25":
for n in $(seq 1 25); do
h=$(printf 'nifi-node-%02d' "$n")
printf '%s ' "$h"
ssh "$h" "keytool -list -keystore /opt/nifi/conf/truststore.jks -storepass '<KEYSTORE_PASS>' -v 2>/dev/null | grep -m1 'SHA256:'"
done | awk '{print $2}' | sort | uniq -c
如果 uniq -c 出来两行,就说明集群里同时存在两套 CA——这时候不要修单台,直接按"全量重签"重来一次,否则你会一直修不完。
这一条还有个变体:证书换了、
authorizers.xml里的Node Identity还是旧 DN,于是握手能过、授权过不去,表现为not authorized to join the cluster。两组东西必须一起换。
5.4 证书过期
两年一签的证书最容易在"某天早上突然全挂"时被想起。处置:
# 查 25 台证书到期时间,一眼看全
for n in $(seq 1 25); do
h=$(printf 'nifi-node-%02d' "$n")
printf '%s: ' "$h"
ssh "$h" "keytool -list -v -keystore /opt/nifi/conf/keystore.jks -storepass '<KEYSTORE_PASS>' \
| grep 'Valid from' | head -1"
done
提前一个月重签,流程同扩容(全量重签 + 全量分发 + 改 Node Identity)。把"剩余天数 < 90"做进巡检,比记在日历上可靠。
6. Unable to decrypt / 敏感属性解不开
现象:节点能起,但某些处理器报凭据错误;或者 flow 加载时日志刷解密失败。
根因:nifi.sensitive.props.key 不一致。这个 key 加密了 flow 里所有敏感属性(数据库密码、keytab 口令、SSL 上下文里的密码),换 key 等于换锁。
处置:
# 用原来那个值,在每台上重设
/opt/nifi/bin/nifi.sh set-sensitive-properties-key '<SENSITIVE_KEY>'
如果原 key 已经丢了:只能重新录入所有敏感属性(NiFi 无法解密旧值)。所以这个 key 必须和证书一起进密码管理。
一个和它很像但不同的报错:Configuration does not have security enabled, keytab and principal will be ignored。这不是 key 的问题,而是读到的 core-site.xml 是一份没开 kerberos 的配置(典型场景:目标集群的配置文件被本平台的同名文件覆盖)。处置是检查处理器里 Hadoop Configuration Resources 指向的那两个 xml 到底是谁的(第 4 篇"双写两个 HDFS 集群"一节)。
7. 授权族:能登录,但进去一片空白
7.1 根因
Kerberos 认证只解决"你是谁",授权要另外配:
- 身份字符串不匹配:Kerberos 主体是
etl_user_01@EXAMPLE.COM,users.xml里写的是etl_user_01或大小写不同; - 用户在
users.xml里,但没有/flow策略; - 有
/flow,但没有任何进程组的view策略(根组没有、自己的组也没 Override)。
处置:
# 看这个身份在不在 users.xml
grep -i 'etl_user_01' /opt/nifi/conf/users.xml
# 看它有哪些策略
grep -n 'etl_user_01' /opt/nifi/conf/authorizations.xml
然后在 UI 里按第 3 篇的"最小授权组合"补齐。
7.2 Unable to locate initial admin ... to seed policies
现象:服务起来了,但没人能进;日志里:
org.apache.nifi.authorization.AuthorizationException:
Unable to locate initial admin <identity> to seed policies
根因:authorizers.xml 里声明的初始管理员,和实际登录的身份对不上。三种写法容易错:
Initial Admin Identity为空,或者还是模板里的占位值;- 身份字符串拼错(少了 realm 后缀、大小写不同);
- 用新式
StandardManagedAuthorizer时,只写了Initial Admin Identity,没写Initial User Identity 1(前者在 accessPolicyProvider,后者在 userGroupProvider,两个都要)。
处置:改 authorizers.xml 补齐身份,重启。注意 seed 只发生一次——users.xml / authorizations.xml 已经生成之后,改配置不会再 seed,只能在 UI 里手工补权限,或者备份后删掉这两个文件重新生成。第 3 篇 3.6 节有完整写法。
7.3 组件灰显、队列不消化:不是权限,是 DISABLED
现象:业务说流程不跑,队列一直涨;用户权限看下来 view / modify / operate 全有。
根因:这条流程依赖的 Controller Service(CSVReader、SchemaRegistry 之类)被置成了 DISABLED——某次变更或版本升级后状态丢了,依赖它的处理器就永远不跑。
区分方法:
| 表现 | 无权限 | DISABLED |
|---|---|---|
| UI 上组件 | 看不到/点不动,提示 not authorized | 能看见、能点,但灰显 |
| 日志 | not authorized / 403 | Controller Service ... is disabled |
| 处置 | 授策略 | Enable 服务,再 Restart 处理器 |
详见第 3 篇 4.6 节。
8. 登录后 302 到错误地址 / 静态资源 404
现象
页面能打开,但登录后跳到 https://内网IP:9443/...,或者 CSS/JS 全 404。
根因
前面挂了 nginx / 负载均衡,NiFi 不知道对外地址。
处置
# 对外访问的 host:port,用于生成跳转地址、校验 Host 头
nifi.web.proxy.host=nifi.example.com:9443
# 反向代理的上下文路径(如 /nifi/),必须配
nifi.web.proxy.context.path=/nifi
同时确认 nginx 的 location 与 proxy.context.path 一致,并且转发了 Host 头。
9. ZK 族:选主、myid、状态丢失
| 现象 | 根因 | 处置 |
|---|---|---|
启动卡在 Waiting for cluster to elect primary node | ZK 连不上、或选主超时 | 检查 nifi.zookeeper.connect.string、22181 端口、election.max.wait.time |
ZK 报 myid 冲突 | 两个节点 myid 相同 | 每个节点唯一,且与 server.N 对应 |
| 集群状态反复重建 | 节点时间不一致 / 网络抖动 | 先修时间,再看交换机侧丢包 |
新节点不跑 ZK 却带了 state/zookeeper | 拷配置时带过来的 | 删目录,embedded.zookeeper.start=false |
BindException ...:3888 | 端口被占 / server.N 里的名字解析不到 | 见 2.3 |
冷启动建议先起 ZK 三台,等 ACTIVE 后再分批(每批 5~6 台)加节点,比 25 台一起冲快得多。
9.1 ListSFTP 存不了 state:ConnectionLoss
这条值得单列,因为它不报错、只丢数据:
WARNING ListSFTP[id=6402381b-...] Unable to save state due to java.io.IOException:
Failed to obtain value from ZooKeeper for component with ID 6402381b-... with exception code CONNECTIONLOSS
Caused by: org.apache.zookeeper.KeeperException$ConnectionLossException:
KeeperErrorCode = ConnectionLoss for /nifi/components/6402381b-...
If NiFi is restarted before state is saved, or if another node begins executing this Processor,
data duplication may occur.
根因:ZK 会话抖动,处理器状态写不进去。后果不是服务中断,是重复采集——重启后状态回到上一个保存点,已经被处理过的文件会被再拉一遍。
处置:
- 短期:确认 ZK 三台的负载和 GC,看是不是某台 ZK 在重启;
CONNECTIONLOSS如果是持续的,说明 ZK 已经不稳了。 - 长期:把内置 ZK 换成外置 ZK 集群。25 个节点的集群状态、flow 版本、primary 选举都压在 3 台内置 ZK 上,ZK 的写是串行的,节点越多心跳越密集(第 2 篇 5.1)。
- 下游要能容忍重复:HDFS 侧按分区 + 文件名覆盖,或者用
DetectDuplicate按文件名过滤。
9.2 UnknownHostException:ZK 连不上的真凶常在 /etc/hosts
现象:业务反馈部分节点掉线,前台看到一批节点服务掉线。
日志:
ERROR [main-SendThread(nifi-node-06.example.com:2181)] o.a.zookeeper.client.StaticHostProvider
Unable to resolve address: nifi-node-06.example.com:2181
java.net.UnknownHostException: nifi-node-06.example.com: Name or service not known
根因:/etc/hosts 里没有 NiFi 集群的主机名映射。这台机器的 hosts 被人改过(或者装系统时就没写),ZK 客户端解析不到对端。
这里有个非常有用的细节:报错里的端口是 2181,而你配的是 22181——说明 state-management.xml 里的 Connect String 还是默认值,没跟着改。两个问题叠在一起了:hosts 缺映射 + 配置漏改。看到端口不对,先别怀疑网络,去看配置文件。
处置:
# 1) 从一台正常节点取 hosts,比对差异
scp nifi-node-01:/etc/hosts /tmp/hosts.good
diff /tmp/hosts.good /etc/hosts
# 2) 全量分发(先备份)
ansible -b -m copy -a 'src=/tmp/hosts.good dest=/etc/hosts owner=root group=root mode=0644 backup=yes' nifi
# 3) 确认解析恢复
ansible -m shell -a 'getent hosts nifi-node-06.example.com' nifi -o
恢复后掉线节点会自己重新连回来,不用重启 NiFi。预防:把 /etc/hosts 纳入和 krb5.conf 同一套 md5 巡检——这两类文件被改,表现都是"莫名掉线"。
10. 容量族:磁盘与 content repository
10.1 盘满 = 全局暂停
| 现象 | 根因 | 处置 |
|---|---|---|
| 流程突然全部暂停 | content/flowfile repository 所在盘满 | df -h,清理 content_repository/archive |
No space left on device | 同上 | 缩短 nifi.content.repository.archive.max.retention.period |
| 出处查询很慢 | provenance 索引过大 | 调小 max.storage.size 或缩短保留时间 |
NiFi 对磁盘满的处理是"暂停一切",不会给你留缓冲。content_repository 单独挂盘,并且加监控。
10.2 archive 达到阈值:不是写失败,是主动节流
Unable to write flowfile content to content repository Container content2
due to archive file size constraints; waiting for archive cleanup.
Total number of file currently archived = 10707
这条不是 ERROR 而是 WARNING,含义是:archive 目录达到了 nifi.content.repository.archive.max.usage.percentage(我们是 70%),NiFi 开始"等清理",写入变慢,整个集群的吞吐跟着掉。
处置:
# 缩短保留时间,让 archive 自己更快滚动
nifi.content.repository.archive.max.retention.period=12 hours
nifi.content.repository.archive.max.usage.percentage=70%
再手动清一批(先 -ls 看,再删):
find /data01/nifi/content_repository/*/*/* -type f -mtime +3 -ls | head
nohup find /data01/nifi/content_repository/*/*/* -type f -mtime +3 | xargs rm -rf &
注意:只能删 archive 里的历史文件,不能删正在用的 content。清理完观察队列有没有恢复消化。
10.3 root 属主:一个权限错误如何让整条流程卡死
现象:流程在 list 阶段卡住,后续队列里没有任何文件;把某台节点停掉后,流程立刻恢复正常且稳定。
排查:对比两台节点的目录结构,发现出问题那台的 /data*/nifi/content_repository/ 下面,有一部分文件和 archive 目录同级(正常应该全在 archive 里),而且 archive 的属主是 root。
根因:中途有人用 root 启动过 NiFi,写出来的目录和文件属主是 root;之后用 nifi 用户启动,nifi 用户对 root 属主的目录没有写权限,content 写不进去,处理器就卡在那里——不报错,只是不动。
处置:
# 1) 全量修属主
chown -R nifi:nifi /data01/nifi
chown -R nifi:nifi /data02/nifi
chown -R nifi:nifi /data03/nifi
# 2) 删掉那些"不在 archive 目录里"的野生文件(先看再删)
find /data01/nifi/content_repository/ -maxdepth 2 -mindepth 2 -type f -not -path "*/archive/*" | head
nohup find /data01/nifi/content_repository/ -maxdepth 2 -mindepth 2 -type f -not -path "*/archive/*" -delete &
经验:NiFi 这类"卡住但不报错"的问题,八成是权限或磁盘。先 ls -al 看属主,再 df -h 看空间,比读日志快。
10.4 日志把 /opt 写满
见 3.2。结论重复一次:磁盘满通常是日志速率问题,清理只是止血,滚动策略和监控才是治本(第 6 篇第 4 节)。
11. JVM 族:三种看起来毫不相干的报错
11.1 三副面孔
同一台机器,堆用默认值时能同时出现这三种报错:
# 1) 主日志
java.lang.OutOfMemoryError: GC overhead limit exceeded
# 2) 前台
java.net.SocketTimeoutException: timeout
# 3) REST 接口 500
{"servlet":"jerseySpring",
"cause0":"java.lang.NoClassDefFoundError: Could not initialize class org.springframework.web.context.request.async.WebAsyncManager",
"url":"/nifi-api/flow/current-user","status":"500"}
第一个像 GC 调优问题,第二个像网络问题,第三个像 classpath / 环境坏了。其实是同一件事:堆太小,JVM 在反复 Full GC,应用线程基本没机会跑。类加载失败是 GC 把 Metaspace 或类初始化挤掉之后的连带现象。
11.2 怎么确认
# 1) 看进程实际用的堆参数(不是配置文件里写的,是生效的)
ps -ef | grep -i nifi | grep -v grep | tr ' ' '\n' | grep -- '-Xm'
# 2) 看堆使用(jstat 不用停服务)
jstat -gcutil $(pgrep -f 'nifi.Bootstrap' | head -1) 1000 5
# 3) 看 bootstrap.conf 里到底改没改
grep -E 'java.arg.(2|3)' /opt/nifi/conf/bootstrap.conf
如果 -Xmx 还是 512m 或者 1g,而 flow 里有几十个处理器在跑,基本就可以定案了。
11.3 处置
# conf/bootstrap.conf
java.arg.2=-Xms10240m
java.arg.3=-Xmx10240m
java.arg.4=-XX:MetaspaceSize=512m
java.arg.5=-XX:+HeapDumpOnOutOfMemoryError
java.arg.6=-XX:HeapDumpPath=/data01/nifi/dump
改完 sh nifi.sh restart。25 台要统一改,只改出问题那台会让负载全压到它身上(堆大的节点更"能扛",调度器不知道这件事,但队列会往它身上堆)。
一条顺序上的经验:碰到"接口超时 500 + 前台转圈 + GC 报错"同时出现,先看堆,再查网络、证书、DNS。反过来查,会浪费掉一整个下午。
12. 主机族:不在 NiFi 里的那些故障
12.1 属主错误:jar 和日志变成 root
现象:某台节点服务掉线,重启后又掉;日志里没有明确的认证/证书错误。
根因:这台机器上部分 jar 包和日志文件的属主是 root(有人用 root 拷过文件、或者用 root 跑过一次服务)。NiFi 以 nifi 用户运行,读不了 logs/ 下 root 属主的文件就写不了日志,某些 jar 属主不对则加载失败。
处置:
chown -R nifi:nifi /opt/nifi
chown -R nifi:nifi /data01/nifi /data02/nifi /data03/nifi
预防:所有 Ansible copy/file 任务显式写 owner=nifi group=nifi;不用 root 启动服务(第 6 篇第 8 节)。
12.2 主机内存缓存太多,写盘卡住把机器夯死
现象:节点彻底无响应,SSH 都慢,NiFi 进程还在但什么都不干;重启主机后一切正常。
根因:这台机器上有大量文件写入(content repository 是重写场景),page cache 攒得太多,writeback 时被阻塞,整机进入 D 状态。表现和"NiFi 挂了"完全一样。
处置与预防:
# 看有多少脏页在等落盘
grep -E 'Dirty|Writeback' /proc/meminfo
# 看是不是有进程长时间处于 D 状态
ps -eo pid,stat,comm | awk '$2 ~ /D/'
- 降低
vm.dirty_ratio/vm.dirty_background_ratio(比如 10 / 5),让脏页更早落盘,代价是写入抖动更明显但不会夯死。 - content repository 的盘用 SSD 或者至少别和系统盘共用。
- 加
node_exporter的node_pressure_io_stalled类指标监控,比等业务报障早。
12.3 时间不同步
Clock skew too great 见 3.1。补一句:时间偏差不只影响 Kerberos,也会让证书校验、ZK 会话、日志时间线全部错乱,排查时先把 date 对齐。
13. SSH / SFTP 族
SFTP 相关的报错是这套环境里最"会骗人"的一类,因为它同时有三个完全不同的根因。
13.1 Received SSH_MSG_UNIMPLEMENTED while exchanging keys
日志:
ERROR [sshj-Reader-/10.20.30.31:22] net.schmizz.sshj.transport.TransportImpl
Dying because - Received SSH_MSG_UNIMPLEMENTED while exchanging keys
net.schmizz.sshj.transport.TransportException: Received SSH_MSG_UNIMPLEMENTED while exchanging keys
ERROR [Timer-Driven Process Thread-6] o.a.nifi.processors.standard.FetchSFTP
... org.apache.nifi.processors.standard.socket.ClientConnectException: SSH Client connection failed [[10.20.30.31:22]]
Caused by: net.schmizz.sshj.transport.TransportException: Received SSH_MSG_UNIMPLEMENTED while exchanging keys
这个报错我们遇到过两次,根因完全不同:
根因 A:sshj 库版本缺陷。 NiFi 1.17.0 的 nifi-standard-nar 里带的是 sshj 0.33.0,某些服务端(老版本 OpenSSH、或者配置了少见的 kex 算法)在密钥交换阶段会回一个未实现的报文,sshj 直接断开。NiFi 后续版本升级了 sshj,修掉了这个问题。
我们当时的处置是手工替换 NAR 里的 jar:
# 1) 把新 jar 放到 standard NAR 解包目录的 bundled-dependencies 下
ansible -m copy -a 'src=/data/pkg/sshj-0.38.0.jar
dest=/opt/nifi/nifi-1.17.0/work/nar/extensions/nifi-standard-nar-1.17.0.nar-unpacked/NAR-INF/bundled-dependencies/
owner=nifi group=nifi mode=0664' nifi -o
# 2) 旧 jar 改名备份(不要删)
ansible -m shell -a 'mv .../sshj-0.33.0.jar .../sshj-0.33.0.jar_bak' nifi -o
# 3) 重启
sh /opt/nifi/nifi-1.17.0/bin/nifi.sh stop
sh /opt/nifi/nifi-1.17.0/bin/nifi.sh start
这个方案的代价必须讲清楚:
work/nar/extensions/是 NiFi 从 NAR 包解压出来的运行时目录,升级版本或清理 work 目录时会被覆盖,替换就白做了。要么把它写进升级检查清单(每次升级后重做一遍),要么做一个自定义 NAR 把 sshj 版本固定下来——后者才是长久方案。
根因 B:集群各节点的 JDK 版本不一致。 第二次遇到同样的报错,查了一圈 sshj 版本都一样,最后发现是节点之间 JDK 版本不同:不同 JDK 支持的 TLS 加密套件和算法不同,密钥交换协商失败,表现就是 SSH_MSG_UNIMPLEMENTED。
# 一次看全 25 台的 java 版本和 home
ansible -m shell -a 'java -version 2>&1 | head -1; echo $JAVA_HOME' nifi -o
ansible -m shell -a 'alternatives --config java 2>/dev/null | head -5' nifi -o
处置:把所有节点统一到同一个 JDK 版本(alternatives + /etc/profile 的 JAVA_HOME 都要改,并且注意 nifi 用户登录时的环境是否读到了新值——su - nifi 之后再 java -version 确认一次),然后重启服务。
怎么区分 A 和 B:先看 25 台的 java -version 是否一致(1 分钟)。一致就是库的问题,不一致就是 JDK 的问题。这个顺序比先翻 sshj 的 changelog 快得多。
13.2 Timeout expired: 30000 MILLISECONDS
net.schmizz.sshj.transport.TransportException: Timeout expired: 30000 MILLISECONDS
ClientConnectException: SSH Client connection failed [[10.20.30.31:22]
根因:远端 SFTP 响应慢(负载高、网络抖动、磁盘 IO 顶住),30 秒建连/握手没完成。注意它常常和 HDFS 侧的 slow waitForAckedSeqno 同时出现——那就不是单点问题,是集群整体负载高(第 4 篇第 5 节)。
处置:
- 把 FetchSFTP/ListSFTP 的
Connection Timeout从 30s 调到 10–20s,快速失败、快速重试,比挂着 30s 占线程好; - 给重试队列加 back pressure,避免远端抖一下就把本地堆满;
- 业务侧降并发,别用"加节点"解决远端慢的问题。
13.3 not.found / permission.denied
ERROR ListSFTP[id=...] Failed to perform listing on remote host due to
Could not perform listing on /data08/sftpfile/xxx because could not find the file on the remote server
ERROR ListSFTP[id=...] Unable to get listing from /1212bak; skipping:
org.apache.nifi.processors.standard.util.PermissionDeniedException:
Could not perform listing on /1212bak due to insufficient permissions
这两类基本是上游问题:文件还没生成(not.found)、目录权限没给(permission.denied)。关键不是消灭报错,是确保它不丢数据——检查这些关系是不是被配成了 terminate(第 4 篇第 4 节)。
13.4 关系配 terminate:最贵的一个配置
comms.failure、not.found、permission.denied 三个关系如果 auto-terminate,等于"拉不到就丢",业务侧只会看到"少了几条文件",而 NiFi 侧一片绿色。这三类一律改成 retry,并给重试队列限量。
14. 数据族:文件写坏了
14.1 MalformedRecordException / EOF reached before encapsulated token finished
ERROR PutParquet[id=096a3848-...] Failed to write due to java.io.IOException:
org.apache.nifi.serialization.MalformedRecordException: Error while getting next record
Caused by: java.io.IOException: (startline 328401) EOF reached before encapsulated token finished
根因:源文件有问题——被截断(上游写到一半)、带残留的反斜杠/引号导致列结构崩掉、列数和 schema 不符。Record Reader 逐行解析,遇到坏行整批失败,不是跳过那一行。
处置:在 Record Reader 之前拦。三种方案的能力边界见第 4 篇 3.4 节,结论是 ExecuteScript 预校验最靠谱,ReplaceText 只能做固定替换,UpdateRecord 来不及(坏行进不到 record 级)。
14.2 is not a Parquet file. Expected magic number at tail
java.lang.RuntimeException: viewfs://.../biz_a_2025010106_<uuid>.snappy.parquet
is not a Parquet file. Expected magic number at tail, but found [-48, -19, -53, 94]
根因:文件写了一半(节点重启、磁盘满、超时中断),Parquet 的尾部 magic number(PAR1)没写进去。文件存在、有大小,但读不了。
判定:
hadoop fs -tail -c 4 <file> | hexdump -C # 末尾必须是 50 41 52 31
hadoop fs -cat <file> | head -c 4 # 开头也必须是 PAR1
处置:删掉坏文件,重跑那个批次。不要试图修复——NiFi 没有内置的"写完后校验 HDFS 文件"能力,缺的那半截数据只能重采(第 4 篇 7.3 有完整校验方法)。
14.3 队列卡在 list 阶段
现象是"流程不报错、队列也不涨、就是没数据进来"。三个方向:
- List 组件本身没扫到(文件命名窗口错过,第 4 篇 2.6);
- content repository 写不进去(属主/空间,见 10.3);
- 处理器不是 RUNNING(有人 Stop 了没启,或者 DISABLED 的服务拖住了它,见 7.3)。
看 Provenance 按组件过滤,一眼就能分清是"没进来"还是"进来了没出去"。
15. UI 超时 / API 500:最难定位的一类
这一条我们没有完全闭环,如实写下来,因为它可能是很多人会遇到的形态。
现象:
- UI 和接口
/nifi-api/flow/process-groups/root?uiOnly=true返回 HTTP 500; - 服务端日志里集群请求复制失败,
java.net.SocketTimeoutException: timeout; - 节点间通信/协调阶段超时,页面加载不出来。
已排除:Kerberos/keytab(认证是通的)、DNS(nslookup/dig 正常且耗时低)、GC(没有长时间停顿)、防火墙(端口未阻断)。
做过的尝试:把某节点的 nifi.cluster.node.address 从 hostname 改成 IP,无效。
后来的情况:第二天自己恢复了。推测是当时 primary 节点太忙(请求复制都要经过它),切换之后就好了——但这只是推测,没有证据。
如果再来一次,我会按这个顺序查:
- primary 节点的 GC 和线程池(
jstat、线程 dump 看是否有大量Process Cluster Protocol线程阻塞); nifi.cluster.protocol.timeout与nifi.cluster.node.connection.timeout是否需要调大(默认偏短,25 台规模下调度压力大);- 请求复制路径上的网络(
curl -k https://<peer>:9443/nifi-api/access/config -w '%{time_total}',从每个节点测一遍); - 是否有个别处理器占了全部 timer 线程(线程 dump 里数
Timer-Driven Process Thread的占用)。
诚实的结论:这一类"集群通信超时"没有单一根因,它更像是"负载 + 超时阈值 + primary 单点"三者叠加出来的表现。能做的不是找一个开关,而是把 primary 的负载压下来、把超时阈值调到匹配规模、把 UI 访问从 primary 上挪开。
16. 端口:五个必须通的口子
# 9443 被谁占了
ss -lntp | grep 9443
# 集群协议端口通不通(从节点 A 测节点 B)
nc -zv nifi-node-02.example.com 11443
# S2S 端口
nc -zv nifi-node-02.example.com 10443
NiFi 用到的端口一共五个,扩容/搬迁时漏开一个就够排查半天:
| 端口 | 用途 |
|---|---|
| 9443 | Web UI / REST |
| 11443 | 集群节点协议 |
| 6342 | 负载均衡 |
| 10443 | 站点到站点(S2S) |
| 22181 | 内置 ZooKeeper 客户端 |
另外三个容易忽略的:2888(ZK 选主)、3888(ZK 心跳)、以及 nifi.remote.input.socket.port 对应的裸 TCP 端口(默认和 10443 同段但走不同协议)。安全扫描也最爱扫这几个,第 6 篇第 5 节讲怎么处置。
17. 一张速查表
| 日志关键字 | 一句话根因 | 去哪节 |
|---|---|---|
UninheritableFlowException | 本地 flow 与集群不一致 | 1 |
FlowSynchronizationException / partially updated | 同步中断留下半个 flow | 1 |
Proposed flow is not inheritable | 集群 flow 会删掉本地连接 | 1 |
Failed to start web server: Already closed | 上游是 flow 没加载,别查端口 | 1.1 |
Invalid nifi.web.https configuration | https 开了但 truststore 没配 | 2.1 |
truststore properties are not valid | 同上 | 2.1 |
Remote input HTTPS is enabled but ... | secure 与 https 端口矛盾 | 2.2 |
BindException: Cannot assign requested address | 端口占用或 server.N 名字解析不到 | 2.3 |
Cannot locate KDC | krb5.conf 被覆盖 | 3.2 |
Clock skew too great | 时间不同步 | 3.1 |
Server not found in Kerberos database | 主体不存在/写错 | 3.1 |
Pre-authentication information was invalid | 密码错(或被 randkey 了) | 3.1、3.3 |
is already connected | 节点身份重复(多半是拷了安装包) | 4.2 |
not authorized to join the cluster | Node Identity 缺失/不一致 | 4.2 |
certificate_unknown | truststore 没跟着换 | 5.3 |
handshake_failure | 双向 TLS 不互信(也可能是启动方式,见 2.4) | 5.3 |
unable to find valid certification path | 客户端不信任 CA | 5.2 |
Unable to decrypt | sensitive props key 不一致 | 6 |
Configuration does not have security enabled | 读到了没开 kerberos 的 core-site | 6 |
| 登录后空白 | 身份不匹配或无 /flow 策略 | 7.1 |
Unable to locate initial admin | 初始管理员身份对不上 | 7.2 |
Controller Service ... is disabled | 不是权限,是状态 | 7.3 |
| 302 到内网 IP | 没配 proxy.host/context.path | 8 |
| 选主卡住 | ZK 连不上/myid 冲突 | 9 |
ConnectionLoss(ListSFTP state) | ZK 会话抖动,会重复采集 | 9.1 |
UnknownHostException(ZK) | /etc/hosts 缺映射 | 9.2 |
| 流程全部暂停 | 磁盘满 | 10.1 |
archive file size constraints | archive 到阈值,主动节流 | 10.2 |
| 队列卡住但不报错 | 目录属主是 root | 10.3 |
GC overhead limit exceeded | 堆太小(默认值) | 11.1 |
WebAsyncManager NoClassDefFoundError | 同上,不是框架坏了 | 11.1 |
SocketTimeoutException: timeout | 先看堆,再看负载 | 11.1、15 |
Permission denied(本地文件) | 属主错(root) | 12.1 |
| 主机无响应、SSH 也慢 | page cache 写回阻塞 | 12.2 |
SSH_MSG_UNIMPLEMENTED | sshj 版本缺陷 或 JDK 不一致 | 13.1 |
Timeout expired: 30000 MILLISECONDS | 远端慢/集群整体负载高 | 13.2 |
MalformedRecordException / EOF ... token | 源文件坏行/截断,整批失败 | 14.1 |
Expected magic number at tail | Parquet 写了一半 | 14.2 |
process-groups/root 500 + 复制超时 | primary 负载/超时阈值 | 15 |
18. 小结
这套环境跑下来,真正致命的错误只有几类,且全部和"身份"有关:
- 证书身份:CN/DN 不一致、只有部分节点换证书;
- 节点身份:整包拷贝导致两个节点同身份;
- 用户身份:Kerberos 主体与
users.xml不一致; - flow 身份:节点本地 flow 与集群版本不一致,靠删
flow.xml.gz/flow.json.gz复位; - 主机身份:
/etc/hosts、krb5.conf这些"不属于 NiFi 但决定 NiFi 能不能起来"的文件被改掉。
前四类是 NiFi 自己的概念,最后一类是它借来的地基。配置项写错,日志会直接告诉你哪一行;这五类错了,日志只会说"连不上""未授权""不能继承",然后让你查一整天。
所以配 NiFi 安全和排障时,最值得花时间的事不是背参数,而是把这几类身份画成一张表对齐:证书 DN、Node Identity、用户主体、flow 版本、主机名与 hosts。对着表逐项打勾,比翻日志快得多。