springcloudtencetn 父工程:

pom

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>com.gton</groupId>
<artifactId>cloud</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>gateway</module>
<module>usermanager</module>
<module>commodity</module>
<module>back-stage-management</module>
<module>common</module>
</modules>
<name>cloud</name>
<description>Spring Cloud Tencent +北极星(服务管理 流量管理 故障容错 配置管理) 微服务架构系统</description> <properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-cloud-tencent-version>1.7.0-2021.0.3</spring-cloud-tencent-version>
<spring-cloud-dependencies-version>2021.0.3</spring-cloud-dependencies-version>
<projectlombok-version>1.18.16</projectlombok-version>
<spring-boot.version>2.6.9</spring-boot.version>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>${spring-cloud-tencent-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build> </project>

gateway导入pom

<?xml version="1.0" encoding="UTF-8"?>
<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>cloud</artifactId>
<groupId>com.gton</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>gateway</artifactId> <properties>
<fastJson-version>2.0.18</fastJson-version>
</properties> <dependencies> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <!--网关路由-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency> <!--服务注册与发现-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency> <!--服务限流-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency> <!--北极星配置中心-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
</dependency> <!--北极星熔断-->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency> <!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency> <!-- bootstrap最高级启动配置读取 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-spring-retry</artifactId>
</dependency> <!--使用gateway做网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastJson-version}</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</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"] #读取的文件名

北极星控制台配置

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<RouteDefinition> definitions) {
log.info("gateway update route {}", definitions);
// 删除缓存routerDefinition
List<RouteDefinition> 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<RouteDefinition> routeUpdates = new ArrayList<>();
// 获取配置修改的所有key
Set<String> changedKeys = event.changedKeys();
// 保留已经处理的
Set<String> 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<RouteDefinition> 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<PredicateDefinition> 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<String, String> 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<String, String> args = predicateDefinition.getArgs();
args.put(split[0], split[1]);
predicates.add(predicateDefinition);
} List<FilterDefinition> 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<String, String> 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<String, String> 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<String> 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<String> rule = readRouterConfig.getRule();
List<RouteDefinition> 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("网关路由配置加载结束。。。。。。");
}
}

到此结束!!!!

北极星Polaris+Gateway动态网关配置!的更多相关文章

  1. Nacos下动态路由配置

    前言 Nacos最近项目一直在使用,其简单灵活,支持更细粒度的命令空间,分组等为麻烦复杂的环境切换提供了方便:同时也很好支持动态路由的配置,只需要简单的几步即可.在国产的注册中心.配置中心中比较突出, ...

  2. Linux IP和网关配置

    操作环境 SuSE11/SuSE10 配置方法一<永久有效,重启不失效> 通过修改/etc/sysconfig/network/ifcfg-eth*文件直接配置,服务器重启不失效,建议使用 ...

  3. DHCP:动态主机配置协议

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...

  4. DHCP(动态主机配置协议)工作流程

    一.DHCP的作用 我们先来看一下什么是DHCP,DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)它可以为客户机自动分配IP地址.子网掩码以及缺省网 ...

  5. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  6. Spring Cloud Alibaba | Nacos动态网关路由

    Spring Cloud Alibaba | Gateway基于Nacos动态网关路由 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud ...

  7. spring cloud 2.x版本 Gateway动态路由教程

    摘要 本文采用的Spring cloud为2.1.8RELEASE,version=Greenwich.SR3 本文基于前面的几篇Spring cloud Gateway文章的实现. 参考 Gatew ...

  8. 动态主机配置协议-DHCP

    一.DHCP 概述 当局域网中有大量的PC时.如果我们逐个为每台PC去手动配置IP.那这就是一个吃力也未必讨好的办法 累死你 而DHCP 刚好可以解决这个问题.DHCP全称(动态主机配置协议).使用的 ...

  9. Spring Cloud 系列之 Gateway 服务网关(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Gateway 服务网关(一) 本篇文章讲解 Gateway 网关的多种路由规则.动态路由规则(配合服务发现的路由规则 ...

  10. 【转载】茶叶蛋干货!《超容易的Linux系统管理入门书》(连载十)进行动态主机配置DHCP

    使用动态主机配置协议DHCP(Dynamic Host Configuration Protocol)则可以避免网络参数变化后一些繁琐的配置,客户端可以从DHCP服务端检索相关信息并完成相关网络配置, ...

随机推荐

  1. torch.sort 和 torch.argsort

    定义 torch.sort(input,dim,descending) torch.argsort(input,dim,descending) 用法 torch.sort:对输入数据排序,返回两个值, ...

  2. [Python]-opencv-python模块(cv2)-图片读取和格式转换

    python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ...

  3. SQL 时间范围和时间粒度

    前言 使用 SQL 进行业务数据计算时,经常会遇到两个概念:时间范围 和 时间粒度 .以 最近一天的每小时的用户访问人数 为例: 最近一天 是时间范围 每小时 是时间粒度 常见的时间范围:最近五分钟. ...

  4. OKR之剑(理念篇)02—— OKR布道之旅

    作者:vivo互联网平台产品研发团队 1.我们是如何引入的 1.1.企业文化匹配 大概是在2013年底,一些创业者在硅谷深受OKR洗礼,并在自己的公司内小范围运用,以此OKR开始传入中国.而vivo初 ...

  5. Elastic Stack 8.0 再次创建enrollment token

    enrollment token 在第一个 Elasticsearch 启动后的有效时间为30分钟.超过30分钟的时间上述 token 将会无效. enrollment token分两个,一个是kib ...

  6. vivo 公司 Kubernetes 集群 Ingress 网关实践

    文章转载自:https://mp.weixin.qq.com/s/qPqrJ3un1peeWgG9xO2m-Q 背景 vivo 人工智能计算平台小组从 2018 年底开始建设 AI 计算平台至今,已经 ...

  7. rpm,docker,k8s三种方式安装部署GitLab服务

    rpm方式 源地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ wget https://mirrors.tuna.tsinghua ...

  8. Opengl ES之纹理贴图

    纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...

  9. Vu3.x如何给v-for循环出来的输入框绑定v-mode的值,以及实现父子组件传值、双向绑定

    观前须知:本人演示使用的input是自己手敲的,如果使用的是element-ui等表单组建的input框请选择性参考,不保证我的方法对你们也完全有效. 父组件代码: 这里我的MiniInput是以组件 ...

  10. 它让你1小时精通RabbitMQ消息队列(新增死信处理)

    支持.NET/.NET Framework/.NET Core RabbitMQ作为一款主流的消息队列工具早已广受欢迎.相比于其它的MQ工具,RabbitMQ支持的语言更多.功能更完善. 本文提供一种 ...