diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/CommandCenterProvider.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/CommandCenterProvider.java index 99c77ff9..12bb1713 100644 --- a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/CommandCenterProvider.java +++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/command/CommandCenterProvider.java @@ -25,7 +25,7 @@ import com.alibaba.csp.sentinel.util.SpiLoader; * @author cdfive * @since 1.5.0 */ -public class CommandCenterProvider { +public final class CommandCenterProvider { private static CommandCenter commandCenter = null; @@ -34,10 +34,10 @@ public class CommandCenterProvider { } private static void resolveInstance() { - CommandCenter resolveCommandCenter = SpiLoader.loadFirstInstance(CommandCenter.class); + CommandCenter resolveCommandCenter = SpiLoader.loadHighestPriorityInstance(CommandCenter.class); if (resolveCommandCenter == null) { - RecordLog.warn("[CommandCenterProvider] No existing CommandCenter, resolve failed"); + RecordLog.warn("[CommandCenterProvider] WARN: No existing CommandCenter found"); } else { commandCenter = resolveCommandCenter; RecordLog.info("[CommandCenterProvider] CommandCenter resolved: " + resolveCommandCenter.getClass() diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/heartbeat/HeartbeatSenderProvider.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/heartbeat/HeartbeatSenderProvider.java new file mode 100644 index 00000000..c1d04f5c --- /dev/null +++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/heartbeat/HeartbeatSenderProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Alibaba Group Holding Ltd. + * + * Licensed 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.alibaba.csp.sentinel.heartbeat; + +import com.alibaba.csp.sentinel.log.RecordLog; +import com.alibaba.csp.sentinel.transport.HeartbeatSender; +import com.alibaba.csp.sentinel.util.SpiLoader; + +/** + * @author Eric Zhao + * @since 1.6.0 + */ +public final class HeartbeatSenderProvider { + + private static HeartbeatSender heartbeatSender = null; + + static { + resolveInstance(); + } + + private static void resolveInstance() { + HeartbeatSender resolved = SpiLoader.loadHighestPriorityInstance(HeartbeatSender.class); + if (resolved == null) { + RecordLog.warn("[HeartbeatSenderProvider] WARN: No existing HeartbeatSender found"); + } else { + heartbeatSender = resolved; + RecordLog.info("[HeartbeatSenderProvider] HeartbeatSender activated: " + resolved.getClass() + .getCanonicalName()); + } + } + + /** + * Get resolved {@link HeartbeatSender} instance. + * + * @return resolved {@code HeartbeatSender} instance + */ + public static HeartbeatSender getHeartbeatSender() { + return heartbeatSender; + } + + private HeartbeatSenderProvider() {} +} diff --git a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/transport/init/HeartbeatSenderInitFunc.java b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/transport/init/HeartbeatSenderInitFunc.java index 450df24d..47562305 100755 --- a/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/transport/init/HeartbeatSenderInitFunc.java +++ b/sentinel-transport/sentinel-transport-common/src/main/java/com/alibaba/csp/sentinel/transport/init/HeartbeatSenderInitFunc.java @@ -15,15 +15,16 @@ */ package com.alibaba.csp.sentinel.transport.init; -import java.util.Iterator; -import java.util.ServiceLoader; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy; import java.util.concurrent.TimeUnit; import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; import com.alibaba.csp.sentinel.config.SentinelConfig; +import com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider; import com.alibaba.csp.sentinel.init.InitFunc; +import com.alibaba.csp.sentinel.init.InitOrder; import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.transport.HeartbeatSender; import com.alibaba.csp.sentinel.transport.config.TransportConfig; @@ -33,30 +34,35 @@ import com.alibaba.csp.sentinel.transport.config.TransportConfig; * * @author Eric Zhao */ +@InitOrder(-1) public class HeartbeatSenderInitFunc implements InitFunc { - @SuppressWarnings("PMD.ThreadPoolCreationRule") - private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(2, - new NamedThreadFactory("sentinel-heartbeat-send-task", true)); + private ScheduledExecutorService pool = null; - private boolean validHeartbeatInterval(Long interval) { - return interval != null && interval > 0; + private void initSchedulerIfNeeded() { + if (pool == null) { + pool = new ScheduledThreadPoolExecutor(2, + new NamedThreadFactory("sentinel-heartbeat-send-task", true), + new DiscardOldestPolicy()); + } } @Override public void init() { - ServiceLoader loader = ServiceLoader.load(HeartbeatSender.class); - Iterator iterator = loader.iterator(); - if (iterator.hasNext()) { - final HeartbeatSender sender = iterator.next(); - if (iterator.hasNext()) { - throw new IllegalStateException("Only single heartbeat sender can be scheduled"); - } else { - long interval = retrieveInterval(sender); - setIntervalIfNotExists(interval); - scheduleHeartbeatTask(sender, interval); - } + HeartbeatSender sender = HeartbeatSenderProvider.getHeartbeatSender(); + if (sender == null) { + RecordLog.warn("[HeartbeatSenderInitFunc] WARN: No HeartbeatSender loaded"); + return; } + + initSchedulerIfNeeded(); + long interval = retrieveInterval(sender); + setIntervalIfNotExists(interval); + scheduleHeartbeatTask(sender, interval); + } + + private boolean isValidHeartbeatInterval(Long interval) { + return interval != null && interval > 0; } private void setIntervalIfNotExists(long interval) { @@ -65,13 +71,14 @@ public class HeartbeatSenderInitFunc implements InitFunc { long retrieveInterval(/*@NonNull*/ HeartbeatSender sender) { Long intervalInConfig = TransportConfig.getHeartbeatIntervalMs(); - if (validHeartbeatInterval(intervalInConfig)) { - RecordLog.info("[HeartbeatSenderInit] Using heartbeat interval in Sentinel config property: " + intervalInConfig); + if (isValidHeartbeatInterval(intervalInConfig)) { + RecordLog.info("[HeartbeatSenderInitFunc] Using heartbeat interval " + + "in Sentinel config property: " + intervalInConfig); return intervalInConfig; } else { long senderInterval = sender.intervalMs(); - RecordLog.info("[HeartbeatSenderInit] Heartbeat interval not configured in config property or invalid, " - + "using sender default: " + senderInterval); + RecordLog.info("[HeartbeatSenderInit] Heartbeat interval not configured in " + + "config property or invalid, using sender default: " + senderInterval); return senderInterval; } } diff --git a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/NettyHttpCommandCenter.java b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/NettyHttpCommandCenter.java index 82750b98..29adb01f 100755 --- a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/NettyHttpCommandCenter.java +++ b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/NettyHttpCommandCenter.java @@ -22,6 +22,7 @@ import java.util.concurrent.Executors; import com.alibaba.csp.sentinel.command.CommandHandler; import com.alibaba.csp.sentinel.command.CommandHandlerProvider; import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; +import com.alibaba.csp.sentinel.spi.SpiOrder; import com.alibaba.csp.sentinel.transport.command.netty.HttpServer; import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.transport.CommandCenter; @@ -31,6 +32,7 @@ import com.alibaba.csp.sentinel.transport.CommandCenter; * * @author Eric Zhao */ +@SpiOrder(SpiOrder.LOWEST_PRECEDENCE - 100) public class NettyHttpCommandCenter implements CommandCenter { private final HttpServer server = new HttpServer(); diff --git a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/heartbeat/HttpHeartbeatSender.java b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/heartbeat/HttpHeartbeatSender.java index 138d92a5..b528a4a4 100755 --- a/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/heartbeat/HttpHeartbeatSender.java +++ b/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/heartbeat/HttpHeartbeatSender.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.csp.sentinel.Constants; +import com.alibaba.csp.sentinel.spi.SpiOrder; import com.alibaba.csp.sentinel.transport.config.TransportConfig; import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.util.AppNameUtil; @@ -39,6 +40,7 @@ import org.apache.http.impl.client.HttpClients; * @author Eric Zhao * @author leyou */ +@SpiOrder(SpiOrder.LOWEST_PRECEDENCE - 100) public class HttpHeartbeatSender implements HeartbeatSender { private final CloseableHttpClient client;