스토리지 클러스터링을위한 동적 라우팅 게이트웨이 [세] 라우팅, 게이트웨이 게이트웨이 동적 라우팅 구성, 사용의 MySQL [SpringCloud는 빌드 워크 분산]

처음 두, 주로 직접 운영 엔티티 클래스와 테이블을 작성하는

스토리지 클러스터링을위한 동적 라우팅 게이트웨이 [두] 라우팅, 게이트웨이 게이트웨이 동적 라우팅 구성, 사용의 MySQL [SpringCloud는 빌드 워크 분산]

스토리지 클러스터링을위한 동적 라우팅 게이트웨이 라우팅, 게이트웨이 게이트웨이 동적 라우팅 구성, 사용의 MySQL [SpringCloud 빌드 워크 분산] [A]

다음의 주요 지침은 동적 로딩의 게이트웨이를 구성 할 수 있습니다.

찾을 수있는 스프링 클라우드 게이트웨이 소스를 분석함으로써, 기본 구현 클래스는 RouteDefinitionWriter InMemoryRouteDefinitionRepository는 그림과 같습니다 :

RouteDefinitionRepository 继承了RouteDefinitionWriter,是 Spring Cloud Gateway官方预留的接口。从而可以通过下面两种方式来实现集群下的动态路由修改:RouteDefinitionWriter 接口和 RouteDefinitionRepository 接口。在这里推荐实现RouteDefinitionRepository 这个接口,从数据库或者从配置中心获取路由进行动态配置。

여기 내 MySQL의 구현 클래스에 직접 부착 : MysqlRouteDefinitionRepository


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.keda.gateway.entity.DynamicRouteVo;
import com.keda.gateway.entity.GatewayDynamicRoute;
import com.keda.gateway.service.IGatewayDynamicRouteService;
import com.keda.gateway.struts.DynamicRouteStruts;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: seowen
 * @Date: 2019/12/19 15:27
 * @Version 1.0
 */
@Component
public class MysqlRouteDefinitionRepository implements RouteDefinitionRepository {

    @Autowired
    private IGatewayDynamicRouteService routeService;

    /**
     * Gateway启动的时候,会加载这个方法
     * @return
     */
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        //从数据库中,获取我们自定义的 路由信息数据
        List<GatewayDynamicRoute> listByEnable = routeService.getListByEnable(true);

        if (CollectionUtils.isNotEmpty(listByEnable)){
            //转换成 RouteDefinition 集合后,返回
            return Flux.fromIterable(this.toRouteList(listByEnable));
        }
        //如果 数据库为 空,则返回一个 空的集合
        return Flux.fromIterable(new ArrayList<RouteDefinition>());
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return null;
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return null;
    }

    /**
     * 转换成 List<RouteDefinition>
     * @param listByEnable
     * @return
     */
    private List<RouteDefinition> toRouteList(List<GatewayDynamicRoute> listByEnable){
        List<RouteDefinition> routeList = new ArrayList<>();
        /**
         * 循环转换:
         * 因为数据库中,Predicates 和 Filters 存储的 json字符串。所以,得先转换成 对应的 vo.
         * 然后在转换成 List<PredicateDefinition>和 List<FilterDefinition>
         */

        listByEnable.stream().forEach(gw->{
            RouteDefinition r = new RouteDefinition();
            r.setUri(DynamicUtil.getUri(gw.getUri()));
            r.setOrder(gw.getOrder());
            r.setId(gw.getRouteId());
            r.setPredicates(DynamicRouteStruts.INSTANCES.toPredicateDefinition(JSONArray.parseArray(gw.getPredicates(), DynamicRouteVo.PredicateDefinitionVo.class)));
            r.setFilters(DynamicRouteStruts.INSTANCES.toFilterDefinition(JSONArray.parseArray(gw.getFilters(),DynamicRouteVo.FilterDefinitionVo.class)));
            routeList.add(r);
        });
        return routeList;
    }

}
MysqlRouteDefinitionRepository 类写好后,还不行。 我们需要当每次操作 动态有路由表,都希望 gateway网关,重新加载 路由数据。 这个时候,我们就需要一个spring事件来支持。


DynamicRouteServiceImpl 类,就是我的 事件事件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

/**
 * @Author: seowen
 * @Date: 2019/12/19 15:49
 * @Version 1.0
 */
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher publisher;


    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    /**
     * 增加路由
     * @param routeDefinition
     * @return
     */
    public String add(RouteDefinition routeDefinition){
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        this.doLoad();
        return "success";
    }

    /**
     * 更新路由
     */
    public String update(RouteDefinition definition) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
        } catch (Exception e) {
            return "update fail,not find route  routeId: " + definition.getId();
        }
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.doLoad();
            return "success";
        } catch (Exception e) {
            return "update route  fail";
        }
    }


    /**
     * 删除路由
     *
     */
    public String delete(String id) {
//        return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(()->Mono.just(ResponseEntity.ok().build())))
//                .onErrorResume(t -> t instanceof NotFoundException,t -> Mono.just(ResponseEntity.notFound().build()));
        try {
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            this.doLoad();
        } catch (Exception e) {
            e.printStackTrace();
            return "delete fail,not find route  routeId: " + id;
        }
        return "delete success";
    }

    /**
     * 重新刷新 路由
     */
    public String doLoad() {
        try {
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        }catch (Exception e){
            e.printStackTrace();
            return "load fail";
        }
        return "load success";
    }


}

 우리는 각 데이터베이스 작업 후에는 라우팅을 새로 고치려면이 doLoad () 메서드를 호출해야합니다
추가 방법 GatewayDynamicRouteController로

    /**
     * 增加路由
     * @param routeBean
     * @return
     */
    @PostMapping("/add")
    public String add(@RequestBody DynamicRouteVo.RouteBean routeBean){

        service.saveOne(DynamicRouteStruts.INSTANCES.toGatewayDynamicRoute(routeBean));
        return this.dynamicRouteService.doLoad();
    }

특별 참고 사항 :

{
	"routeId":"keda-creditcard",
	"uri":"lb://KEDA-CREDITCARD",
	"order":"1",
	"enable":"true",
	"predicates":[ 
		{
	        "name": "Path",
	        "args": {
	            "_genkey_0": "/main/**"
	        }
	    }
    ],
	"filters":[
	    {
            "name": "StripPrefix",
            "args": {
                "_genkey_0": "1"
            }
        },
        {
            "name": "Retry",
            "args": {
                "retries": "3",
                "series.0": "SERVER_ERROR",
                "methods.0": "GET",
                "methods.1": "POST"
            }
        }	
	]
	
}

위, 요청 매개 변수 :
라우팅 정보를 제공합니다. 일반적  = 값 이름 형태.

위의 경로 및  StripPrefix은 일반입니다  이름 속성 이름 . 특히 참고로,에 대응하는 값이다 "/ / ** 주""1" . 경우 게이트웨이 정적 경로 구성하겠습니다 직접 YML 파일, 라우팅 정보, 도시 된 바와 같이



때  술어필터링 노드의 구성이 간단하게   이름 = 값 시간. 프레스 할 게이트웨이 넣을 때 "="(즉 숯 61)을 분할한다. 그 다음에 값 "," 문자열로 분할 어레이 . 그리고, 「로 배열을 반복 _genkey_ "접두사 + 배열 첨자 후에는 열쇠이다. 밸류 값.

지도 인수해야 할

소스는 다음과 같습니다 :

따라서 우리는 경로를 추가, 또한이 규칙을 준수합니다. 예를 들면 :

	        "name": "Path",
	        "args": {
	            "_genkey_0": "/main/**"
	        }

경로가 추가 될 때, 인수 속성 및 상응하는 키있다 : 값 쌍하면 키 복합 (즉, 모음) 인 경우.
즉, 해당 키를 "키를 누르십시오. 작은 기호"표현하는 것입니다. 예를 들면 :

 "name": "Retry",
 "args": {
     "retries": "3",
     "series.0": "SERVER_ERROR",
     "methods.0": "GET",
     "methods.1": "POST"
 }

 

따라서, 분산 아키텍처에서, 설정 동적 라우팅 기능 클러스터 게이트웨이 서비스는 완료! ! ! !

发布了111 篇原创文章 · 获赞 28 · 访问量 4万+

추천

출처blog.csdn.net/weixin_42697074/article/details/103821946