• 北极星Polaris+Gateway动态网关配置!


    springcloudtencetn 父工程:

    pom

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <groupId>com.gtongroupId>
        <artifactId>cloudartifactId>
        <packaging>pompackaging>
        <version>0.0.1-SNAPSHOTversion>
        <modules>
            <module>gatewaymodule>
            <module>usermanagermodule>
            <module>commoditymodule>
            <module>back-stage-managementmodule>
            <module>commonmodule>
        modules>
        <name>cloudname>
        <description>Spring Cloud Tencent +北极星(服务管理 流量管理 故障容错 配置管理) 微服务架构系统description>
    
        <properties>
            <java.version>11java.version>
            <maven.compiler.source>11maven.compiler.source>
            <maven.compiler.target>11maven.compiler.target>
            <spring-cloud-tencent-version>1.7.0-2021.0.3spring-cloud-tencent-version>
            <spring-cloud-dependencies-version>2021.0.3spring-cloud-dependencies-version>
            <projectlombok-version>1.18.16projectlombok-version>
            <spring-boot.version>2.6.9spring-boot.version>
        properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.tencent.cloudgroupId>
                    <artifactId>spring-cloud-tencent-dependenciesartifactId>
                    <version>${spring-cloud-tencent-version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
    
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>${spring-cloud-dependencies-version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                <dependency>
                    <groupId>org.projectlombokgroupId>
                    <artifactId>lombokartifactId>
                    <version>1.18.16version>
                dependency>
    
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-dependenciesartifactId>
                    <version>${spring-boot.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.pluginsgroupId>
                    <artifactId>maven-compiler-pluginartifactId>
                    <version>3.8.1version>
                    <configuration>
                        <source>11source>
                        <target>11target>
                        <encoding>UTF-8encoding>
                    configuration>
                plugin>
            plugins>
        build>
    
    project>
    
    

    gateway导入pom

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>cloudartifactId>
            <groupId>com.gtongroupId>
            <version>0.0.1-SNAPSHOTversion>
        parent>
        <modelVersion>4.0.0modelVersion>
    
        <artifactId>gatewayartifactId>
    
        <properties>
            <fastJson-version>2.0.18fastJson-version>
        properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.tencent.cloudgroupId>
                <artifactId>spring-cloud-starter-tencent-polaris-routerartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.tencent.cloudgroupId>
                <artifactId>spring-cloud-starter-tencent-polaris-discoveryartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.tencent.cloudgroupId>
                <artifactId>spring-cloud-starter-tencent-polaris-ratelimitartifactId>
            dependency>
    
    
            
            <dependency>
                <groupId>com.tencent.cloudgroupId>
                <artifactId>spring-cloud-starter-tencent-polaris-configartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.tencent.cloudgroupId>
                <artifactId>spring-cloud-starter-tencent-polaris-circuitbreakerartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-loadbalancerartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-bootstrapartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-circuitbreaker-spring-retryartifactId>
            dependency>
    
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-gatewayartifactId>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.fastjson2groupId>
                <artifactId>fastjson2artifactId>
                <version>${fastJson-version}version>
            dependency>
    
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
            dependency>
        dependencies>
    
    
    project>
    

    网关配置:

    spring:
      application:
        name: gateway
      cloud:
        gateway:
          discovery:
            locator:
              # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
              enabled: true
        polaris:
          address: grpc://localhost:8091 #北极星注册中心地址
          namespace: polaris-cloud-market #北极星注册中心的使用命名空间,自定义
          config:
            auto-refresh: true #当配置发布后,动态刷新
            address:  grpc://localhost:8093  # 当配置中心和 注册中心地址不一致时可以选择,否着可以不填
            groups:
              - name: gatewayOnly #读取的文件所在分组
                files: ["router.properties","myconfig.yaml"]  #读取的文件名
    
    

    北极星控制台配置
    image

    gateway网关的路由操作类:

    package com.gton.service;
    
    
    import lombok.extern.slf4j.Slf4j;
    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.RouteDefinitionLocator;
    import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.ApplicationEventPublisherAware;
    import org.springframework.stereotype.Service;
    import org.springframework.util.CollectionUtils;
    import reactor.core.publisher.Mono;
    
    import java.util.List;
    
    /**
     * @description:动态更新路由网关service
     * @author: GuoTong
     * @createTime: 2022-10-05 22:24
     * @since JDK 1.8 OR 11
     **/
    @Slf4j
    @Service
    public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
        @Autowired
        private RouteDefinitionWriter routeDefinitionWriter;
        @Autowired
        private RouteDefinitionLocator routeDefinitionLocator;
    
        /**
         * 发布事件
         */
        @Autowired
        private ApplicationEventPublisher publisher;
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
            this.publisher = applicationEventPublisher;
        }
    
        /**
         * 删除路由
         *
         * @param id
         * @return
         */
        public String delete(String id) {
            try {
                log.info("gateway delete route id {}", id);
                this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
                this.publisher.publishEvent(new RefreshRoutesEvent(this));
                return "delete success";
            } catch (Exception e) {
                return "delete fail";
            }
        }
    
        /**
         * 更新路由
         *
         * @param definitions
         * @return
         */
        public String updateList(List definitions) {
            log.info("gateway update route {}", definitions);
            // 删除缓存routerDefinition
            List routeDefinitionsExits = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
            if (!CollectionUtils.isEmpty(routeDefinitionsExits)) {
                routeDefinitionsExits.forEach(routeDefinition -> {
                    log.info("delete routeDefinition:{}", routeDefinition);
                    delete(routeDefinition.getId());
                });
            }
            definitions.forEach(this::updateById);
            return "success";
        }
    
        /**
         * 更新路由
         *
         * @param definition
         * @return
         */
        public String updateById(RouteDefinition definition) {
            try {
                log.info("gateway update route {}", definition);
                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.publisher.publishEvent(new RefreshRoutesEvent(this));
                return "success";
            } catch (Exception e) {
                return "update route fail";
            }
        }
    
        /**
         * 增加路由
         *
         * @param definition
         * @return
         */
        public String add(RouteDefinition definition) {
            log.info("gateway add route {}", definition);
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "success";
        }
    }
    
    

    监听路由变化

    package com.gton.listener;
    
    import com.alibaba.fastjson2.JSONObject;
    import com.gton.service.DynamicRouteServiceImpl;
    import com.tencent.cloud.polaris.config.annotation.PolarisConfigKVFileChangeListener;
    import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
    import com.tencent.polaris.api.utils.CollectionUtils;
    import com.tencent.polaris.configuration.api.core.ChangeType;
    import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    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.stereotype.Component;
    
    import java.net.URI;
    import java.util.*;
    
    /**
     * @description: 监听Polaris的配置更新
     * @author: GuoTong
     * @createTime: 2022-11-24 22:25
     * @since JDK 1.8 OR 11
     **/
    @Component
    @Slf4j
    @SuppressWarnings("all")
    public class ListenerPolaris {
    
        @Autowired
        private DynamicRouteServiceImpl dynamicRouteService;
    
    
        /**
         * PolarisConfigKVFileChangeListener Example .
         * 监听北极星中心变更路由
         *
         * @param event instance of {@link ConfigChangeEvent}
         */
        @PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "routes")
        public void onChange(ConfigChangeEvent event) {
            // 封装需要更新的路由规则数据
            List routeUpdates = new ArrayList<>();
            // 获取配置修改的所有key
            Set changedKeys = event.changedKeys();
            // 保留已经处理的
            Set intIndex = new HashSet<>();
            for (String changedKey : changedKeys) {
                // 获取修改的实体
                ConfigPropertyChangeInfo changeInfo = event.getChange(changedKey);
                if (changeInfo.getChangeType() == ChangeType.ADDED) {
                    String newValue = changeInfo.getNewValue();
                    // 添加新路由
                    addNewRule(routeUpdates, newValue);
    
                }
                // 删除老路由(弃用)
                if (changeInfo.getChangeType() == ChangeType.DELETED) {
                    String newValue = changeInfo.getNewValue();
                    JSONObject jsonObject = JSONObject.parseObject(newValue);
                    String id = jsonObject.getString("id");
                    dynamicRouteService.delete(id);
                }
                if (CollectionUtils.isNotEmpty(routeUpdates)) {
                    routeUpdates.forEach(item -> dynamicRouteService.add(item));
                }
    
            }
    
        }
    
        /**
         * Description: 添加新路由
         *
         * @param routeUpdates
         * @param changeInfo
         * @author: GuoTong
         * @date: 2022-11-25 15:32:59
         * @return:void
         */
        public void addNewRule(List routeUpdates, String newValue) {
    
            RouteDefinition routeDefinition = new RouteDefinition();
            JSONObject jsonObject = JSONObject.parseObject(newValue);
            routeDefinition.setId(jsonObject.getString("id"));
            routeDefinition.setUri(URI.create(jsonObject.getString("uri")));
            List predicates = routeDefinition.getPredicates();
            String predicates1 = jsonObject.getString("predicates");
            if (predicates1.contains(";")) {
                String[] split = predicates1.split(";");
                for (String vars : split) {
                    String[] var3 = vars.split("=");
                    PredicateDefinition predicateDefinition = new PredicateDefinition();
                    predicateDefinition.setName(var3[0]);
                    Map args = predicateDefinition.getArgs();
                    args.put(var3[0], var3[1]);
                    predicates.add(predicateDefinition);
                }
            } else {
                String[] split = predicates1.split("=");
                PredicateDefinition predicateDefinition = new PredicateDefinition();
                predicateDefinition.setName(split[0]);
                Map args = predicateDefinition.getArgs();
                args.put(split[0], split[1]);
                predicates.add(predicateDefinition);
            }
    
            List filters = routeDefinition.getFilters();
            String var6 = jsonObject.getString("filters");
            if (var6.contains(";")) {
                String[] var7 = var6.split(";");
                for (String var8 : var7) {
                    String[] split = var8.split("=");
                    FilterDefinition filterDefinition = new FilterDefinition();
                    filterDefinition.setName(split[0]);
                    Map args = filterDefinition.getArgs();
                    args.put(split[0], split[1]);
                    filters.add(filterDefinition);
                }
    
            } else {
                String[] split = var6.split("=");
                FilterDefinition filterDefinition = new FilterDefinition();
                filterDefinition.setName(split[0]);
                Map args = filterDefinition.getArgs();
                args.put(split[0], split[1]);
                filters.add(filterDefinition);
            }
            routeUpdates.add(routeDefinition);
        }
    
    }
    
    

    初始化读取配置

    package com.gton.config;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    /**
     * @description: 读取北极星配置路由
     * @author: GuoTong
     * @createTime: 2022-11-25 15:55
     * @since JDK 1.8 OR 11
     **/
    @ConfigurationProperties(prefix = "routes")
    @Component
    @Data
    public class ReadRouterConfig {
    
        /**
         * Description:  网关路由动态配置
         *
         * @author: GuoTong
         * @date: 2022-11-25 16:08:23
         * @param rule
         * @return:
         */
        private List rule;
    
    }
    

    启动加载配置问阿金

    package com.gton.config;
    
    import com.gton.listener.ListenerPolaris;
    import com.gton.service.DynamicRouteServiceImpl;
    import com.tencent.polaris.api.utils.CollectionUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    import org.springframework.cloud.gateway.route.RouteDefinition;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @program: PersonalDesign
     * @description: 项目一启动就执行
     **/
    @Slf4j
    @Component
    @Order(value = 1)
    public class MyApplicationRunner implements ApplicationRunner {
    
        @Autowired
        private ReadRouterConfig readRouterConfig;
    
        @Autowired
        private ListenerPolaris listenerPolaris;
    
        @Autowired
        private DynamicRouteServiceImpl dynamicRouteService;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            log.info("开始网关路由配置加载。。。。。。");
            // 读取北极星上的配置信息
            List rule = readRouterConfig.getRule();
            List routeUpdates = new ArrayList<>();
            // 北极星上的配置处理
            rule.forEach(item -> listenerPolaris.addNewRule(routeUpdates, item));
            if (log.isDebugEnabled()) {
                log.debug("加载的路由配置是->{}", routeUpdates);
            }
            // 启动完成注册相关路由配置
            if (CollectionUtils.isNotEmpty(routeUpdates)) {
                routeUpdates.forEach(item -> dynamicRouteService.add(item));
            }
            log.info("网关路由配置加载结束。。。。。。");
        }
    }
    
    

    到此结束!!!!

  • 相关阅读:
    python调用seafile接口上传文件到seafile
    内存-虚拟地址到物理内存地址转换
    Java I/O流概述
    5年测试在职经验之谈:2年功能测试、3年自动化测试,从入门到不可自拔...
    SSL证书如何做到保障网站安全?
    熬了五年,马同学第一本书出版了!
    含文档+PPT+源码等]精品spring boot汽车销售管理系统[包运行成功]程序设计源码计算机毕设
    KT148A语音芯片下载过程的问题集锦 包含下载不了批量生产的说明
    其他word转化为PDF的方式
    怎么查找Linux服务器是否有后门账户
  • 原文地址:https://www.cnblogs.com/gtnotgod/p/16925721.html