com.nepxion.discovery.plugin.strategy.gateway.route.AbstractGatewayStrategyRoute Maven / Gradle / Ivy
package com.nepxion.discovery.plugin.strategy.gateway.route;
/**
* Title: Nepxion Discovery
* Description: Nepxion Discovery
* Copyright: Copyright (c) 2017-2050
* Company: Nepxion
* @author Ning Zhang
* @author Haojun Ren
* @version 1.0
*/
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.core.type.TypeReference;
import com.nepxion.discovery.common.constant.DiscoveryConstant;
import com.nepxion.discovery.common.entity.GatewayStrategyRouteEntity;
import com.nepxion.discovery.common.exception.DiscoveryException;
import com.nepxion.discovery.common.future.DiscoveryFutureCallback;
import com.nepxion.discovery.common.future.DiscoveryFutureResolver;
import com.nepxion.discovery.common.thread.DiscoveryThreadPoolFactory;
import com.nepxion.discovery.common.util.JsonUtil;
import com.nepxion.discovery.plugin.framework.event.PluginPublisher;
import com.nepxion.discovery.plugin.strategy.gateway.event.GatewayStrategyRouteAddedEvent;
import com.nepxion.discovery.plugin.strategy.gateway.event.GatewayStrategyRouteDeletedEvent;
import com.nepxion.discovery.plugin.strategy.gateway.event.GatewayStrategyRouteModifiedEvent;
import com.nepxion.discovery.plugin.strategy.gateway.event.GatewayStrategyRouteUpdatedAllEvent;
public abstract class AbstractGatewayStrategyRoute implements GatewayStrategyRoute, ApplicationEventPublisherAware {
private static final Logger LOG = LoggerFactory.getLogger(AbstractGatewayStrategyRoute.class);
private ExecutorService executorService = DiscoveryThreadPoolFactory.getExecutorService("gateway-route");
@Autowired
private RouteDefinitionLocator routeDefinitionLocator;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private GatewayProperties gatewayProperties;
@Autowired
private PluginPublisher pluginPublisher;
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public synchronized void add(GatewayStrategyRouteEntity gatewayStrategyRouteEntity) {
if (gatewayStrategyRouteEntity == null) {
throw new DiscoveryException("Gateway dynamic route is null");
}
Map routeDefinitionMap = locateRoutes();
String routeId = gatewayStrategyRouteEntity.getId();
if (routeDefinitionMap.containsKey(routeId)) {
throw new DiscoveryException("Gateway dynamic route for routeId=[" + routeId + "] is duplicated");
}
RouteDefinition routeDefinition = convertRoute(gatewayStrategyRouteEntity);
addRoute(routeDefinition);
LOG.info("Added Gateway dynamic route={}", routeDefinition);
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
pluginPublisher.asyncPublish(new GatewayStrategyRouteAddedEvent(gatewayStrategyRouteEntity));
}
@Override
public synchronized void modify(GatewayStrategyRouteEntity gatewayStrategyRouteEntity) {
if (gatewayStrategyRouteEntity == null) {
throw new DiscoveryException("Gateway dynamic route is null");
}
Map routeDefinitionMap = locateRoutes();
String routeId = gatewayStrategyRouteEntity.getId();
if (!routeDefinitionMap.containsKey(routeId)) {
throw new DiscoveryException("Gateway dynamic route for routeId=[" + routeId + "] isn't found");
}
RouteDefinition routeDefinition = convertRoute(gatewayStrategyRouteEntity);
modifyRoute(routeDefinition);
LOG.info("Modified Gateway dynamic route={}", routeDefinition);
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
pluginPublisher.asyncPublish(new GatewayStrategyRouteModifiedEvent(gatewayStrategyRouteEntity));
}
@Override
public synchronized void delete(String routeId) {
if (StringUtils.isEmpty(routeId)) {
throw new DiscoveryException("RouteId is empty");
}
Map routeDefinitionMap = locateRoutes();
RouteDefinition routeDefinition = routeDefinitionMap.get(routeId);
if (routeDefinition == null) {
throw new DiscoveryException("Gateway dynamic route for routeId=[" + routeId + "] isn't found");
}
deleteRoute(routeDefinition);
LOG.info("Deleted Gateway dynamic route for routeId={}", routeId);
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
pluginPublisher.asyncPublish(new GatewayStrategyRouteDeletedEvent(routeId));
}
@Override
public synchronized void updateAll(List gatewayStrategyRouteEntityList) {
if (gatewayStrategyRouteEntityList == null) {
throw new DiscoveryException("Gateway dynamic routes are null");
}
boolean isIdDuplicated = isIdDuplicated(gatewayStrategyRouteEntityList);
if (isIdDuplicated) {
throw new DiscoveryException("Gateway dynamic routes have duplicated routeIds");
}
Map dynamicRouteDefinitionMap = gatewayStrategyRouteEntityList.stream().collect(Collectors.toMap(GatewayStrategyRouteEntity::getId, this::convertRoute));
Map currentRouteDefinitionMap = locateRoutes();
List addRouteDefinitionList = new ArrayList(dynamicRouteDefinitionMap.size());
List modifyRouteDefinitionList = new ArrayList(dynamicRouteDefinitionMap.size());
List deleteRouteDefinitionList = new ArrayList(dynamicRouteDefinitionMap.size());
for (Map.Entry entry : dynamicRouteDefinitionMap.entrySet()) {
String routeId = entry.getKey();
RouteDefinition routeDefinition = entry.getValue();
if (!currentRouteDefinitionMap.containsKey(routeId)) {
addRouteDefinitionList.add(routeDefinition);
}
}
for (Map.Entry entry : dynamicRouteDefinitionMap.entrySet()) {
String routeId = entry.getKey();
RouteDefinition routeDefinition = entry.getValue();
if (currentRouteDefinitionMap.containsKey(routeId)) {
RouteDefinition currentRouteDefinition = currentRouteDefinitionMap.get(routeId);
if (!currentRouteDefinition.equals(routeDefinition)) {
modifyRouteDefinitionList.add(routeDefinition);
}
}
}
for (Map.Entry entry : currentRouteDefinitionMap.entrySet()) {
String routeId = entry.getKey();
RouteDefinition routeDefinition = entry.getValue();
if (!dynamicRouteDefinitionMap.containsKey(routeId)) {
deleteRouteDefinitionList.add(routeDefinition);
}
}
for (RouteDefinition routeDefinition : addRouteDefinitionList) {
addRoute(routeDefinition);
}
for (RouteDefinition routeDefinition : modifyRouteDefinitionList) {
modifyRoute(routeDefinition);
}
for (RouteDefinition routeDefinition : deleteRouteDefinitionList) {
deleteRoute(routeDefinition);
}
LOG.info("--- Gateway Dynamic Routes Update Information ----");
LOG.info("Total count={}", gatewayStrategyRouteEntityList.size());
LOG.info("Added count={}", addRouteDefinitionList.size());
LOG.info("Modified count={}", modifyRouteDefinitionList.size());
LOG.info("Deleted count={}", deleteRouteDefinitionList.size());
LOG.info("--------------------------------------------------");
if (addRouteDefinitionList.isEmpty() && modifyRouteDefinitionList.isEmpty() && deleteRouteDefinitionList.isEmpty()) {
return;
}
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
pluginPublisher.asyncPublish(new GatewayStrategyRouteUpdatedAllEvent(gatewayStrategyRouteEntityList));
}
@Override
public synchronized void updateAll(String gatewayStrategyRouteConfig) {
if (StringUtils.isBlank(gatewayStrategyRouteConfig)) {
gatewayStrategyRouteConfig = DiscoveryConstant.EMPTY_JSON_RULE_MULTIPLE;
}
List gatewayStrategyRouteEntityList = JsonUtil.fromJson(gatewayStrategyRouteConfig, new TypeReference>() {
});
updateAll(gatewayStrategyRouteEntityList);
}
@Override
public GatewayStrategyRouteEntity view(String routeId) {
if (StringUtils.isEmpty(routeId)) {
throw new DiscoveryException("RouteId is empty");
}
RouteDefinition routeDefinition = locateRoutes().get(routeId);
if (routeDefinition == null) {
throw new DiscoveryException("Gateway dynamic route for routeId=[" + routeId + "] isn't found");
}
return convertRoute(routeDefinition);
}
@Override
public List viewAll() {
List gatewayStrategyRouteEntityList = new ArrayList();
Map routeDefinitionMap = locateRoutes();
for (Map.Entry entry : routeDefinitionMap.entrySet()) {
RouteDefinition routeDefinition = entry.getValue();
GatewayStrategyRouteEntity gatewayStrategyRouteEntity = convertRoute(routeDefinition);
gatewayStrategyRouteEntityList.add(gatewayStrategyRouteEntity);
}
return gatewayStrategyRouteEntityList;
}
public Map locateRoutes() {
/*
Map routeDefinitionMap = new HashMap();
Flux routeDefinitions = routeDefinitionLocator.getRouteDefinitions();
Disposable disposable = null;
try {
disposable = routeDefinitions.subscribe(routeDefinition -> routeDefinitionMap.put(routeDefinition.getId(), routeDefinition));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
} finally {
if (disposable != null) {
disposable.dispose();
}
}
return routeDefinitionMap;
*/
Flux routeDefinitions = routeDefinitionLocator.getRouteDefinitions();
try {
return DiscoveryFutureResolver.call(executorService, new DiscoveryFutureCallback
© 2015 - 2025 Weber Informatics LLC | Privacy Policy