ARTEMIS-3664 Critical Analyzer should not HALT or STOP the broker during the startup

This commit is contained in:
Clebert Suconic 2022-01-31 11:59:11 -05:00 committed by clebertsuconic
parent 4a6a74e1c3
commit ba02fccb77
6 changed files with 174 additions and 29 deletions

View File

@ -149,7 +149,7 @@ public class CriticalAnalyzerImpl implements CriticalAnalyzer {
}
}
private void fireActions(CriticalComponent component) {
protected void fireActions(CriticalComponent component) {
for (CriticalAction action : actions) {
try {
action.run(component);

View File

@ -0,0 +1,26 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.utils.critical;
public class CriticalAnalyzerAccessor {
public static void fireActions(CriticalAnalyzer impl, CriticalComponent component) {
((CriticalAnalyzerImpl)impl).fireActions(component);
}
}

View File

@ -2216,4 +2216,8 @@ public interface ActiveMQServerLogger extends BasicLogger {
@Message(id = 224115, value = "Address control unblock of address ''{0}''. Clients will be granted credit as normal.", format = Message.Format.MESSAGE_FORMAT)
void unblockingViaControl(SimpleString addressName);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 224116, value = "The component {0} is not responsive during start up. The Server may be taking too long to start", format = Message.Format.MESSAGE_FORMAT)
void tooLongToStart(Object component);
}

View File

@ -704,7 +704,13 @@ public class ActiveMQServerImpl implements ActiveMQServer {
}
}
private void initializeCriticalAnalyzer() throws Exception {
private void takingLongToStart(Object criticalComponent) {
ActiveMQServerLogger.LOGGER.tooLongToStart(criticalComponent);
threadDump();
}
protected void initializeCriticalAnalyzer() throws Exception {
// Some tests will play crazy frequenceistop/start
CriticalAnalyzer analyzer = this.getCriticalAnalyzer();
@ -735,49 +741,61 @@ public class ActiveMQServerImpl implements ActiveMQServer {
case HALT:
criticalAction = criticalComponent -> {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemHalt(criticalComponent);
if (ActiveMQServerImpl.this.state == SERVER_STATE.STARTING) {
takingLongToStart(criticalComponent);
} else {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemHalt(criticalComponent);
threadDump();
sendCriticalNotification(criticalComponent);
threadDump();
sendCriticalNotification(criticalComponent);
Runtime.getRuntime().halt(70); // Linux systems will have /usr/include/sysexits.h showing 70 as internal software error
Runtime.getRuntime().halt(70); // Linux systems will have /usr/include/sysexits.h showing 70 as internal software error
}
};
break;
case SHUTDOWN:
criticalAction = criticalComponent -> {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemShutdown(criticalComponent);
if (ActiveMQServerImpl.this.state == SERVER_STATE.STARTING) {
takingLongToStart(criticalComponent);
} else {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemShutdown(criticalComponent);
threadDump();
threadDump();
// on the case of a critical failure, -1 cannot simply means forever.
// in case graceful is -1, we will set it to 30 seconds
sendCriticalNotification(criticalComponent);
// on the case of a critical failure, -1 cannot simply means forever.
// in case graceful is -1, we will set it to 30 seconds
sendCriticalNotification(criticalComponent);
// you can't stop from the check thread,
// nor can use an executor
Thread stopThread = new Thread() {
@Override
public void run() {
try {
ActiveMQServerImpl.this.stop();
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
// you can't stop from the check thread,
// nor can use an executor
Thread stopThread = new Thread() {
@Override
public void run() {
try {
ActiveMQServerImpl.this.stop();
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
}
}
}
};
stopThread.start();
};
stopThread.start();
}
};
break;
case LOG:
criticalAction = criticalComponent -> {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemLog(criticalComponent);
threadDump();
sendCriticalNotification(criticalComponent);
if (ActiveMQServerImpl.this.state == SERVER_STATE.STARTING) {
takingLongToStart(criticalComponent);
} else {
checkCriticalAnalyzerLogging();
ActiveMQServerLogger.LOGGER.criticalSystemLog(criticalComponent);
threadDump();
sendCriticalNotification(criticalComponent);
}
};
break;
}

View File

@ -0,0 +1,27 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.server.impl;
public class ActiveMQServerImplAccessor {
public static void initializeCriticalAnalyzer(ActiveMQServerImpl server) throws Exception {
server.initializeCriticalAnalyzer();
}
}

View File

@ -0,0 +1,70 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.server.impl;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerAccessor;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
import org.apache.activemq.artemis.utils.critical.CriticalComponentImpl;
import org.junit.Assert;
import org.junit.Test;
public class ActiveMQServerStartupTest extends ActiveMQTestBase {
@Test
public void testTooLongToStartHalt() throws Exception {
testTooLongToStart(CriticalAnalyzerPolicy.HALT);
}
@Test
public void testTooLongToStartShutdown() throws Exception {
testTooLongToStart(CriticalAnalyzerPolicy.SHUTDOWN);
}
@Test
public void testTooLongToStartLOG() throws Exception {
testTooLongToStart(CriticalAnalyzerPolicy.LOG);
}
private void testTooLongToStart(CriticalAnalyzerPolicy policy) throws Exception {
AssertionLoggerHandler.startCapture();
try {
ConfigurationImpl configuration = new ConfigurationImpl();
configuration.setCriticalAnalyzerPolicy(policy);
configuration.setCriticalAnalyzer(true);
configuration.setPersistenceEnabled(false);
ActiveMQServerImpl server = new ActiveMQServerImpl(configuration);
addServer(server);
server.start();
// this will be faking a condition
server.setState(ActiveMQServer.SERVER_STATE.STARTING);
CriticalAnalyzerAccessor.fireActions(server.getCriticalAnalyzer(), new CriticalComponentImpl(server.getCriticalAnalyzer(), 2));
Assert.assertTrue(AssertionLoggerHandler.findText("224116"));
Assert.assertEquals(ActiveMQServer.SERVER_STATE.STARTING, server.getState()); // should not be changed
server.stop();
} finally {
AssertionLoggerHandler.stopCapture();
}
}
}