Skip to content
Permalink
Browse files
Fix and optimize some problems of conditional routing when using ZK t…
…o make it work (#704)

* Fix and optimize some problems of conditional routing when using ZK to make it work

* Fix UT problem
  • Loading branch information
KeRan213539 committed Mar 19, 2021
1 parent 810e7a7 commit a7dc202c96383f84f9b029dbe878a66b3ff332e2
Showing 17 changed files with 3,334 additions and 3,146 deletions.
@@ -78,6 +78,7 @@ public class Constants {
public static final String METRICS_PORT = "metrics.port";
public static final String METRICS_PROTOCOL = "metrics.protocol";
public static final Set<String> CONFIGS = new HashSet<>();
public static final String COLON = ":";

static {
CONFIGS.add(WEIGHT);
@@ -24,6 +24,8 @@
import java.util.List;
import java.util.Map;

import static org.apache.dubbo.admin.common.util.Constants.COLON;

public class ConvertUtil {
private ConvertUtil() {
}
@@ -52,11 +54,49 @@ public static String getIdFromDTO(BaseDTO baseDTO) {
if (StringUtils.isNotEmpty(baseDTO.getApplication())) {
id = baseDTO.getApplication();
} else {
id = baseDTO.getService();
// id format: "${class}:${version}:${group}"
id = new StringBuilder(baseDTO.getService()).append(COLON).append(null2EmptyString(baseDTO.getServiceVersion()))
.append(COLON).append(null2EmptyString(baseDTO.getServiceGroup())).toString();
}
return id;
}

/**
* Detach interface class, version and group from id.
* @param id
* @return java.lang.String[] 0: interface class; 1: version; 2: group
*/
public static String[] detachId(String id) {
if (id.contains(COLON)) {
return id.split(COLON);
} else {
return new String[]{id};
}
}

public static String getServiceIdFromDTO(BaseDTO baseDTO, boolean groupAsFolder) {
StringBuilder buf = new StringBuilder();
buf.append(baseDTO.getService());
if (StringUtils.isNotEmpty(baseDTO.getServiceVersion())) {
buf.append(COLON).append(baseDTO.getServiceVersion());
}
if (StringUtils.isNotEmpty(baseDTO.getServiceGroup())) {
if (groupAsFolder) {
buf.insert(0, baseDTO.getServiceGroup() + "/");
} else {
buf.append(COLON).append(baseDTO.getServiceGroup());
}
}
return buf.toString();
}

public static String null2EmptyString(String str) {
if (null == str) {
str = StringUtils.EMPTY_STRING;
}
return str;
}

public static String getScopeFromDTO(BaseDTO baseDTO) {
if (StringUtils.isNotEmpty(baseDTO.getApplication())) {
return org.apache.dubbo.admin.common.util.Constants.APPLICATION;
@@ -25,6 +25,8 @@
import java.util.List;
import java.util.Map;

import static org.apache.dubbo.admin.common.util.Constants.COLON;

public class SyncUtils {

public static final String SERVICE_FILTER_KEY = ".service";
@@ -33,8 +35,6 @@ public class SyncUtils {

public static final String ID_FILTER_KEY = ".id";

public static final String COLON = ":";

public static Provider url2Provider(Pair<String, URL> pair) {
if (pair == null) {
return null;
@@ -64,14 +64,21 @@ public boolean createRule(@RequestBody ConditionRouteDTO routeDTO, @PathVariable
if (StringUtils.isNotEmpty(app) && providerService.findVersionInApplication(app).equals("2.6")) {
throw new VersionValidationException("dubbo 2.6 does not support application scope routing rule");
}

routeService.createConditionRoute(routeDTO);
return true;
}

@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDTO newConditionRoute, @PathVariable String env) {
public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDTO newConditionRoute, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
ConditionRouteDTO oldConditionRoute = routeService.findConditionRoute(id);
ConditionRouteDTO crDTO = new ConditionRouteDTO();
crDTO.setService(id);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
ConditionRouteDTO oldConditionRoute = routeService.findConditionRoute(crDTO);
if (oldConditionRoute == null) {
throw new ResourceNotFoundException("can not find route rule for: " + id);
}
@@ -81,13 +88,20 @@ public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDT

@RequestMapping(method = RequestMethod.GET)
public List<ConditionRouteDTO> searchRoutes(@RequestParam(required = false) String application,
@RequestParam(required = false) String service, @PathVariable String env) {
ConditionRouteDTO conditionRoute = null;
@RequestParam(required = false) String service, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
ConditionRouteDTO conditionRoute;
List<ConditionRouteDTO> result = new ArrayList<>();
ConditionRouteDTO crDTO = new ConditionRouteDTO();
if (StringUtils.isNotBlank(application)) {
conditionRoute = routeService.findConditionRoute(application);
crDTO.setService(application);
conditionRoute = routeService.findConditionRoute(crDTO);
} else if (StringUtils.isNotBlank(service)) {
conditionRoute = routeService.findConditionRoute(service);
crDTO.setService(service);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
conditionRoute = routeService.findConditionRoute(crDTO);
} else {
throw new ParamValidationException("Either Service or application is required.");
}
@@ -98,33 +112,57 @@ public List<ConditionRouteDTO> searchRoutes(@RequestParam(required = false) Stri
}

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ConditionRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
public ConditionRouteDTO detailRoute(@PathVariable String id, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
ConditionRouteDTO conditionRoute = routeService.findConditionRoute(id);
ConditionRouteDTO crDTO = new ConditionRouteDTO();
crDTO.setService(id);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
ConditionRouteDTO conditionRoute = routeService.findConditionRoute(crDTO);
if (conditionRoute == null || conditionRoute.getConditions() == null) {
throw new ResourceNotFoundException("Unknown ID!");
}
return conditionRoute;
}

@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
public boolean deleteRoute(@PathVariable String id, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
routeService.deleteConditionRoute(id);
ConditionRouteDTO crDTO = new ConditionRouteDTO();
crDTO.setService(id);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
routeService.deleteConditionRoute(crDTO);
return true;
}

@RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
public boolean enableRoute(@PathVariable String id, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
routeService.enableConditionRoute(id);
ConditionRouteDTO crDTO = new ConditionRouteDTO();
crDTO.setService(id);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
routeService.enableConditionRoute(crDTO);
return true;
}

@RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
public boolean disableRoute(@PathVariable String id, @PathVariable String env,
@RequestParam(required = false) String serviceVersion,
@RequestParam(required = false) String serviceGroup) {
id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
routeService.disableConditionRoute(id);
ConditionRouteDTO crDTO = new ConditionRouteDTO();
crDTO.setService(id);
crDTO.setServiceVersion(serviceVersion);
crDTO.setServiceGroup(serviceGroup);
routeService.disableConditionRoute(crDTO);
return true;
}

@@ -24,6 +24,8 @@
public abstract class BaseDTO {
private String application;
private String service;
private String serviceVersion;
private String serviceGroup;

public String getApplication() {
return application;
@@ -40,4 +42,20 @@ public String getService() {
public void setService(String service) {
this.service = service;
}

public String getServiceVersion() {
return serviceVersion;
}

public void setServiceVersion(String serviceVersion) {
this.serviceVersion = serviceVersion;
}

public String getServiceGroup() {
return serviceGroup;
}

public void setServiceGroup(String serviceGroup) {
this.serviceGroup = serviceGroup;
}
}
@@ -30,7 +30,7 @@ public interface RouteService {

void updateConditionRoute(ConditionRouteDTO newConditionRoute);

void deleteConditionRoute(String id);
void deleteConditionRoute(ConditionRouteDTO conditionRoute);

void deleteAccess(String id);

@@ -40,12 +40,14 @@ public interface RouteService {

void updateAccess(AccessDTO accessDTO);

void enableConditionRoute(String id);
void enableConditionRoute(ConditionRouteDTO conditionRoute);


void disableConditionRoute(String id);
void disableConditionRoute(ConditionRouteDTO conditionRoute);


ConditionRouteDTO findConditionRoute(ConditionRouteDTO crDTO);

ConditionRouteDTO findConditionRoute(String id);

void createTagRoute(TagRouteDTO tagRoute);
@@ -87,11 +87,10 @@ public void updateConditionRoute(ConditionRouteDTO newConditionRoute) {
}

@Override
public void deleteConditionRoute(String id) {
if (StringUtils.isEmpty(id)) {
// throw exception
}
public void deleteConditionRoute(ConditionRouteDTO conditionRoute) {
String id = ConvertUtil.getIdFromDTO(conditionRoute);
String path = getPath(id, Constants.CONDITION_ROUTE);

String config = dynamicConfiguration.getConfig(path);
if (config == null) {
//throw exception
@@ -210,8 +209,10 @@ public void updateAccess(AccessDTO accessDTO) {
}

@Override
public void enableConditionRoute(String id) {
public void enableConditionRoute(ConditionRouteDTO conditionRoute) {
String id = ConvertUtil.getIdFromDTO(conditionRoute);
String path = getPath(id, Constants.CONDITION_ROUTE);

String config = dynamicConfiguration.getConfig(path);
if (config != null) {
RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
@@ -234,8 +235,10 @@ public void enableConditionRoute(String id) {
}

@Override
public void disableConditionRoute(String serviceName) {
String path = getPath(serviceName, Constants.CONDITION_ROUTE);
public void disableConditionRoute(ConditionRouteDTO conditionRoute) {
String id = ConvertUtil.getIdFromDTO(conditionRoute);
String path = getPath(id, Constants.CONDITION_ROUTE);

String config = dynamicConfiguration.getConfig(path);
if (config != null) {
RoutingRule routeRule = YamlParser.loadObject(config, RoutingRule.class);
@@ -257,6 +260,11 @@ public void disableConditionRoute(String serviceName) {

}

@Override
public ConditionRouteDTO findConditionRoute(ConditionRouteDTO crDTO) {
return findConditionRoute(ConvertUtil.getIdFromDTO(crDTO));
}

@Override
public ConditionRouteDTO findConditionRoute(String id) {
String path = getPath(id, Constants.CONDITION_ROUTE);
@@ -268,6 +276,11 @@ public ConditionRouteDTO findConditionRoute(String id) {
if (org.apache.commons.lang3.StringUtils.isNotBlank(service)) {
conditionRouteDTO.setService(service.replace("*", "/"));
}
String[] detachResult = ConvertUtil.detachId(id);
if (detachResult.length > 1) {
conditionRouteDTO.setServiceVersion(detachResult[1]);
conditionRouteDTO.setServiceGroup(detachResult[2]);
}
return conditionRouteDTO;
}
return null;
@@ -118,7 +118,7 @@ public void shouldUpdateRule() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -152,7 +152,7 @@ public void shouldGetServiceRule() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -183,7 +183,7 @@ public void shouldDeleteRule() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -218,7 +218,7 @@ public void shouldGetRouteDetail() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -245,7 +245,7 @@ public void shouldEnableRoute() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -274,7 +274,7 @@ public void shouldDisableRoute() throws Exception {
+ "priority: 0\n"
+ "runtime: false\n"
+ "scope: service";
String path = "/dubbo/config/dubbo/" + service + ".condition-router";
String path = "/dubbo/config/dubbo/" + service + "::.condition-router";
zkClient.create().creatingParentContainersIfNeeded().forPath(path);
zkClient.setData().forPath(path, content.getBytes());

@@ -24,7 +24,7 @@

@Service
public class AnnotatedGreetingService {
@DubboReference(version = "1.0.0")
@DubboReference(version = "1.0.0", group = "test")
private GreetingService greetingService;

public String sayHello(String name) {
@@ -22,7 +22,7 @@
import org.apache.dubbo.admin.api.GreetingService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(version = "1.0.0")
@DubboService(version = "1.0.0", group = "test")
public class AnnotatedGreetingService implements GreetingService {
public String sayHello(String name) {
System.out.println("greeting service received: " + name);

0 comments on commit a7dc202

Please sign in to comment.