All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.cloud.routing.repository.RoutingDataRepository Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2022-2023 the original author or authors.
 *
 * 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.cloud.routing.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.cloud.commons.governance.routing.MatchService;
import com.alibaba.cloud.commons.governance.routing.RoutingRule;
import com.alibaba.cloud.commons.governance.routing.UnifiedRoutingDataStructure;
import com.alibaba.cloud.commons.governance.routing.rule.Rule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.util.CollectionUtils;

/**
 * @author HH
 * @since 2.2.10-RC1
 */
public class RoutingDataRepository {

	private static final Logger LOG = LoggerFactory
			.getLogger(RoutingDataRepository.class);

	/**
	 * Key is service name,value is hashmap,which key is single RoutingRule key,value is
	 * match service. Use double hash index to parse route rule.
	 */
	private ConcurrentHashMap>> routeCache = new ConcurrentHashMap<>();

	/**
	 * The default version of each service.
	 */
	private ConcurrentHashMap defaultRoutingVersion = new ConcurrentHashMap<>();

	/**
	 * Sign of path.
	 */
	private static final String PATH = "path";

	/**
	 * Contain rule of single path rule.
	 */
	private ConcurrentHashMap> pathRuleMap = new ConcurrentHashMap<>();

	/**
	 * If do not set weight value,it will be set 100 by default.
	 */
	private static final int DEFAULT_WEIGHT = 100;

	/**
	 * Sum of all version's weight.
	 */
	public static final int SUM_WEIGHT = 100;

	/**
	 * Weight value can't less than it.
	 */
	public static final int MIN_WEIGHT = 0;

	public void updateRouteData(final List routeDataList) {
		ConcurrentHashMap>> newRouteCache = new ConcurrentHashMap<>();
		ConcurrentHashMap> newPathRuleMap = new ConcurrentHashMap<>();
		for (UnifiedRoutingDataStructure routeData : routeDataList) {
			nonNullCheck(routeData);
			buildHashIndex(routeData, newRouteCache, newPathRuleMap);
			defaultRoutingVersion.put(routeData.getTargetService(),
					routeData.getLabelRouteRule().getDefaultRouteVersion());
		}
		// Replace it atomically
		this.routeCache = newRouteCache;
		this.pathRuleMap = newPathRuleMap;
	}

	private void nonNullCheck(UnifiedRoutingDataStructure unifiedRoutingDataStructure) {
		String targetService = unifiedRoutingDataStructure.getTargetService();
		if (targetService == null) {
			LOG.error("Lose target Service name.");
		}
		final RoutingRule labelRouteData = unifiedRoutingDataStructure
				.getLabelRouteRule();
		final List matchServiceList = labelRouteData.getMatchRouteList();
		for (MatchService matchService : matchServiceList) {
			final List ruleList = matchService.getRuleList();
			String version = matchService.getVersion();
			Integer weight = matchService.getWeight();
			if (CollectionUtils.isEmpty(ruleList)) {
				LOG.error("Rule is empty in version = {} ", version);
			}
			if (version == null) {
				LOG.error("Target service = {} lose version,please check it. ",
						targetService);
			}
			if (weight == null) {
				weight = DEFAULT_WEIGHT;
			}
			if (weight < MIN_WEIGHT || weight > SUM_WEIGHT) {
				LOG.error(
						"The weight of provider = {} version = {} had set error,please check it. ",
						targetService, version);
			}
		}
	}

	private void buildHashIndex(final UnifiedRoutingDataStructure routerData,
			ConcurrentHashMap>> newRouteCache,
			ConcurrentHashMap> newPathRuleMap) {
		final List matchRouteList = routerData.getLabelRouteRule()
				.getMatchRouteList();
		HashMap> singleRuleMap = new HashMap<>();

		for (MatchService matchService : matchRouteList) {
			List ruleList = matchService.getRuleList();

			// Take out the path label separately, because there is no key for hash index.
			if (ruleList.size() == 1
					&& PATH.equalsIgnoreCase(ruleList.get(0).getType())) {
				List matchServiceList = newPathRuleMap
						.get(routerData.getTargetService());
				if (matchServiceList == null) {
					matchServiceList = new ArrayList<>();
				}
				matchServiceList.add(matchService);
				newPathRuleMap.put(routerData.getTargetService(), matchServiceList);
				continue;
			}
			for (Rule routeRule : ruleList) {
				List matchServiceList = singleRuleMap
						.get(routeRule.getKey());
				if (matchServiceList == null) {
					matchServiceList = new ArrayList<>();
				}
				matchServiceList.add(matchService);
				if (routeRule.getKey() != null) {
					singleRuleMap.put(routeRule.getKey(), matchServiceList);
				}
			}
		}
		newRouteCache.put(routerData.getTargetService(), singleRuleMap);
	}

	public HashMap> getRouteRule(String targetService) {
		return routeCache.get(targetService);
	}

	public String getDefaultRouteVersion(String targetService) {
		return defaultRoutingVersion.get(targetService);
	}

	public List getPathRules(String targetService) {
		return pathRuleMap.get(targetService);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy