Skip to content

Commit

Permalink
Merge pull request #3024: Add traffic routing capability
Browse files Browse the repository at this point in the history
* Support traffic routing capability.
  • Loading branch information
sczyh30 authored Feb 14, 2023
2 parents 4bfd321 + 19ecab4 commit f10aedd
Show file tree
Hide file tree
Showing 44 changed files with 2,824 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.List;

/**
* @author panxiaojun233
*/
public abstract class AbstractLoadBalancer implements LoadBalancer {
@Override
public Instance select(List<Instance> instances, TrafficContext trafficContext) throws TrafficException {
if (instances == null || instances.size() == 0) {
return null;
}
if (instances.size() == 1) {
return instances.get(0);
}
return doSelect(instances, trafficContext);
}

protected abstract Instance doSelect(List<Instance> instances, TrafficContext trafficContext);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.csp.sentinel.traffic.rule.router.TrafficRouterRuleManager;

/**
* @author panxiaojun233
*/
public class ClusterManager implements InstanceListener {
private List<RouterFilter> routerFilterList;
private LoadBalancer loadBalancer;
private InstanceManager instanceManager;
private volatile Set<String> remoteAppName = Collections.emptySet();

public ClusterManager(List<RouterFilter> routerFilterList, LoadBalancer loadBalancer, InstanceManager instanceManager) {
this.routerFilterList = routerFilterList;
this.loadBalancer = loadBalancer;
this.instanceManager = instanceManager;
}

public Set<String> getRemoteAppName() {
return remoteAppName;
}

public ClusterManager(List<RouterFilter> routerFilterList) {
this.routerFilterList = routerFilterList;
}

public ClusterManager(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}

/**
* Select one invoker in list, routing first, then load balancing.
*
* @param context traffic context.
* @return selected instance.
*/
public Instance selectOneInstance(TrafficContext context) {
return loadBalancer.select(route(context), context);
}

/**
* Select one invoker in list.
*
* @param context traffic context.
* @param instances instance List.
* @return selected instance.
*/
public Instance loadBalance(TrafficContext context, List<Instance> instances) {
return loadBalancer.select(instances, context);
}

public Instance loadBalance(TrafficContext context) {
return loadBalancer.select(instanceManager.getInstances(), context);
}

/**
* Filter instances form instanceManager by current routing rule and traffic context.
*
* @param context traffic context
* @return instance List
*/
public List<Instance> route(TrafficContext context) {
List<Instance> instances = instanceManager.getInstances();
for (RouterFilter routerFilter : routerFilterList) {
instances = routerFilter.filter(instances, context);
}
return instances;
}

/**
* Register the application in the instance List.
*
* @param instances instance List
*/
private void registerAppRule(List<Instance> instances) {
Set<String> currentApplication = new HashSet<>();
if (instances != null && instances.size() > 0) {
for (Instance instance : instances) {
String applicationName = instance.getAppName();
if (applicationName != null && applicationName.length() > 0) {
currentApplication.add(applicationName);
}
}
}

if (!remoteAppName.equals(currentApplication)) {
synchronized (this) {
Set<String> current = new HashSet<>(currentApplication);
Set<String> previous = new HashSet<>(remoteAppName);
previous.removeAll(currentApplication);
current.removeAll(remoteAppName);
for (String app : current) {
TrafficRouterRuleManager.register(app);
}
for (String app : previous) {
TrafficRouterRuleManager.unregister(app);
}
remoteAppName = currentApplication;
}
}
}

@Override
public void notify(List<Instance> instances) {
registerAppRule(instances);
instanceManager.storeInstances(instances);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.List;

/**
* @author panxiaojun233
*/
public class DefaultInstanceListener implements InstanceListener {

private InstanceManager instanceManager;

public DefaultInstanceListener(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}

@Override
public void notify(List<Instance> instances) {
instanceManager.storeInstances(instances);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author panxiaojun233
*/
public class DefaultInstanceManager implements InstanceManager {

private volatile List<Instance> instanceList = Collections.emptyList();

@Override
public void storeInstances(List<Instance> instances) {
if (instances == null || instances.size() == 0) {
return;
}
instanceList = new ArrayList<>(instances);
}

@Override
public List<Instance> getInstances() {
return instanceList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.Map;

/**
* @author panxiaojun233
*/
public class Instance {
private String appName;
private String host;
private Integer port;
private Map<String, String> metadata;
private Object targetInstance;

public String getAppName() {
return appName;
}

public void setAppName(String appName) {
this.appName = appName;
}

public Object getTargetInstance() {
return targetInstance;
}

public void setTargetInstance(Object targetInstance) {
this.targetInstance = targetInstance;
}

public String getHost() {
return host;
}

public void setHost(String host) {
this.host = host;
}

public Integer getPort() {
return port;
}

public void setPort(Integer port) {
this.port = port;
}

public Map<String, String> getMetadata() {
return metadata;
}

public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}

@Override
public String toString() {
return "Instance{" +
"appName='" + appName + '\'' +
", host='" + host + '\'' +
", port=" + port +
", metadata=" + metadata +
", targetInstance=" + targetInstance +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.List;

/**
* @author panxiaojun233
*/
public interface InstanceListener {

/**
* Notify the {@link ClusterManager} the instance list. Instance list may change from time to time.
*
* @param instances instance list.
*/
void notify(List<Instance> instances);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 1999-2018 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
*
* http://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.traffic;

import java.util.List;

/**
* @author panxiaojun233
*/
public interface InstanceManager {

/**
* store the instance list from {@link InstanceListener#notify(List)}.
*
* @param instances
*/
void storeInstances(List<Instance> instances);

List<Instance> getInstances();
}
Loading

0 comments on commit f10aedd

Please sign in to comment.