赞
踩
目录
1、在nacos中新注册一个配置,名叫dynamic-routing.json
Spring Cloud Gateway是Spring官方基于Spring5.0、SpringBoot2.0和Project Reactor等技术开发的网关,旨在为微服务框架提供一种简单而有效的统一的API路由管理方式,统一访问接口。
Spring Cloud Gateway作为Spring Cloud生态体系中的网关,目标是替代Netflix的Zuul,其不仅提供统 一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全、监控/埋点和限流等等。 它是基于Netty的响应式开发模式。
1️⃣路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL、一组断言工厂和一 组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。
2️⃣断言(Predicate):Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配 来自http Request中的任何信息,比如请求头和参数等。
3️⃣过滤器(Filter):一个标准的Spring WebFilter,Spring Cloud Gateway中的Filter分为两种类型: Gateway Filter和Global Filter。过滤器Filter可以对请求和响应进行处理。
在其中有gataway、nacos、以及loadbalancer的依赖,没有继承父依赖,所以的重新组织依赖
- <?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.zj</groupId>
- <artifactId>gateway</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>gateway</name>
- <description>gateway</description>
-
-
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
- <spring-boot.version>2.4.1</spring-boot.version>
- <spring-cloud.version>2020.0.0</spring-cloud.version>
- <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
- </properties>
-
-
-
-
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-webflux</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-gateway</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-loadbalancer</artifactId>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>${spring-boot.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>${spring-cloud.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-alibaba-dependencies</artifactId>
- <version>${spring-cloud-alibaba.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>1.8</source>
- <target>1.8</target>
- <encoding>UTF-8</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.4.1</version>
- <configuration>
- <mainClass>com.zj.gateway.GatewayApplication</mainClass>
- </configuration>
- <executions>
- <execution>
- <id>repackage</id>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- </project>
server: #此处的8084端口号,就好像以前外置的tomcat的8080,让我们通过浏览器进行访问 #但此服务只是做了一个路由,它会将请求路由到其它微服务(一般是消费者)进行处理 port: 8085 spring: application: #微服务名 name: gateway cloud: nacos: discovery: #指定nacos注册中心的地址 server-addr: 127.0.0.1:8848 gateway: discovery: locator: #是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false #为true代表开启基于服务发现的路由规则。 enabled: false #配置之后访问时service-id无需大写 lower-case-service-id: true routes: # 路由标识(id:标识,具有唯一性) - id: user-consumer-api #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死 uri: lb://consumer #优先级,越小越优先 #order: 999 #路由条件(predicates:断言) predicates: # 路径匹配, - Path=/cum/** filters: #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo #前缀过滤,请求地址:http://localhost:8084/usr/hello #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务 #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉 - StripPrefix=1 # 路由标识(id:标识,具有唯一性) - id: user-provider-api #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死 uri: lb://provider #优先级,越小越优先 #order: 999 #路由条件(predicates:断言) predicates: # 路径匹配, - Path=/api/pro/** filters: #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo #前缀过滤,请求地址:http://localhost:8084/usr/hello #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务 #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉 - StripPrefix=2 logging: level: #开启spring-Cloud-gateway的日志级别为debug,方便debug调试 org.springframework.cloud.gateway: trace org.springframework.http.server.reactive: debug org.springframework.web.reactive: debug reactor.ipc.netty: debug #springboot监控Actuator,暴露所有端点 management: endpoints: web: exposure: include: '*' #自定义配置 gateway: nacos: server-addr: ${spring.cloud.nacos.discovery.server-addr} # namespace: xxx-xx-xx-xx data-id: dynamic-routing.json group: DEFAULT_GROUP
gateway:
discovery:
locator:
#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
#为true代表开启基于服务发现的路由规则。
enabled: true
#配置之后访问时service-id无需大写
lower-case-service-id: true
gateway:
discovery:
locator:
#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
#为true代表开启基于服务发现的路由规则。
enabled: false
#配置之后访问时service-id无需大写
lower-case-service-id: true
routes:
# 路由标识(id:标识,具有唯一性)
- id: user-consumer-api
#目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
uri: lb://consumer
#优先级,越小越优先
#order: 999
#路由条件(predicates:断言)
predicates:
# 路径匹配,
- Path=/cum/**
filters:
#路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
#前缀过滤,请求地址:http://localhost:8084/usr/hello
#此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
#因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
- StripPrefix=1
# 路由标识(id:标识,具有唯一性)
- id: user-provider-api
#目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
uri: lb://provider
#优先级,越小越优先
#order: 999
#路由条件(predicates:断言)
predicates:
# 路径匹配,
- Path=/api/pro/**
filters:
#路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
#前缀过滤,请求地址:http://localhost:8084/usr/hello
#此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
#因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
- StripPrefix=2
enabled: false后的测试:
- <?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.zj</groupId>
- <artifactId>gateway</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>gateway</name>
- <description>gateway</description>
-
-
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
- <spring-boot.version>2.4.1</spring-boot.version>
- <spring-cloud.version>2020.0.0</spring-cloud.version>
- <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
- </properties>
-
-
-
-
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-webflux</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-gateway</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-loadbalancer</artifactId>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.35</version>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>${spring-boot.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>${spring-cloud.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-alibaba-dependencies</artifactId>
- <version>${spring-cloud-alibaba.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>1.8</source>
- <target>1.8</target>
- <encoding>UTF-8</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.4.1</version>
- <configuration>
- <mainClass>com.zj.gateway.GatewayApplication</mainClass>
- </configuration>
- <executions>
- <execution>
- <id>repackage</id>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- </project>
- {
- "refreshGatewayRoute": true,
- "routeList": [
- {
- "id": "consumer-api",
- "predicates": [
- {
- "name": "Path",
- "args": {
- "_genkey_0": "/cum/**"
- }
- }
- ],
- "filters": [
- {
- "name": "StripPrefix",
- "args": {
- "_genkey_0": "1"
- }
- }
- ],
- "uri": "lb://consumer",
- "order": 0
- },
- {
- "id": "provider-api",
- "predicates": [
- {
- "name": "Path",
- "args": {
- "_genkey_0": "/ccc/prv/**"
- }
- }
- ],
- "filters": [
- {
- "name": "StripPrefix",
- "args": {
- "_genkey_0": "2"
- }
- }
- ],
- "uri": "lb://provider",
- "order": 0
- }
- ]
- }
DynamicRoutingConfig:
- package com.zj.gateway;
-
- import com.alibaba.fastjson.JSON;
- 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.listener.Listener;
- import com.alibaba.nacos.api.exception.NacosException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.zj.gateway.pojo.FilterEntity;
- import com.zj.gateway.pojo.GatewayNacosProperties;
- import com.zj.gateway.pojo.PredicateEntity;
- import com.zj.gateway.pojo.RouteEntity;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
- 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.cloud.gateway.route.RouteDefinitionWriter;
- import org.springframework.context.ApplicationEventPublisher;
- import org.springframework.context.ApplicationEventPublisherAware;
- import org.springframework.context.annotation.Bean;
- import org.springframework.stereotype.Component;
- import org.springframework.web.util.UriComponentsBuilder;
- import reactor.core.publisher.Mono;
-
- import java.net.URI;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- import java.util.concurrent.Executor;
-
- /**
- * 此类实现了Spring Cloud Gateway + nacos 的动态路由,
- * 它实现一个Spring提供的事件推送接口ApplicationEventPublisherAware
- */
- @SuppressWarnings("all")
- @Slf4j
- @Component
- public class DynamicRoutingConfig implements ApplicationEventPublisherAware {
-
- @Autowired
- private RouteDefinitionWriter routeDefinitionWriter;
-
- @Autowired
- private GatewayNacosProperties gatewayProperties;
-
- @Autowired
- private ObjectMapper mapper;
-
- private ApplicationEventPublisher applicationEventPublisher;
-
- @Override
- public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
- this.applicationEventPublisher = applicationEventPublisher;
- }
-
- /**
- * 这个方法主要负责监听Nacos的配置变化,这里先使用参数构建一个ConfigService,
- * 再使用ConfigService开启一个监听,
- * 并且在监听的方法中刷新路由信息。
- */
- @Bean
- public void refreshRouting() throws NacosException {
- //创建Properties配置类
- Properties properties = new Properties();
- System.out.println(gatewayProperties);
- //设置nacos的服务器地址,从配置类GatewayProperties中获取
- properties.put(PropertyKeyConst.SERVER_ADDR, gatewayProperties.getServerAddr());
- //设置nacos的命名空间,表示从具体的命名空间中获取配置信息,不填代表默认从public获得
- if (gatewayProperties.getNamespace() != null) {
- properties.put(PropertyKeyConst.NAMESPACE, gatewayProperties.getNamespace());
- }
- //根据Properties配置创建ConfigService类
- ConfigService configService = NacosFactory.createConfigService(properties);
- //获得nacos中已有的路由配置
- String json = configService.getConfig(gatewayProperties.getDataId(), gatewayProperties.getGroup(), 5000);
- if(json==null) {
- return;
- }
-
- this.parseJson(json);
-
- //添加监听器,监听nacos中的数据修改事件
- configService.addListener(gatewayProperties.getDataId(), gatewayProperties.getGroup(), new Listener() {
- @Override
- public Executor getExecutor() {
- return null;
- }
-
- /**
- * 用于接收远端nacos中数据修改后的回调方法
- */
- @Override
- public void receiveConfigInfo(String configInfo) {
- log.warn(configInfo);
- //获取nacos中修改的数据并进行转换
- parseJson(configInfo);
- }
- });
-
- }
-
- /**
- * 解析从nacos读取的路由配置信息(json格式)
- */
- public void parseJson(String json) {
- log.warn("从Nacos返回的路由配置(JSON格式):" + json);
- boolean refreshGatewayRoute = JSONObject.parseObject(json).getBoolean("refreshGatewayRoute");
- if (refreshGatewayRoute) {
- List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(json).getString("routeList")).toJavaList(RouteEntity.class);
- for (RouteEntity route : list) {
- update(assembleRouteDefinition(route));
- }
- } else {
- log.warn("路由未发生变更");
- }
- }
-
-
- /**
- * 路由更新
- */
- public void update(RouteDefinition routeDefinition) {
-
- try {
- this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
- log.warn("路由删除成功:" + routeDefinition.getId());
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- }
- try {
- routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
- this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
- log.warn("路由更新成功:" + routeDefinition.getId());
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- }
-
- }
-
- /**
- * 路由定义
- */
- public RouteDefinition assembleRouteDefinition(RouteEntity routeEntity) {
-
- RouteDefinition definition = new RouteDefinition();
-
- // ID
- definition.setId(routeEntity.getId());
-
- // Predicates
- List<PredicateDefinition> pdList = new ArrayList<>();
- for (PredicateEntity predicateEntity : routeEntity.getPredicates()) {
- PredicateDefinition predicateDefinition = new PredicateDefinition();
- predicateDefinition.setArgs(predicateEntity.getArgs());
- predicateDefinition.setName(predicateEntity.getName());
- pdList.add(predicateDefinition);
- }
- definition.setPredicates(pdList);
-
- // Filters
- List<FilterDefinition> fdList = new ArrayList<>();
- for (FilterEntity filterEntity : routeEntity.getFilters()) {
- FilterDefinition filterDefinition = new FilterDefinition();
- filterDefinition.setArgs(filterEntity.getArgs());
- filterDefinition.setName(filterEntity.getName());
- fdList.add(filterDefinition);
- }
- definition.setFilters(fdList);
-
- // URI
- URI uri = UriComponentsBuilder.fromUriString(routeEntity.getUri()).build().toUri();
- definition.setUri(uri);
-
- return definition;
- }
-
- }
pojo--->FilterEntity
- package com.zj.gateway.pojo;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.experimental.Accessors;
-
- import java.util.LinkedHashMap;
- import java.util.Map;
-
- /**
- * @author zj
- */
- @SuppressWarnings("all")
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Accessors(chain = true)
- public class FilterEntity {
-
- //过滤器对应的Name
- private String name;
-
- //路由规则
- private Map<String, String> args = new LinkedHashMap<>();
-
- }
pojo--->GatewayNacosProperties
- package com.zj.gateway.pojo;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.experimental.Accessors;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
-
- @SuppressWarnings("all")
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Accessors(chain = true)
- @ConfigurationProperties(prefix = "gateway.nacos")
- @Component
- public class GatewayNacosProperties {
-
- private String serverAddr;
- private String dataId;
- private String namespace;
- private String group;
-
- }
pojo--->PredicateEntity
- package com.zj.gateway.pojo;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.experimental.Accessors;
-
- import java.util.LinkedHashMap;
- import java.util.Map;
-
- /**
- * @author zj
- */
- @SuppressWarnings("all")
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Accessors(chain = true)
- public class PredicateEntity {
-
- //断言对应的Name
- private String name;
-
- //断言规则
- private Map<String, String> args = new LinkedHashMap<>();
-
- }
pojo--->RouteEntity
- package com.zj.gateway.pojo;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.experimental.Accessors;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * @author hgh
- */
- @SuppressWarnings("all")
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Accessors(chain = true)
- public class RouteEntity {
-
- //路由id
- private String id;
-
- //路由断言集合
- private List<PredicateEntity> predicates = new ArrayList<>();
-
- //路由过滤器集合
- private List<FilterEntity> filters = new ArrayList<>();
-
- //路由转发的目标uri
- private String uri;
-
- //路由执行的顺序
- private int order = 0;
-
- }
当我在配置中修改路径之后就访问不到了
这就实现了动态路由
今天的知识就分享到这了,希望能够帮助到你!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。