gateway集成nacos实现动态网关

1.将gateway注册至nacos

此方法成功后以此类推可以获取监听nacos上的所有配置

spring cloud 版本:Hoxton.SR3
spring boot 版本:2.2.5.RELEASE
spring cloud alibaba版本:2.2.1.RELEASE
–其他版本对应可以自行相关文档对应(手动滑稽)
bootstrap.yml的内容

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:
        locator:
          lower-case-service-id: true   #忽略服务大小写
          enabled: true             #动态创建路由
    nacos:
      discovery:
        server-addr: 10.165.12.109:8848
        enabled: true
      config:
        file-extension: yaml
        server-addr: 10.165.12.109:8848
server:
  port: 1111

application.yml的内容

polo:
  nacos:
    whiteApiName : "whiteApi"    #这个地方不需要用
    whiteIpName : "whiteIp"        #这个地方不需要用
  gateway:
    dateId: "gateway-service-route"
    group: "DEFAULT_GROUP"

pom.xml的内容


        
            org.springframework.boot
            spring-boot-starter-webflux
        
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        

        
        
            org.springframework.cloud
            spring-cloud-starter-gateway
        
        
            org.springframework.boot
            spring-boot-starter-validation
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-config
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.alibaba
            fastjson
        
        
        
            org.projectlombok
            lombok
        


编写一个配置类用来读取目前配置文件yml的内容

@Configuration
public class GatewayConfig {
    public static final long DEFAULT_TIMEOUT = 30000;

    public static String GATEWAY_CONFIG_DATA_ID;

    public static String GATEWAY_CONFIG_GROUP;

    public static String NACOS_SERVER_ADDR;

    @Value("${spring.cloud.nacos.discovery.server-addr}")
    public void setNacosServerAddr(String nacosServerAddr){
        NACOS_SERVER_ADDR = nacosServerAddr;
    }
    @Value("${polo.gateway.dateId}")
    public void setGatewayConfigDataId(String gatewayConfigDataId){
        GATEWAY_CONFIG_DATA_ID = gatewayConfigDataId;
    }
    @Value("${polo.gateway.group}")
    public void setGatewayConfigGroup(String gatewayConfigGroup){
        GATEWAY_CONFIG_GROUP = gatewayConfigGroup;
    }
}

编写一个监听器用来获取监听nacos上面的配置文件,并且更新发布

@Slf4j
@ConditionalOnProperty(value = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
@Component
public class DynamicRouteListener {

    ConfigService configService;

    @Autowired
    RouteDefinitionWriter routeDefinitionWriter;

    @Autowired
    ApplicationEventPublisher applicationEventPublisher;


    @EventListener(ApplicationReadyEvent.class)
    public void createListener(){
        if ((configService =initConfigService()) == null){
            log.error("【configService】为空");
            return;
        }
        try {
            //通过configService使用配置id和group拿到路由文本以及编写监听器事件
            String route =configService.getConfigAndSignListener(GatewayConfig.GATEWAY_CONFIG_DATA_ID,GatewayConfig.GATEWAY_CONFIG_GROUP,10000, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                //监听器监听到配置更新
                @Override
                public void receiveConfigInfo(String s) {
                    log.info("【路由更新】监听到路由更新:{}", s);
                    List list = JsonUtils.toList(s, RouteDefinition.class);
                    list.forEach(definition->{
                        //监听器更新
                        updateDefinition(definition);
                    });
                }
            });
            log.info("现有路由:{}",route);
            //拿到目前的路由并发布
            JsonUtils.toList(route,RouteDefinition.class).forEach( f ->{
                updateDefinition(f);
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }
    private void updateDefinition(RouteDefinition routeDefinition){
        //删除原路由
        try {
            routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
        } catch (Exception e) {
            log.error("删除原路由失败");
        }
        //保存并发布新路由
        try {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            log.error("发布路由失败");
            e.printStackTrace();
        }
    }

    /**
     * 初始化configService
     * @return
     */
    private ConfigService initConfigService(){
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR,GatewayConfig.NACOS_SERVER_ADDR);
        try {
            return NacosFactory.createConfigService(properties);
        } catch (NacosException e){
            log.error("【ConfigService】初始化失败");
            return null;
        }
    }

}

上面代码大概总结如下:

/**
 * 动态路由:
 * 1.初始化ConfigService(当然也可以创建一个配置类然后再自动注入)
 * 2.通过初始化configService.getConfigAndSignListener(id,group,timeout,listener)拿到当前配置和监听器(@EventListener(ApplicationReadyEvent.class(事件源.class)))
 * 2.1。监听器监听nacos配置,并转化为RouteDefinition,并更新发布
 * 3.拿到当前当前文本路由进行发布更新
 */

上文中有个工具类也贴在下面

@Slf4j
public class JsonUtils {

   private static ObjectMapper mapper = new ObjectMapper();

   public static  List toList(String jsonData, Class beanType) {
       mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
       JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);
       try {
           return mapper.readValue(jsonData, javaType);
       } catch (Exception e) {
           log.warn("", e);
       }
       return new ArrayList();
   }
}

启动类也要加上@Enabl
eDiscoveryClient用来连接nscos上注册发现
gateway集成nacos实现动态网关_第1张图片
测试
1.启动nacos:本文用的window版本,在nacos bin目录下,startup.cmd -m standalone 启动,能够进入nacos网站地址说明启动成功
2.启动网关
2.1.1 启动官网时,将会自动注册nacos服务列表
在这里插入图片描述
2.1.2 由于我们添加了监听器,启动时就会首先去nacos读取相关配置(先得在nacos配置管理编写与咱们yml名字对应的配置文件),并发布(上面代码有体现)
打印的日志
gateway集成nacos实现动态网关_第2张图片
nacos上面编写的配置(pattern参数多了一个/!)
gateway集成nacos实现动态网关_第3张图片
可以看出和我们的配置一毛一样
配置类容贴上

[{
    "id": "user-center",
    "order": 0,
    "predicates": [{
        "args": {
            "pattern": "user-center/**"
        },
        "name": "Path"
    }],
    "uri": "lb://user-center"
}]

在nacos修改配置并发布,看监听器能否监听并发布
gateway集成nacos实现动态网关_第4张图片
控制成功监听到了
gateway集成nacos实现动态网关_第5张图片


1.网关路由编写是json格式和名字对用RouteDefinition,不然一个字母的错误毁了一个小时
2.各个cloud boot alibaba 版本对应上

你可能感兴趣的:(cloud,gateway,spring,cloud,spring,boot)