boot3+JDK17+spring-cloud-gateway:4.0.0+spring-cloud:2022.0.0.0+Nacos2.2.1配置动态路由的网关
项目依赖

配置
# 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配置动态路由的网关的更多相关文章
- spring cloud gateway 启动报错,Failed to bind on [0.0.0.0:xxx] bind(..) failed: 权限不够
最近把操作系统迁移到了deepin,不得不说Linux中需要学习的还是有很多的,本地启动网关的时候就遇到一个坑,特此记录一下,报错信息. Caused by: reactor.netty.Channe ...
- api网关揭秘--spring cloud gateway源码解析
要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux. 1.gateway 和zuul对比 I am the au ...
- 纠错帖:Zuul & Spring Cloud Gateway & Linkerd性能对比 (转载)
纠错帖:Zuul & Spring Cloud Gateway & Linkerd性能对比 Spring Cloud Spring Cloud Spring Cloud Gatew ...
- spring cloud gateway 之限流篇
转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...
- 微服务网关实战——Spring Cloud Gateway
导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...
- 微服务网关 Spring Cloud Gateway
1. 为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...
- 跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探
SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如 ...
- 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)
前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...
- Spring Cloud Gateway使用简介
Spring Cloud Gateway是类似Nginx的网关路由代理,有替代原来Spring cloud zuul之意: Spring 5 推出了自己的Spring Cloud Gateway,支持 ...
- Spring Cloud Gateway入坑记
Spring Cloud Gateway入坑记 前提 最近在做老系统的重构,重构完成后新系统中需要引入一个网关服务,作为新系统和老系统接口的适配和代理.之前,很多网关应用使用的是Spring-Clou ...
随机推荐
- Anaconda下载以前的旧版本
由于Anaconda新的版本,可能不太适合我们当前开发,我们需要下载历史版本. 可以尝试从两个地方下载:1.推荐从 "清华大学开源软件镜像站" 下载:https://mirrors ...
- 跟着源码学IM(九):基于Netty实现一套分布式IM系统
本文作者小傅哥,原题"使用DDD+Netty,开发一个分布式IM(即时通信)系统".为了提升阅读体验,有大量修订和改动,感谢原作者. 0.系列文章 <跟着源码学IM(一):手 ...
- 万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制
本文作者"Carson",现就职于腾讯公司,原题"高效保活长连接:手把手教你实现自适应的心跳保活机制",有较多修订和改动. 1.引言 当要实现IM即时通讯聊天. ...
- 从零开始的Python世界生活——语法基础先导篇(Python小白零基础光速入门上手)
从零开始的Python世界生活--语法基础先导篇(Python小白零基础光速入门上手) 1. 准备阶段 1.1 下载并安装Python 1.1.1 下载步骤: 访问Python官方网站:点击这里下载P ...
- 【Java 温故而知新系列】基础知识-02 数据基本类型
1.Java基本数据类型 Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间. 基本数据类型 数值型:整数类型(byte,short,int,lon ...
- JSON和XML的对比及应用领域
JSON和XML的对比 对比表格 对比维度 JSON XML 可读性 通常更简洁,易于阅读和编写12 结构清晰,但可能因标签和属性而显得冗长1 解析难度 解析通常比XML简单,多数现代编程语言内置解析 ...
- w3cschool-Netty 实战精髓篇1
https://www.w3cschool.cn/essential_netty_in_action/ Netty 异步和数据驱动 2021-04-22 14:57 更新 在学习Netty的异步和数据 ...
- 基于MPC的快速transformer安全推理框架
论文:一种基于安全多方计算的快速Transformer安全推理方案-刘伟欣 摘要 数据隐私泄露问题:当前Transformer推理应用中用户的数据会被泄露给模型提供方 安全推理方法:基于MPC实现Tr ...
- python:公共操作
运算符 公共方法 range """ 1 2 3 4 5 6 7 8 9 """ # 不包含 end# 如果不写开始,默认从零开始# 如果不 ...
- Codeforces Round 961 (Div. 2)
题目链接:Codeforces Round 961 (Div. 2) 总结:B1wa两发可惜,C出得有点小慢. A. Diagonals fag:贪心 Description:给定一个\(n * n\ ...