diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/LocalFirstMode.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/LocalFirstMode.java index 1ccdff02b..cdd163ac8 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/LocalFirstMode.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/LocalFirstMode.java @@ -28,5 +28,10 @@ public enum LocalFirstMode { /** * Local-first routing is applied at the cluster level. */ - CLUSTER + CLUSTER, + + /** + * Local-first routing is applied at the cloud level. + */ + CLOUD } \ No newline at end of file diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CellFilter.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CellFilter.java index 3c840d436..613344708 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CellFilter.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CellFilter.java @@ -15,10 +15,9 @@ */ package com.jd.live.agent.governance.invoke.filter.route; -import com.jd.live.agent.core.extension.annotation.ConditionalOnProperty; import com.jd.live.agent.core.extension.annotation.Extension; import com.jd.live.agent.core.instance.Location; -import com.jd.live.agent.governance.config.GovernanceConfig; +import com.jd.live.agent.governance.annotation.ConditionalOnGovernanceEnabled; import com.jd.live.agent.governance.config.LocalFirstMode; import com.jd.live.agent.governance.config.ServiceConfig; import com.jd.live.agent.governance.instance.CellGroup; @@ -53,7 +52,7 @@ * @since 1.0.0 */ @Extension(value = "CellFilter", order = RouteFilter.ORDER_LIVE_CELL) -@ConditionalOnProperty(value = GovernanceConfig.CONFIG_LIVE_ENABLED, matchIfMissing = true) +@ConditionalOnGovernanceEnabled public class CellFilter implements RouteFilter { @Override @@ -183,11 +182,11 @@ private List routeCluster(List endpoints /** * Routes an outbound invocation to suitable endpoints * - * @param invocation The outbound invocation containing metadata for the election. - * @param target The {@code RouteTarget} containing the endpoints to be filtered. - * @param localFirst Local first mode. + * @param invocation The outbound invocation containing metadata for the election. + * @param target The {@code RouteTarget} containing the endpoints to be filtered. + * @param localFirst Local first mode. * @param thresholdFunc A function that returns a threshold value for the current cell. If the number of local endpoints exceeds this threshold, - * those endpoints are preferred. + * those endpoints are preferred. * @return true if the routing decision was successful, false otherwise. */ private boolean routeAny(OutboundInvocation invocation, @@ -195,15 +194,14 @@ private boolean routeAny(OutboundInvocation invocation, LocalFirstMode localFirst, Function thresholdFunc) { LiveMetadata liveMetadata = invocation.getLiveMetadata(); - LiveSpace targetSpace = liveMetadata.getTargetSpace(); - if (targetSpace == null) { - return true; - } - Unit preferUnit = localFirst != null ? targetSpace.getLocalUnit() : null; - Unit centerUnit = targetSpace.getCenter(); - Cell preferCell = localFirst != null ? targetSpace.getLocalCell() : null; - String preferCloud = localFirst != null ? invocation.getContext().getLocation().getCloud() : null; - String cluster = localFirst == LocalFirstMode.CLUSTER ? invocation.getContext().getLocation().getCluster() : null; + LiveSpace targetSpace = liveMetadata != null ? liveMetadata.getTargetSpace() : null; + + String preferCluster = localFirst == LocalFirstMode.CLUSTER ? invocation.getContext().getLocation().getCluster() : null; + String preferCloud = localFirst == LocalFirstMode.CLOUD ? invocation.getContext().getLocation().getCloud() : null; + Unit preferUnit = localFirst != null && targetSpace != null ? targetSpace.getLocalUnit() : null; + Unit centerUnit = targetSpace != null ? targetSpace.getCenter() : null; + Cell preferCell = localFirst != null && targetSpace != null ? targetSpace.getLocalCell() : null; + Set unavailableCells = getUnavailableCells(invocation); if (!unavailableCells.isEmpty()) { target.filter(endpoint -> !unavailableCells.contains(endpoint.getCell())); @@ -218,13 +216,7 @@ private boolean routeAny(OutboundInvocation invocation, for (Endpoint endpoint : target.getEndpoints()) { if (preferUnit != null && endpoint.isUnit(preferUnit.getCode())) { if (preferCell != null && endpoint.isCell(preferCell.getCode())) { - if (cluster != null && endpoint.isCluster(cluster)) { - preferClusterEndpoints.add(endpoint); - } else { - preferCellEndpoints.add(endpoint); - } - } else if (preferCloud != null && endpoint.isCloud(preferCloud)) { - preferCloudEndpoints.add(endpoint); + preferCellEndpoints.add(endpoint); } else { preferUnitEndpoints.add(endpoint); } @@ -233,6 +225,12 @@ private boolean routeAny(OutboundInvocation invocation, } else { otherUnitEndpoints.add(endpoint); } + if (preferCluster != null && endpoint.isCluster(preferCluster)) { + preferClusterEndpoints.add(endpoint); + } + if (preferCloud != null && endpoint.isCloud(preferCloud)) { + preferCloudEndpoints.add(endpoint); + } } List[] candidates = new List[]{ preferClusterEndpoints, preferCellEndpoints, preferCloudEndpoints, @@ -264,13 +262,13 @@ private boolean routeAny(OutboundInvocation invocation, /** * Returns a set of cell codes that are not available. * - * @param invocation The outbound invocation containing metadata for the election. + * @param invocation The outbound invocation containing metadata for the election. * @return A set of cell codes that are not accessible for the given invocation and live metadata. */ private Set getUnavailableCells(OutboundInvocation invocation) { Set unavailableCells = new HashSet<>(); LiveMetadata metadata = invocation.getLiveMetadata(); - List units = metadata.getTargetSpace().getSpec().getUnits(); + List units = metadata != null ? metadata.getTargetSpace().getSpec().getUnits() : null; if (units != null) { UnitRule rule = metadata.getRule(); @@ -622,7 +620,7 @@ private static class Candidate { * @param weight The weight of this candidate. * @param priority The priority of this candidate. * @param threshold The threshold value for this candidate. - * @param cloud The cloud value for this candidate. + * @param cloud The cloud value for this candidate. */ Candidate(CellRoute cellRoute, int instance, int weight, int priority, int threshold, String cloud) { this.cellRoute = cellRoute; diff --git a/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveLocation.java b/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveLocation.java index 28f3a8b6c..930de04e7 100644 --- a/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveLocation.java +++ b/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveLocation.java @@ -27,6 +27,8 @@ public class LiveLocation implements Serializable { private String liveSpaceId; private String unit; private String cell; + private String cluster; + private String cloud; private String ruleId; private String laneSpaceId; private String lane; @@ -36,10 +38,12 @@ public LiveLocation() { } - public LiveLocation(String liveSpaceId, String unit, String cell, String ruleId, String laneSpaceId, String lane) { + public LiveLocation(String liveSpaceId, String unit, String cell, String cluster, String cloud, String ruleId, String laneSpaceId, String lane) { this.liveSpaceId = liveSpaceId; this.unit = unit; this.cell = cell; + this.cluster = cluster; + this.cloud = cloud; this.ruleId = ruleId; this.laneSpaceId = laneSpaceId; this.lane = lane; @@ -51,6 +55,8 @@ public static LiveLocation build() { System.getProperty(LiveTransmission.X_LIVE_SPACE_ID), System.getProperty(LiveTransmission.X_LIVE_UNIT), System.getProperty(LiveTransmission.X_LIVE_CELL), + System.getProperty(LiveTransmission.X_LIVE_CLUSTER), + System.getProperty(LiveTransmission.X_LIVE_CLOUD), System.getProperty(LiveTransmission.X_LIVE_RULE_ID), System.getProperty(LiveTransmission.X_LANE_SPACE_ID), System.getProperty(LiveTransmission.X_LANE_CODE) @@ -63,6 +69,8 @@ public String toString() { "live-space-id=" + (liveSpaceId == null ? "null" : ('\'' + liveSpaceId + '\'')) + ", unit=" + (unit == null ? "null" : ('\'' + unit + '\'')) + ", cell=" + (cell == null ? "null" : ('\'' + cell + '\'')) + + ", cluster=" + (cluster == null ? "null" : ('\'' + cluster + '\'')) + + ", cloud=" + (cloud == null ? "null" : ('\'' + cloud + '\'')) + ", ruleId=" + (ruleId == null ? "null" : ('\'' + ruleId + '\'')) + ", lane-space-id=" + (laneSpaceId == null ? "null" : ('\'' + laneSpaceId + '\'')) + ", lane=" + (lane == null ? "null" : ('\'' + lane + '\'')) + diff --git a/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveTransmission.java b/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveTransmission.java index 2ea1cc9e6..80606a979 100644 --- a/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveTransmission.java +++ b/joylive-demo/joylive-demo-common/joylive-demo-api/src/main/java/com/jd/live/agent/demo/response/LiveTransmission.java @@ -27,6 +27,8 @@ public class LiveTransmission implements Serializable { public static final String X_LIVE_SPACE_ID = "x-live-space-id"; public static final String X_LIVE_UNIT = "x-live-unit"; public static final String X_LIVE_CELL = "x-live-cell"; + public static final String X_LIVE_CLUSTER = "x-live-cluster"; + public static final String X_LIVE_CLOUD = "x-live-cloud"; public static final String X_LIVE_RULE_ID = "x-live-rule-id"; public static final String X_LIVE_UID = "x-live-uid"; public static final String X_LANE_SPACE_ID = "x-lane-space-id";