项目依赖

配置

# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=localhost:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
spring.cloud.nacos.config.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.name=zuul-client
spring.cloud.util.enabled=false
spring.profiles.active=dev
spring.cloud.nacos.discovery.group=cloud-test
spring.cloud.nacos.config.group=cloud-test
spring.cloud.nacos.config.file-extension=properties
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa
#dataId 的完整格式如下:prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置
# ${prefix}-${spring.profiles.active}.${file-extension}
# 数据库连接信息{单数据源}

路由配置

sidecar:
# 异构微服务的IP
ip: 127.0.0.1
# 异构微服务的端口
port: 8060
# 异构微服务的健康检查URL
health-check-url: http://localhost:8060/health.json spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启通过服务中心的自动根据 serviceId 创建路由的功能
routes:
- id: ldapsso-client
uri: lb://ldapsso-client
predicates:
- Path=/ldapsso/**
filters:
- StripPrefix=1
- id: service-b
uri: lb://service-b
predicates:
- Path=/service-b/test-service-b/**
filters:
- StripPrefix=1
inetutils:
ignored-interfaces: 'VMware Virtual Ethernet Adapter for VMnet1,VMware Virtual Ethernet Adapter for VMnet8'
nacos:
discovery:
server-addr: localhost:8848
application:
name: zuul-client management:
endpoint:
health:
show-details: always
server:
port: 28083

启动器

@SpringBootApplication
@EnableDiscoveryClient
public class ZuulApplication { public static void main(String[] args) {
try {
SpringApplication.run(ZuulApplication.class, args);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
} @Bean
public InetIPv6Utils inetIPv6Utils() {
InetUtilsProperties properties = new InetUtilsProperties();
return new InetIPv6Utils(properties);
} @Bean
public InetUtils inetUtils() {
InetUtilsProperties properties = new InetUtilsProperties();
return new InetUtils(properties);
} }

测试类

@RestController
public class IndexController { @RequestMapping("/index")
public String getIndex(){
return "Zuul";
}
}

路由更新业务处理

public interface RouteService {

    /**
* 更新路由配置
*
* @param routeDefinition
*/
void update(RouteDefinition routeDefinition); /**
* 添加路由配置
*
* @param routeDefinition
*/
void add(RouteDefinition routeDefinition); } @Slf4j
@Service
public class RouteServiceImpl implements RouteService, ApplicationEventPublisherAware { @Autowired
private RouteDefinitionWriter routeDefinitionWriter; /**
* 事件发布者
*/
private ApplicationEventPublisher publisher; @Override
public void update(RouteDefinition routeDefinition) {
log.info("更新路由配置项:{}", routeDefinition);
this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
} @Override
public void add(RouteDefinition routeDefinition) {
log.info("新增路由配置项:{}", routeDefinition);
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
} @Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}

动态路由加载

package com.example.zuul.listner;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.UuidUtils;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.*;
import java.util.concurrent.Executor; @Component
@Slf4j
public class NacosRefreshConfig { @Autowired
private RouteService routeService; @Value("${spring.cloud.nacos.config.server-addr}")
private String nacosAddr;
@Value("${spring.cloud.nacos.config.namespace}")
private String nameSpace; @Value("${spring.cloud.nacos.config.username}")
private String username; @Value("${spring.cloud.nacos.config.password}")
private String password; @PostConstruct
public void initBindListner() throws NacosException {
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, nacosAddr);
properties.put(PropertyKeyConst.NAMESPACE, nameSpace);
properties.put(PropertyKeyConst.USERNAME, username);
properties.put(PropertyKeyConst.PASSWORD, password);
ConfigService configService = NacosFactory.createConfigService(properties);
configService.addListener(Constants.CONFIG_FILE_NAME, Constants.CONFIG_FILE_GROUP, new Listener() {
@Override
public Executor getExecutor() {
return null;
} @Override
public void receiveConfigInfo(String configInfo) {
// 刷新路由
List<RouteDefinition> extracted = extracted(configInfo);
for (RouteDefinition routeDefinition : extracted) {
routeService.update(routeDefinition);
}
}
});
} private static List<RouteDefinition> extracted(String configInfo) {
List<RouteDefinition> list = new ArrayList<>();
JSONArray jsonObjectArr = JSONArray.parseArray(configInfo);
for (int i = 0; i < jsonObjectArr.size(); i++) {
RouteDefinition routeDefinition = new RouteDefinition();
JSONObject jsonObject = jsonObjectArr.getJSONObject(i);
routeDefinition.setId(StringUtils.defaultIfEmpty(jsonObject.getString("id"), UuidUtils.generateUuid()));
routeDefinition.setUri(URI.create(jsonObject.getString("uri")));
List<PredicateDefinition> predicates = routeDefinition.getPredicates();
JSONArray predicates1 = jsonObject.getJSONArray("predicates");
if (predicates1 != null && predicates1.size() > 1) {
for (int ii = 0; ii < predicates1.size(); ii++) {
Set<Map.Entry<String, Object>> entries = predicates1.getJSONObject(ii).entrySet();
for (Map.Entry<String, Object> entry : entries) {
PredicateDefinition predicateDefinition = new PredicateDefinition();
predicateDefinition.setName(entry.getKey());
Map<String, String> args = predicateDefinition.getArgs();
args.put(entry.getKey(), entry.getValue().toString());
predicates.add(predicateDefinition);
}
}
} else {
Set<Map.Entry<String, Object>> entries = predicates1.getJSONObject(0).entrySet();
for (Map.Entry<String, Object> entry : entries) {
PredicateDefinition predicateDefinition = new PredicateDefinition();
predicateDefinition.setName(entry.getKey());
Map<String, String> args = predicateDefinition.getArgs();
args.put(entry.getKey(), entry.getValue().toString());
predicates.add(predicateDefinition);
}
} List<FilterDefinition> filters = routeDefinition.getFilters();
JSONArray var6 = jsonObject.getJSONArray("filters");
if (var6 != null && var6.size() > 1) {
for (int ij = 0; ij < var6.size(); ij++) {
Set<Map.Entry<String, Object>> entries = var6.getJSONObject(ij).entrySet();
for (Map.Entry<String, Object> entry : entries) {
FilterDefinition filterDefinition = new FilterDefinition();
filterDefinition.setName(entry.getKey());
Map<String, String> args = filterDefinition.getArgs();
args.put(entry.getKey(), entry.getValue().toString());
filters.add(filterDefinition);
}
} } else {
Set<Map.Entry<String, Object>> entries = var6.getJSONObject(0).entrySet();
for (Map.Entry<String, Object> entry : entries) {
FilterDefinition filterDefinition = new FilterDefinition();
filterDefinition.setName(entry.getKey());
Map<String, String> args = filterDefinition.getArgs();
args.put(entry.getKey(), entry.getValue().toString());
filters.add(filterDefinition);
}
}
list.add(routeDefinition);
}
return list;
} @NacosConfigListener(dataId = Constants.CONFIG_FILE_NAME)
public void refresh(String msg) {
log.error("-----------------------");
JSONObject jsonObject = JSONObject.parseObject(msg);
log.error(jsonObject.toJSONString());
}
} public interface Constants {
String CONFIG_FILE_NAME = "zuul-client";
String CONFIG_FILE_GROUP = "cloud-test";
}

Nacos配置

[
{"id":"ldapsso-client","uri":"lb://ldapsso-client","predicates":[{"Path":"/ldapsso/**"}],"filters":[{"StripPrefix":1}]},
{"id":"baidu","uri":"https://www.baidu.com","predicates":[{"Path":"/baidu/**"}],"filters":[{"StripPrefix":1}]},
{"id":"client","uri":"lb://ldapsso-client","predicates":[{"Path":"/client/**"}],"filters":[{"StripPrefix":1}]}
]

测试动态路由生效

完结====

boot3+JDK17+spring-cloud-gateway:4.0.0+spring-cloud:2022.0.0.0+Nacos2.2.1配置动态路由的网关的更多相关文章

  1. spring cloud gateway 启动报错,Failed to bind on [0.0.0.0:xxx] bind(..) failed: 权限不够

    最近把操作系统迁移到了deepin,不得不说Linux中需要学习的还是有很多的,本地启动网关的时候就遇到一个坑,特此记录一下,报错信息. Caused by: reactor.netty.Channe ...

  2. api网关揭秘--spring cloud gateway源码解析

    要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux. 1.gateway 和zuul对比 I am the au ...

  3. 纠错帖:Zuul & Spring Cloud Gateway & Linkerd性能对比 (转载)

    纠错帖:Zuul & Spring Cloud Gateway & Linkerd性能对比  Spring Cloud  Spring Cloud Spring Cloud Gatew ...

  4. spring cloud gateway 之限流篇

    转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...

  5. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

  6. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  7. 跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探

    SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如 ...

  8. 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)

    前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...

  9. Spring Cloud Gateway使用简介

    Spring Cloud Gateway是类似Nginx的网关路由代理,有替代原来Spring cloud zuul之意: Spring 5 推出了自己的Spring Cloud Gateway,支持 ...

  10. Spring Cloud Gateway入坑记

    Spring Cloud Gateway入坑记 前提 最近在做老系统的重构,重构完成后新系统中需要引入一个网关服务,作为新系统和老系统接口的适配和代理.之前,很多网关应用使用的是Spring-Clou ...

随机推荐

  1. 循规蹈矩--从零开始建设k8s监控(一)

    前言 监控k8s集群,目前主流就是使用prometheus以及其周围的生态,本文开始介绍怎么一步步完成k8s监控的建设 环境准备 组件 版本 操作系统 Ubuntu 22.04.4 LTS minik ...

  2. lottie-web动画库在HTML5页面中和在vue项目中的两种使用方式

    本文主要介绍lottie-web动画库在HTML5页面中和在vue项目中的两种使用方式. 1.在HTML5页面中的使用方式 具体使用步骤详见下面的代码: <!DOCTYPE html> & ...

  3. .Net程序员机会来了,微软官方新推出一个面向Windows开发者本地运行AI模型的开源工具

    想要开发AI产品的.Net程序员机会来了,这个项目应该好好研究. 虽然说大模型基本都有提供网络API,但肯定没有直接使用本地模型速度快. 最近微软官方新推出AI Dev Gallery开源项目,可以帮 ...

  4. 记一次cannot access its superinterface问题的的排查 → 强如Spring也一样写Bug

    开心一刻 昨天在幼儿园,领着儿子在办公室跟他班主任聊他的情况 班主任:皓瑟,你跟我聊天是不是紧张呀 儿子:是的,老师 班主任:不用紧张,我虽然是你的班主任,但我也才22岁,你就把我当成班上的女同学 班 ...

  5. 手把手带你使用Karpenter减少K8s集群资源浪费

    Kubernetes 集群的主要成本因素之一是数据平面上的计算层.将 Kubernetes 集群运行在 Amazon EC2 Spot 实例上是一种显著降低计算成本的有效方式.使用 Spot 实例可以 ...

  6. 单点登录-OAuth2

    单点登录的实现原理 单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来 ...

  7. biancheng-Spring Cloud Alibaba Nacos

    参考http://c.biancheng.net/springcloud/what-is-alibaba.html http://c.biancheng.net/springcloud/nacos.h ...

  8. String、StringBuffer、StringBuilder三者的异同

    /*String.StringBuffer.StringBuilder三者的异同?String:不可变的字符序列:底层使用char[]存储StringBuffer:可变的字符序列:线程安全的,效率低: ...

  9. PayDay Intermediate

    nmap + dirsearch 发现web站点 扫目录 ┌──(root㉿kali)-[/home/ftpuserr] └─# nmap -p- -A 192.168.167.39 Starting ...

  10. Zabbix 安装报错解析

    一.Q:Error connecting to database: Access denied for user 'zabbix' @ 'localhost' to database 'zabbix' ...