order
This paper focuses on the network health check of artemis
NetworkHealthCheck
activemq-artemis-2.11.0/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java
public class NetworkHealthCheck extends ActiveMQScheduledComponent { private static final Logger logger = Logger.getLogger(NetworkHealthCheck.class); private final Set<ActiveMQComponent> componentList = new ConcurrentHashSet<>(); private final Set<InetAddress> addresses = new ConcurrentHashSet<>(); private final Set<URL> urls = new ConcurrentHashSet<>(); private NetworkInterface networkInterface; public static final String IPV6_DEFAULT_COMMAND = "ping6 -c 1 %2$s"; public static final String IPV4_DEFAULT_COMMAND = "ping -c 1 -t %d %s"; private String ipv4Command = IPV4_DEFAULT_COMMAND; private String ipv6Command = IPV6_DEFAULT_COMMAND; // To be used on tests. As we use the loopback as a valid address on tests. private boolean ignoreLoopback = false; private boolean ownShutdown = false; /** * The timeout to be used on isReachable */ private int networkTimeout; //...... public void run() { boolean healthy = check(); if (healthy) { for (ActiveMQComponent component : componentList) { if (!component.isStarted() && ownShutdown) { try { ActiveMQUtilLogger.LOGGER.startingService(component.toString()); component.start(); } catch (Exception e) { ActiveMQUtilLogger.LOGGER.errorStartingComponent(e, component.toString()); } } ownShutdown = false; } } else { for (ActiveMQComponent component : componentList) { if (component.isStarted()) { ownShutdown = true; try { ActiveMQUtilLogger.LOGGER.stoppingService(component.toString()); component.stop(); } catch (Exception e) { ActiveMQUtilLogger.LOGGER.errorStoppingComponent(e, component.toString()); } } } } } //...... }
- NetworkHealthCheck inherits ActiveMQScheduledComponent. Its run method first performs check to determine whether it is healthy, and then traverses the componentList. For non healthy updates with component.isStarted() true, ownShutdown is true, and then component.stop(); for healthy updates with component.isStarted() false and ownShutdown is true, component.start() is the most important Update ownShutdown to false after
check
activemq-artemis-2.11.0/artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java
public class NetworkHealthCheck extends ActiveMQScheduledComponent { //...... public boolean check() { if (isEmpty()) { return true; } for (InetAddress address : addresses) { if (check(address)) { return true; } } for (URL url : urls) { if (check(url)) { return true; } } return false; } public boolean isEmpty() { return addresses.isEmpty() && urls.isEmpty(); } public boolean check(InetAddress address) { if (address == null) { return false; } try { if (!hasCustomPingCommand() && isReachable(address)) { if (logger.isTraceEnabled()) { logger.tracef(address + " OK"); } return true; } else { return purePing(address); } } catch (Exception e) { ActiveMQUtilLogger.LOGGER.failedToCheckAddress(e, address.toString()); return false; } } public boolean hasCustomPingCommand() { return !getIpv4Command().equals(IPV4_DEFAULT_COMMAND) || !getIpv6Command().equals(IPV6_DEFAULT_COMMAND); } protected boolean isReachable(InetAddress address) throws IOException { return address.isReachable(networkInterface, 0, networkTimeout); } public boolean purePing(InetAddress address) throws IOException, InterruptedException { long timeout = Math.max(1, TimeUnit.MILLISECONDS.toSeconds(networkTimeout)); // it did not work with a simple isReachable, it could be because there's no root access, so we will try ping executable if (logger.isTraceEnabled()) { logger.trace("purePing on canonical address " + address.getCanonicalHostName()); } ProcessBuilder processBuilder; if (address instanceof Inet6Address) { processBuilder = buildProcess(ipv6Command, timeout, address.getCanonicalHostName()); } else { processBuilder = buildProcess(ipv4Command, timeout, address.getCanonicalHostName()); } Process pingProcess = processBuilder.start(); readStream(pingProcess.getInputStream(), false); readStream(pingProcess.getErrorStream(), true); return pingProcess.waitFor() == 0; } public boolean check(URL url) { if (url == null) { return false; } try { URLConnection connection = url.openConnection(); connection.setReadTimeout(networkTimeout); InputStream is = connection.getInputStream(); is.close(); return true; } catch (Exception e) { ActiveMQUtilLogger.LOGGER.failedToCheckURL(e, url.toString()); return false; } } //...... }
- The check method returns true for the addresses and urls that are empty, and then performs check by traversing the addresses and urls one by one; for the check of InetAddress, returns true when the hasCustomPingCommand method returns false and isReachable returns true, otherwise use purePing to check; the purePing method uses Process to ping; for the check of url, use the URLConnection of jdk to check openConnection, success returns true, timeout or other exceptions returns false
Summary
NetworkHealthCheck inherits ActiveMQScheduledComponent. Its run method first performs check to determine whether it is healthy, and then traverses the componentList. For non healthy updates with component.isStarted() true, ownShutdown is true, and then component.stop(); for healthy updates with component.isStarted() false and ownShutdown is true, component.start() is the most important Update ownShutdown to false after