ZooKeeper节点数据量限制引起的Hadoop YARN ResourceManager崩溃原因分析

YARN不是调度器:揭秘Hadoop分布式操作系统内核架构 YARN是Hadoop生态中首个将计算资源抽象为可编程操作系统内核的基础设施,其核心在于资源抽象、进程隔离与生命周期自治。它通过ResourceManager、ApplicationMaster和NodeManager构成的双层调度模型,实现全局资源仲裁与应用级智能调度的解耦。技术价值体现在多租户隔离、跨框架资源复用及生产级容错能力,广泛应用于Spark、Flink等大数据引擎的资源底座。深入理解YARN的CGroups内存控制、Timeline Server事件总线与RM HA状态恢复机制,是构建高可用P 阅读详情

面试:你懂什么是分布式系统吗?Redis分布式锁都不会?>>>   hot3.png

环境

  • Hadoop版本:Apache Hadoop 2.6.3
  • ZooKeeper版本:ZooKeeper 3.4.10
  • 两个ResourceManager节点:主节点RM01,从节点RM02

背景

最近有一次我们的Hadoop监控平台发出ResourceManager(以下简称RM)崩溃的报警信息,于是我们分析了RM的日志和ZooKeeper服务端(以下简称ZK)的日志,异常日志信息分别如下:

RM日志

RM01的异常日志如下:

2019-03-03 02:33:01,826 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Retrying operation on ZK. Retry no. 999
2019-03-03 02:33:02,088 INFO org.apache.zookeeper.ClientCnxn: Opening socket connection to server 10.204.245.44/10.204.245.44:5181. Will not attempt to authenticate using SASL (unknown error)
2019-03-03 02:33:02,089 INFO org.apache.zookeeper.ClientCnxn: Socket connection established to 10.204.245.44/10.204.245.44:5181, initiating session
2019-03-03 02:33:02,090 INFO org.apache.zookeeper.ClientCnxn: Session establishment complete on server 10.204.245.44/10.204.245.44:5181, sessionid = 0x1690d678e9448da, negotiated timeout = 60000
2019-03-03 02:33:02,101 WARN org.apache.zookeeper.ClientCnxn: Session 0x1690d678e9448da for server 10.204.245.44/10.204.245.44:5181, unexpected error, closing socket connection and attempting reconnect
java.io.IOException: Broken pipe
	at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
	at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
	at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
	at sun.nio.ch.IOUtil.write(IOUtil.java:65)
	at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:117)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:366)
	at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)
2019-03-03 02:33:02,201 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Exception while executing a ZK operation.
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /bi-rmstore/ZKRMStateRoot/RMAppRoot/application_1551528254601_0725/appattempt_1551528254601_0725_000001
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:99)
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1045)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1073)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1058)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithCheck(ZKRMStateStore.java:1128)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithRetries(ZKRMStateStore.java:1161)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.existsWithRetries(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.updateApplicationAttemptStateInternal(ZKRMStateStore.java:712)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:243)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:226)
	at org.apache.hadoop.yarn.state.StateMachineFactory$SingleInternalArc.doTransition(StateMachineFactory.java:362)
	at org.apache.hadoop.yarn.state.StateMachineFactory.doTransition(StateMachineFactory.java:302)
	at org.apache.hadoop.yarn.state.StateMachineFactory.access$300(StateMachineFactory.java:46)
	at org.apache.hadoop.yarn.state.StateMachineFactory$InternalStateMachine.doTransition(StateMachineFactory.java:448)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore.handleStoreEvent(RMStateStore.java:812)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:872)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:867)
	at org.apache.hadoop.yarn.event.AsyncDispatcher.dispatch(AsyncDispatcher.java:182)
	at org.apache.hadoop.yarn.event.AsyncDispatcher$1.run(AsyncDispatcher.java:109)
	at java.lang.Thread.run(Thread.java:745)
2019-03-03 02:33:02,201 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Maxed out ZK retries. Giving up!
2019-03-03 02:33:02,201 ERROR org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore: Error updating appAttempt: appattempt_1551528254601_0725_000001
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /bi-rmstore/ZKRMStateRoot/RMAppRoot/application_1551528254601_0725/appattempt_1551528254601_0725_000001
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:99)
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1045)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1073)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1058)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithCheck(ZKRMStateStore.java:1128)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithRetries(ZKRMStateStore.java:1161)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.existsWithRetries(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.updateApplicationAttemptStateInternal(ZKRMStateStore.java:712)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:243)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:226)
	at org.apache.hadoop.yarn.state.StateMachineFactory$SingleInternalArc.doTransition(StateMachineFactory.java:362)
	at org.apache.hadoop.yarn.state.StateMachineFactory.doTransition(StateMachineFactory.java:302)
	at org.apache.hadoop.yarn.state.StateMachineFactory.access$300(StateMachineFactory.java:46)
	at org.apache.hadoop.yarn.state.StateMachineFactory$InternalStateMachine.doTransition(StateMachineFactory.java:448)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore.handleStoreEvent(RMStateStore.java:812)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:872)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:867)
	at org.apache.hadoop.yarn.event.AsyncDispatcher.dispatch(AsyncDispatcher.java:182)
	at org.apache.hadoop.yarn.event.AsyncDispatcher$1.run(AsyncDispatcher.java:109)
	at java.lang.Thread.run(Thread.java:745)
2019-03-03 02:33:02,201 ERROR org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore: State store operation failed 
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /bi-rmstore/ZKRMStateRoot/RMAppRoot/application_1551528254601_0725/appattempt_1551528254601_0725_000001
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:99)
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1045)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1073)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1058)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$9.run(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithCheck(ZKRMStateStore.java:1128)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore$ZKAction.runWithRetries(ZKRMStateStore.java:1161)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.existsWithRetries(ZKRMStateStore.java:1055)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore.updateApplicationAttemptStateInternal(ZKRMStateStore.java:712)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:243)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$UpdateAppAttemptTransition.transition(RMStateStore.java:226)
	at org.apache.hadoop.yarn.state.StateMachineFactory$SingleInternalArc.doTransition(StateMachineFactory.java:362)
	at org.apache.hadoop.yarn.state.StateMachineFactory.doTransition(StateMachineFactory.java:302)
	at org.apache.hadoop.yarn.state.StateMachineFactory.access$300(StateMachineFactory.java:46)
	at org.apache.hadoop.yarn.state.StateMachineFactory$InternalStateMachine.doTransition(StateMachineFactory.java:448)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore.handleStoreEvent(RMStateStore.java:812)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:872)
	at org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore$ForwardingEventHandler.handle(RMStateStore.java:867)
	at org.apache.hadoop.yarn.event.AsyncDispatcher.dispatch(AsyncDispatcher.java:182)
	at org.apache.hadoop.yarn.event.AsyncDispatcher$1.run(AsyncDispatcher.java:109)
	at java.lang.Thread.run(Thread.java:745)
2019-03-03 02:33:03,074 INFO org.apache.zookeeper.ZooKeeper: Session: 0x1690d678e9448da closed
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.event.AsyncDispatcher: AsyncDispatcher is draining to stop, igonring any new events.
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptImpl: appattempt_1551528254601_0723_000001 State change from RUNNING to FINAL_SAVING
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Ignore watcher event type: None with state:Disconnected for path:null from old session
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Ignore watcher event type: None with state:SyncConnected for path:null from old session
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Ignore watcher event type: None with state:Disconnected for path:null from old session
2019-03-03 02:33:03,074 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Ignore watcher event type: None with state:SyncConnected for path:null from old session
2019-03-03 02:33:03,074 WARN org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore: State-store fenced ! Transitioning RM to standby

RM02的异常日志如下:

2019-03-05 12:10:24,634 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Retrying operation on ZK. Retry no. 124
2019-03-05 12:10:25,447 INFO org.apache.zookeeper.ClientCnxn: Opening socket connection to server 10.204.245.45/10.204.245.45:5181. Will not attempt to authenticate using SASL (unknown error)
2019-03-05 12:10:25,447 INFO org.apache.zookeeper.ClientCnxn: Socket connection established to 10.204.245.45/10.204.245.45:5181, initiating session
2019-03-05 12:10:25,449 INFO org.apache.zookeeper.ClientCnxn: Session establishment complete on server 10.204.245.45/10.204.245.45:5181, sessionid = 0x1693f9adb5401ae, negotiated timeout = 60000
2019-03-05 12:10:26,704 WARN org.apache.zookeeper.ClientCnxn: Session 0x1693f9adb5401ae for server 10.204.245.45/10.204.245.45:5181, unexpected error, closing socket connection and attempting reconnect
java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3236)
	at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
	at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
	at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:135)
	at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
	at org.apache.jute.BinaryOutputArchive.writeInt(BinaryOutputArchive.java:55)
	at org.apache.zookeeper.proto.SetDataRequest.serialize(SetDataRequest.java:59)
	at org.apache.zookeeper.MultiTransactionRecord.serialize(MultiTransactionRecord.java:77)
	at org.apache.zookeeper.ClientCnxn$Packet.createBB(ClientCnxn.java:292)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:115)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:366)
	at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)

以上是两个RM节点的日志,可以忽略时间点,3月3号和3月5号发生异常的轨迹类似,异常发生的过程如下:

1、我们在yarn-site.xml配置了yarn.resourcemanager.store.class这个属性的值为org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore,也就是说,RM会将它的状态信息保存到ZK中,与此属性相关的,还有如下两个重要属性:

  • yarn.resourcemanager.zk-num-retries:表示RM与ZK的连接丢失后,尝试与ZK建立连接的次数,我们线上默认是1000
  • yarn.resourcemanager.zk-retry-interval-ms:尝试连接ZK的时间间隔,我们线上默认是1000毫秒,也就是1秒

基于以上配置,在RM与ZK连接失败后,每隔1秒RM就会尝试与ZK建立连接,直到达到最大重试次数,因此,从第一段日志我们可以看出如下日志轨迹:

(1)主节点RM01上的RM向ZK的/bi-rmstore节点中写数据发生异常,返回连接丢失错误码KeeperErrorCode=ConnectionLoss:

2019-03-03 02:33:02,201 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Exception while executing a ZK operation.
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /bi-rmstore/ZKRMStateRoot/RMAppRoot/application_1551528254601_0725/appattempt_1551528254601_0725_000001

(2)RM接收到连接丢失的错误码,按照重试逻辑进行重试,一直重试到999次,按照重试间隔时间,这期间花了至少999秒,也就是至少15分钟:

2019-03-03 02:33:01,826 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Retrying operation on ZK. Retry no. 999

(3)重试到第999次,还是连接丢失,那么,进行第1000次重试,但是,这个时候已经达到最大重试次数限制了,于是RM就打印达到最大重试次数、保存状态失败的信息:

2019-03-03 02:33:02,201 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Maxed out ZK retries. Giving up!
2019-03-03 02:33:02,201 ERROR org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore: State store operation failed

(4)主节点的RM发现自己怎么向ZK中写数据都写不进去,于是就标识自己出了问题,接着开始故障转移,将请求转移到RM02服务器,也就是从节点上,此时RM发生了主从切换:

2019-03-03 02:33:03,074 WARN org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore: State-store fenced ! Transitioning RM to standby

(5)因为发生了主从切换,从节点RM02此时是主节点。它切换完成后,也立即执行RM01上没有完成的操作,也就是往ZK写数据,但是也写不进去,最后重试到124次的时候,发生了JVM堆内存溢出异常:

2019-03-05 12:10:24,634 INFO org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore: Retrying operation on ZK. Retry no. 124
java.lang.OutOfMemoryError: Java heap space

堆内存溢出异常发生的原因一般是JVM的堆内存区域中有很多存活的对象,然后一个新对象申请不到所需的堆内存时,就会发生此类异常。

(6)此时,RM02内存溢出了,但是它自己进程没有退出,也没有故障转移,受影响的是90个NodeManager,它们发现连接不到RM了,就自己挂掉了,于是整个集群挂了。在整个故障发生过程中,我们可能会有一个疑问——为什么RM向ZK写数据写不进去?这个问题要结合ZK日志来分析,先抓住一个点,那就是发生内存溢出异常的代码位置:

java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3236)
	at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
	at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
	at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:135)
	at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
	at org.apache.jute.BinaryOutputArchive.writeInt(BinaryOutputArchive.java:55)
	at org.apache.zookeeper.proto.SetDataRequest.serialize(SetDataRequest.java:59)
	at org.apache.zookeeper.MultiTransactionRecord.serialize(MultiTransactionRecord.java:77)
	at org.apache.zookeeper.ClientCnxn$Packet.createBB(ClientCnxn.java:292)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:115)
	at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:366)
	at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)

在这里,重点关注org.apache.zookeeper.proto.SetDataRequest.serialize这个位置的代码,经过查看源码可以知道,这是ZK客户端往服务端写数据时,执行的正常序列化操作,也可以从serialize这个方法名字看出来该方法的作用,关键是写了多大的数据给ZK。接下来我们来看看ZK日志。

ZK日志

ZK日志如下:

2019-03-05 12:59:46,158 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:NIOServerCnxnFactory@197] - Accepted socket connection from /10.216.2.25:41586
2019-03-05 12:59:46,160 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:ZooKeeperServer@966] - Client attempting to renew session 0x2690d678e98ae8b at /10.216.2.25:41586
2019-03-05 12:59:46,160 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:Learner@108] - Revalidating client: 0x2690d678e98ae8b
2019-03-05 12:59:46,161 [myid:1] - INFO  [QuorumPeer[myid=1]/0:0:0:0:0:0:0:0:5181:ZooKeeperServer@712] - Established session 0x2690d678e98ae8b with negotiated timeout 60000 for client /10.216.2.25:41586
2019-03-05 12:59:46,167 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:ZooKeeperServer@997] - got auth packet /10.216.2.25:41586
2019-03-05 12:59:46,167 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:ZooKeeperServer@1031] - auth success /10.216.2.25:41586
2019-03-05 12:59:46,177 [myid:1] - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:NIOServerCnxn@380] - Exception causing close of session 0x2690d678e98ae8b due to java.io.IOException: Len error 1788046
2019-03-05 12:59:46,177 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:NIOServerCnxn@1091] - Closed socket connection for client /10.216.2.25:41586 which had sessionid 0x2690d678e98ae8b

在ZK日志中,我们可以看到ZK Server接收到来自10.216.2.25:41586(RM01)进程的连接请求,最后发生了异常关闭了session,重点关注如下日志片段:

2019-03-05 12:59:46,177 [myid:1] - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:NIOServerCnxn@380] - Exception causing close of session 0x2690d678e98ae8b due to java.io.IOException: Len error 1788046
2019-03-05 12:59:46,177 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:5181:NIOServerCnxn@1091] - Closed socket connection for client /10.216.2.25:41586 which had sessionid 0x2690d678e98ae8b

以上日志显示ZK接收到一个1788046字节(1.7MB)的数据,接着发生了异常,最后关闭了session。在ZK的配置中,有一个jute.maxbuffer参数,这个参数是个全局参数,定义了每个ZNode节点所能存储的最大数据量,以字节为单位,默认为1048576字节,也就是说,默认情况下,ZK规定它的每个ZNode只能存储1兆数据。在这里,YARN集群的RM节点给ZK发送了一个1.7MB的数据,ZK判断这个数据超过了它所限制的最大数据量,因此就抛出了Len error 1788046的异常,最后直接关闭了session,给客户端返回了KeeperErrorCode=ConnectionLoss连接丢失错误码。

在这里,我们基本上清楚了两个RM为什么向ZK写数据写不进去了。还有一个问题,为什么会发生JVM内存溢出呢?这个问题的原因不在于ZK写数据异常,在于以下代码,接下来进行代码剖析。

YARN读写ZK代码

以下代码摘自org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore类的保存状态和重试逻辑部分,具体细节见注释。先看下保存应用状态的逻辑:

 @Override
    public synchronized void updateApplicationStateInternal(ApplicationId appId,
                                                            ApplicationStateData appStateDataPB) throws Exception {
        String nodeUpdatePath = getNodePath(rmAppRoot, appId.toString());

        if (LOG.isDebugEnabled()) {
            LOG.debug("Storing final state info for app: " + appId + " at: "
                    + nodeUpdatePath);
        }
        
        // RM状态字节数组
        byte[] appStateData = appStateDataPB.getProto().toByteArray();

        // 调用重试逻辑写数据
        if (existsWithRetries(nodeUpdatePath, true) != null) {
            setDataWithRetries(nodeUpdatePath, appStateData, -1);
        } else {
            createWithRetries(nodeUpdatePath, appStateData, zkAcl,
                    CreateMode.PERSISTENT);
            LOG.debug(appId + " znode didn't exist. Created a new znode to"
                    + " update the application state.");
        }
    }

该段代码最终会调用以下重试逻辑:

T runWithRetries() throws Exception {
            int retry = 0; // 保存重试次数
            while (true) {
                try {
                    return runWithCheck();
                } catch (KeeperException.NoAuthException nae) {
                    if (HAUtil.isHAEnabled(getConfig())) {
                        // NoAuthException possibly means that this store is fenced due to
                        // another RM becoming active. Even if not,
                        // it is safer to assume we have been fenced
                        throw new StoreFencedException();
                    }
                } catch (KeeperException ke) {
                    if (ke.code() == Code.NODEEXISTS) {
                        LOG.info("znode already exists!");
                        return null;
                    }
                    LOG.info("Exception while executing a ZK operation.", ke);
                    retry++; // 累计重试次数

                    /**
                     * 在未达到最大重试次数的条件的下,根据ZK Server返回的错误码执行不同的重试策略
                     */
                    if (shouldRetry(ke.code()) && retry < numRetries) { // 如果ZK Server返回的错误码为连接丢失、连接超时,则直接进行重试
                        LOG.info("Retrying operation on ZK. Retry no. " + retry);
                        Thread.sleep(zkRetryInterval);
                        continue;
                    }
                    if (shouldRetryWithNewConnection(ke.code()) && retry < numRetries) {  // 如果ZK Server返回的错误码为会话丢失、会话转移,则创建连接后进行重试
                        LOG.info("Retrying operation on ZK with new Connection. " +
                                "Retry no. " + retry);
                        Thread.sleep(zkRetryInterval);
                        createConnection();
                        syncInternal(ke.getPath());
                        continue;
                    }
                    LOG.info("Maxed out ZK retries. Giving up!"); // 达到最大重试次数,放弃重试,抛出异常
                    throw ke;
                }
            }
        }

以上代码就是RM读写ZK失败时的重试逻辑,其中zkRetryInterval和numRetries两个变量的值来源于RM日志部分所列的两个重试配置。

问题原因

总的看来,JVM内存溢出异常发生的轨迹是这样的,RM往ZK写数据,ZK判断这个数据超过了最大数据量限制,然后就关闭了RM与ZK之间的连接。RM捕捉到ZK返回的连接丢失状态码,接着进行重试,重试机制是这样的:1秒重试一次,一直重试到1000次,最后搞的RM节点内存溢出了。观察数据发现,内存溢出时YRAN队列里堆积了200多个需要执行的任务,并且有几十个在执行,RM上的JVM堆内存消耗平时消耗4、5G,堆最大值6G。因此内存溢出的原因就是重试次数太多、太频繁,创建了太多对象,导致内存溢出的。

ZK数据量限制是诱因,重试机制引起的程序循环调用是根源。因为程序运行过程中,抛出了异常,然后在抛出异常的位置执行重试逻辑,重试间隔时间短、频率高,这个时候,方法栈内存和方法在执行过程中引用的堆内存对象也不会被释放,这也间接说明:

  • 设置重试策略时,要结合实际情况设置合适的值

  • 重试逻辑中的while(true)类似于一个死循环,死循环其实是方便了程序员难为了机器,其优点就是易理解,容易编程。这里可以理解为递归调用,递归是用栈机制实现的,每深入一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时间开销

解决方案

在Hadoop YARN jira YARN-2368中发现,之前也有人碰到过类似的问题,官方也给出了相关的解决方案,但是Hadoop版本之间有差异,以Apache Hadoop版本为准:

1、Hadoop 2.9.0以后:

该版本在yarn-site.xml中增加了yarn.resourcemanager.zk-max-znode-size.bytes参数,该参数定义了ZK的ZNode节点所能存储的最大数据量,以字节为单位,默认是1048576字节,也就是1MB。

2、Hadoop 2.9.0以前:

通过在/etc/hadoop/conf/yarn-env.sh设置-Djute.maxbuffer=<bytes>参数解决。ZK在创建客户端连接时,会自动读取jute.maxbuffer的值。在yarn-env.sh末尾增加配置如下,这里我设置该值为3145728字节,也就是3MB:

YARN_OPTS="$YARN_OPTS -Djute.maxbuffer=3145728"

无论采用以上哪一种解决方案,都必须使ZK客户端配置的值与ZK服务端的jute.maxbuffer参数值保持一致,如果要修改,需要同时修改ZK服务端的jute.maxbuffer参数,否则在ZK读写时会发生异常。配置不一致时发生异常如下:

  • ZK客户端的jute.maxbuffer参数值大于ZK服务端的jute.maxbuffer参数值:客户端向服务端写入的数据量超过服务端配置的值时抛出java.io.IOException: Len error异常

  • ZK客户端的jute.maxbuffer参数值小于ZK服务端的jute.maxbuffer参数值:客户端从服务端读取的数据量超过客户端配置的值时抛出java.io.IOException: Unreasonable length异常

相关思考

  • 为什么要限制ZK中ZNode的大小

ZK是一套高吞吐量的系统,为了提高系统的读取速度,ZK不允许从文件中读取需要的数据,而是直接从内存中查找。

换句话说,ZK集群中每一台服务器都包含全量的数据,并且这些数据都会加载到内存中,同时ZNode的数据不支持Append操作,全部都是Replace。

所以从上面分析可以看出,如果ZNode过大,那么读写某一个ZNode将造成不确定的延时,同时ZNode过大,将过快地耗尽ZK服务器的内存,这也是为什么ZK不适合存储大量数据的原因。

  • 如何提升ZK集群的性能

我们说性能,可以从两个方面去考虑:写入的性能与读取的性能。

由于ZK的写入首先需要通过Leader,然后这个写入的消息需要传播到半数以上的Follower通过才能完成整个写入,所以整个集群写入的性能无法通过增加服务器的数量达到目的,相反,整个集群中Follower数量越多,整个集群写入的性能越差。

ZK集群中的每一台服务器都可以提供数据的读取服务,所以整个集群中服务器的数量越多,读取的性能就越好,但是Follower增加又会降低整个集群的写入性能。

  • 在生产环境下配置,jute.maxbuffer参数的值的设置需要考虑哪些因素

首先,要考虑依赖ZK的服务数据量多大的问题。ZK作为一个分布式协调服务,它是要和其他服务整合才能发挥作用的。这里以YARN为例,YARN使用ZK做主备节点之间的故障转移,并且将RM的状态信息保存到ZK中。因此这里设置该参数的时候,要考虑这些数据信息有多大,故障转移节点保存的数据量很少,无非是主备节点的IP、host等信息。状态信息数据量相对来说比较大,RM将调度过程中产生的应用状态信息都保存到了ZK中,统计发现,我们现在出问题的YARN集群节点共有90个,高峰期任务数是节点数的3倍,每天调度几千个任务,任务量不是特别大,状态数据信息大部分在几百K到1M之间,偶尔会产生2M的状态数据信息,因此我们将该参数的值调整为3M。

其次,需要考虑改变该值之后,对其他依赖ZK的服务有没有影响。生产环境中,依赖ZK服务的服务有HBase、JStorm和Hadoop,理论上,这些服务都要修改各自客户端的该参数值,这是一个很繁琐的工作。目前从每天监控结果来看,其他服务保存在ZK中的数据,没有超过500K的,因此不需要改变客户端的该参数值。

最后,还要考虑读写场景和频率,因为数据量太大的话,读写还很多,可能会造成ZK服务端同步数据慢。

  • ZK中保存RM状态的ZNODE会不会越来越大?

不会。在一定条件下,RM会删除保存在ZK中的applicationId对应的状态数据,ZKRMStateStore中对应的逻辑如下:

public synchronized void removeApplicationStateInternal(ApplicationState appState)
            throws Exception {
        String appId = appState.getAppId().toString(); // 获取应用ID
        String appIdRemovePath = getNodePath(rmAppRoot, appId); // 根据应用ID获取对应的路径
        ArrayList<Op> opList = new ArrayList<Op>();

        // 执行状态信息删除操作
        for (ApplicationAttemptId attemptId : appState.attempts.keySet()) {
            String attemptRemovePath = getNodePath(appIdRemovePath, attemptId.toString());
            opList.add(Op.delete(attemptRemovePath, -1));
        }
        opList.add(Op.delete(appIdRemovePath, -1));

        if (LOG.isDebugEnabled()) {
            LOG.debug("Removing info for app: " + appId + " at: " + appIdRemovePath
                    + " and its attempts.");
        }
        doMultiWithRetries(opList);
    }
  • YARN为什么使用Protobuf

这是一个额外的话题,引入Protocal Buffer的一个最大好处——满足向后兼容性。具体原因参考<<YARN/MRv2 RPC框架深入剖析—引入Protocal Buffer的好处>>这篇文章。

参考资料

李亚坤:Hadoop YARN在字节跳动的实践——推荐,总结了头条在YARN使用和改造方面的经验

ResourceManager failed when ZKRMStateStore tries to update znode data larger than 1MB

RM状态存储与还原机制详解

Remove jute.maxbuffer limit packetLen in client side

YARN源码分析(三)-----ResourceManager HA之应用状态存储与恢复

源码走读-Yarn-ResourceManager01-基础概念

Zookeeper在RM HA的应用

YARN/MRv2 RPC框架深入剖析—引入Protocal Buffer的好处

Zookeeper 服务器端和客户端扩大节点数据1M大小限制

ZOOKEEPER jute.maxbuffer参数解惑

YARN架构深度解析:RM/NM/AM三层设计与Container资源隔离原理 YARN是Hadoop生态中实现多计算框架(如Spark、Flink、MapReduce)共享集群资源的核心调度框架,其本质是一套基于资源契约的分布式协调系统。它通过ResourceManager、NodeManager和ApplicationMaster的职责分离,解耦资源管理与任务调度,支撑高并发、多租户、可伸缩的生产级数据平台。关键技术价值在于以cgroups为底座的Container资源隔离机制,确保内存、CPU等硬性配额不被突破,从而避免作业间相互干扰。典型应用场景包括企业数据中台统一资源池建设、 阅读详情

相关推荐

YARN不是调度器,而是分布式操作系统内核

YARN是Hadoop生态中首个将计算资源抽象为可编程内核的分布式系统,其本质超越传统资源调度器,提供进程隔离、内存管控、故障自愈等操作系统级能力。它基于双层调度模型解耦全局资源仲裁(ResourceManager)与应用自治逻辑(ApplicationMaster),通过CGroups、Timeline Server、ZKRMStateStore等机制实现多租户安全与可观测性。在PB级数据平台实践中,YARN的配置偏差、内核参数冲突、版本契约断裂常导致Container OOM、AM注册失败、Timeli

weixin_30861797的博客 433

【Hadoop】resourcemanager.recovery.RMStateStore: State store operation failed

一、背景 今天又碰见了一个很鬼的问题,yarn的ui上nodemanager都是active,而且资源也完全充足,但是我提交任务的时候就卡主了!而且是什么类型的任务都提交不了,相当于yarn的服务直接不可用,关键是什么参数都没有修改,也没有重启yarn服务,突然他就不行了 二、查问题 所以我第一反应是查看resourcemanager的日志(记得要查看active的那台) 结果我看到了 ERROR org.apache.hadoop.yarn.server.resourcemanager.r.

lsr40的博客 1489

Hadoop生态全景解析:从HDFS/YARN到Spark/Flink的工程本质

分布式数据处理是现代大数据平台的核心能力,其底层依赖于可靠的分布式存储与智能资源调度。HDFS通过多副本与心跳机制实现统计级高可用,YARN解耦计算与存储资源,为Spark、Flink等引擎提供统一调度基础。MapReduce定义了‘移动计算而非数据’的范式,Spark以内存计算优化迭代任务,Flink则通过事件时间与状态管理实现真正流批一体。HBase弥补HDFS随机读写短板,Kafka承担高吞吐数据管道角色,Hive作为SQL翻译层降低使用门槛。这些组件并非孤立工具,而是围绕数据生命周期协同演进的有机系

weixin_33912453的博客 388

【总结】yarn ResourceManager 宕机重启总是失败解决排查

Yarn ResourceManager RM服务莫名其妙宕机,重启时报错,经过一番排查发现时内存不足OutOfMemory ,调大RM jvm 内存后的已解决。

Java高手真经 2136

Cloudera CDP实战指南:HDFS可靠性、YARN调优与混合治理

Cloudera Data Platform(CDP)已超越传统Hadoop发行版,演进为面向企业数据治理的操作系统。其核心在于统一元数据管理、动态安全策略与存储计算解耦架构,支撑金融、制造等关键行业对高可用、强合规与弹性扩展的刚性需求。HDFS底层可靠性设计决定集群容灾能力,YARN资源调度真实瓶颈直接影响Spark作业稳定性;而CDP Public Cloud与Private Cloud的混合治理逻辑,则解决了多云/本地数据协同、租户隔离与联邦查询等现实挑战。本文聚焦生产级CDP部署、HDFS脑裂防控、

weixin_34294649的博客 320

HiveServer2配置与Beeline连接实战:从单机到企业级数据服务

在大数据生态中,数据仓库服务化是支撑多用户并发访问和系统集成的关键架构演进。其核心原理在于通过常驻的、多线程的服务进程,对外提供标准化的JDBC/ODBC接口,将计算引擎与客户端解耦。这一架构的技术价值在于实现了统一的会话管理、资源调度和安全认证,使得数据分析平台能够高效、安全地服务众多分析师和业务系统。典型的应用场景包括企业级BI报表、数据应用集成以及调度任务执行。本文聚焦于HiveServer2这一具体实现,深入解析其核心配置参数,如`hive.server2.thrift.bind.host`和`hi

weixin_33672400的博客 484

YARN异常YarnException:Failed while publishing entity的解决方案

版本:HDP3.0 mapreduce提交任务计算时,job已经结束,但是容器仍不能关闭持续等待五分钟 INFO[Thread-100] org.apache.hadoop.yarn.event.AsyncDispatcher:Waiting for AsyncDispatcher to drain.Thread state is :WAITING 五分钟后抛出异常: org.apache.h...

superMario 3422

招聘数据分析全流程:Hadoop+爬虫+SpringBoot实现

大数据分析正在成为企业决策和人才市场洞察的核心能力,而数据采集、分布式存储与离线计算则是构建数据价值链条的基础。爬虫技术用于高效获取海量半结构化数据,Hadoop生态提供高容错的分布式存储与并行计算能力,通过MapReduce完成数据清洗、去重和特征提取,再结合SpringBoot构建Web服务,将分析结果以可视化方式呈现。这类技术组合广泛应用于招聘信息挖掘、行业薪资分析、技能需求图谱构建等场景,尤其适合需要处理多源异构数据的工程实践。本文基于招聘网站真实数据,完整拆解从爬虫采集、HDFS存储、MapRed

weixin_34006965的博客 375

如何关闭 org.apache.zookeeper.clientcnxn 的(控制台大量输出)debug 日志

如何关闭 org.apache.zookeeper.clientcnxn 的(控制台大量输出)debug 日志

comefromcq的专栏 7839

全国充电站分布数据

CnOpenData推出的充电站数据覆盖全国34个省份的3万条数据,包含充电站名称、省份名称、省份代码、商圈、经纬度等地理信息以及商业类型、评分、消费等衍生信息,能为城市规划、环境科学、市场分析、技术发展和社会经济研究等多个领域提供宝贵的数据支持。

Sunny9qx的博客 4024

3D模型文件格式全解析:从STL到glTF,10种主流格式与转换实战指南

在三维数字内容创作与工程制造领域,3D模型文件格式是数据交换与协作的基石。其核心原理在于以不同的数据结构(如三角网格、NURBS曲面、边界表示等)对三维物体的几何、外观及场景信息进行编码。理解这些格式的技术特性,对于保障数据完整性、提升工作流效率具有关键价值,广泛应用于3D打印、游戏开发、影视动画及工业设计等场景。例如,面向增材制造的STL格式以其极简的三角面片结构成为行业通用语,而支持丰富材质与动画的FBX格式则在影视游戏管线中扮演核心角色。本文聚焦于STL、OBJ、FBX、3MF、STEP等10种主流格

weixin_28520495的博客 354

org.apache.zookeeper.ClientCnxn: Opening socket connection to server localhost/127.0.0.1:218

在vmware中安装hadoop伪分布式,使用host-only模式使用hbase shell一直正常,后来为了能上网改为了Briged模式。 启动后再命令端看到了关于hbase的异常信息org.apache.zookeeper.ClientCnxn: Opening socket connection to server localhost/127.0.0.1:2181. Will not a

李战磊专栏 8万+

保姆级教程:用北醒TFmini-i-CAN雷达给PixHawk飞控加装‘眼睛’,实现自动避障与定高

经过多次测试,前向雷达的最佳安装位置是机架前部下方5-10cm处,倾斜角度20-30度。电源方面,建议为CAN设备单独供电,避免电机启动时的电压骤降导致数据异常。北醒TFmini-i-CAN雷达与PixHawk飞控的组合,为DIY爱好者打开了低成本实现智能避障的大门。实际部署时,需确保整个CAN网络的波特率一致(TFmini-i默认为250kbps),每个设备具有唯一ID。雷达的安装角度也直接影响检测效果,建议通过3D打印支架将雷达向前下方倾斜15-30度。当使用多个雷达时,需为每个设备创建独立的参数组。

weixin_30892889的博客 337

ZooKeeper节点数据量限制引起的Hadoop YARN ResourceManager崩溃原因分析(三)

阿里云协同办公工具Teambition 0元试用>>> ...

Viking的博客 1466

QGroundControl高级配置与自定义功能实战指南

本文深入探讨了QGroundControl(QGC)的高级配置与自定义功能,为无人机开发者、系统集成商和高级用户提供实战指南。内容涵盖从品牌界面定制、自定义MAVLink消息处理,到插件开发与自动化部署的全流程,旨在帮助用户解锁QGC的隐藏潜力,打造专属的行业解决方案。

weixin_29234509的博客 239

【Unity实战篇 】| 游戏中实现镂空遮罩效果【矩形、圆形镂空遮罩】

本文来写一下怎样在Unity中完成一个 镂空遮罩 的效果。 镂空遮罩 比较常用的有两种:矩形镂空遮罩、圆形镂空遮罩。 镂空遮罩 在游戏中常被当做新手引导必备的内容,可以给玩家更多不一样的体验。 下面就一起来看一下怎样做出这种效果吧!

努力前行,总会成为自己心中的那道光 1万+

ZooKeeper节点数据量限制引起的Hadoop YARN ResourceManager崩溃原因分析(二)

时隔五个月(点击阅读前文),如标题所示的问题再次发生,本次由于我们大数据监控系统的完善,让我对该问题进行了更深一步的研究。以下是整个排查过程和解决方案: 一、问题说明 从8月8日早上8点12收到第一条ResourceManager服务异常报警,截止到8月11日早上8点,每天早上8点到8点12之间频繁发生ResourceManager服务异常问题,晚上8点和下午1-3点偶尔出现该问题。以下是Spac...

Viking的博客 1756

华为OD机试双机位C卷-水库溃坝填补(Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【水库溃坝填补】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。水库溃坝填补。

qq_45776114的博客 2109

Hadoop工程师校招笔试核心考点:从HDFS到MapReduce的实战剖析

在大数据技术体系中,Hadoop生态始终是分布式存储与计算的基础底座。无论你是备战校招的应届生,还是刚入门的数据开发者,理解HDFS的副本机制与NameNode元数据管理、掌握MapReduce作业的执行生命周期与Shuffle原理,都是构建扎实技术功底的关键。进一步地,YARN资源调度、Zookeeper高可用协调、Hive与Spark的联动应用,则构成了生产环境下的完整技术链路。本文结合爱奇艺Hadoop工程师笔试真题,从存储、计算、调度、协同等层面拆解高频考点,并融入数据倾斜、小文件、集群调优等真实场

weixin_34211761的博客 483

骚戴笔记公告

骚戴笔记公告

我从不打没有准备的仗! 2万+

视觉测量实战:C#上位机+OpenCVSharp 实现工业零件尺寸自动检测(精准像素级,工业级可落地)

本次开发的上位机界面遵循工业现场操作规范简洁、直观、按钮大、文字清晰、参数可视化调节,操作人员为车间工人/质检员,无需复杂操作,所有控件均为WinForms原生控件,拖拽即可完成布局本次实战完成了C#上位机+OpenCVSharp 工业零件尺寸自动检测系统的完整开发,这套方案是工业视觉测量的标准落地方案,适配95%的规则几何零件的尺寸检测场景,从五金件、塑胶件到电子元件,全覆盖无死角。测量效率提升100倍、精度提升10倍、无人工误差、可适配流水线实时检测。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 848

Hadoop生态实战指南:从底层原理到电商全链路搭建

Hadoop生态并非孤立工具集合,而是围绕海量非结构化数据在廉价硬件上实现可靠存储、高效计算与实时服务的一整套工业级数据基础设施。其核心在于HDFS的分布式容错存储、YARN的统一资源调度、MapReduce奠定的批处理范式,以及Spark、Flink等引擎对延迟与一致性的分层优化。技术价值体现在解耦架构带来的资源复用性、跨组件协同形成的端到端数据闭环,以及面向业务场景(如实时风控、用户画像、OLAP分析)的精准能力匹配。本文以电商用户行为分析为典型场景,贯通Kafka接入、Flink实时处理、Hive数仓

weixin_33991418的博客 394

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Zookeeper面试八股文:从数据模型到ZAB协议,一文通关

在分布式系统设计中,一致性协调是绕不开的基础问题。ZooKeeper作为经典的分布式协调组件,通过树形数据模型和会话机制提供可靠的状态管理,而ZAB协议则保证了集群写操作的顺序性与多数派确认,从根本上解决了Leader选举和崩溃恢复的一致性难题。Watcher机制让客户端能够实时感知节点变化,以通知替代轮询,支撑起分布式锁、配置中心、服务注册发现等典型场景。理解这些底层原理,不仅能应对生产环境中的集群部署与故障排查,也能帮助工程师在Hadoop HA、Kafka Controller等生态整合中游刃有余。本

weixin_34306593的博客 316

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: Hadoop NameNode、DataNode热迁移方案
下一篇: OutOfMemoryError: GC Overhead Limit Exceeded错误解析
Viking_bird
博客等级 码龄11年 92粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值