• SpringCloud 网关【Gateway】


    目录

    1. Spring Cloud Gateway 

    2. 使用 

    2.1 导入pom依赖

    2.2 application.yml文件

    2.3 启动类配置

    2.4 方式一

    2.5 方式二

    2.6 方式三(动态路由)


    1. Spring Cloud Gateway 

    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可以对请求和响应进行处理。

    2. 使用 

         2.1 导入pom依赖

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.jmhgroupId>
    6. <artifactId>nacos_gatewayartifactId>
    7. <version>0.0.1-SNAPSHOTversion>
    8. <name>nacos_gatewayname>
    9. <description>Demo project for Spring Bootdescription>
    10. <properties>
    11. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    12. <maven.compiler.source>1.7maven.compiler.source>
    13. <maven.compiler.target>1.7maven.compiler.target>
    14. <spring-boot.version>2.4.1spring-boot.version>
    15. <spring-cloud.version>2020.0.0spring-cloud.version>
    16. <spring-cloud-alibaba.version>2021.1spring-cloud-alibaba.version>
    17. properties>
    18. <dependencies>
    19. <dependency>
    20. <groupId>org.springframework.bootgroupId>
    21. <artifactId>spring-boot-starter-testartifactId>
    22. dependency>
    23. <dependency>
    24. <groupId>com.alibaba.cloudgroupId>
    25. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    26. dependency>
    27. <dependency>
    28. <groupId>org.springframework.cloudgroupId>
    29. <artifactId>spring-cloud-starter-openfeignartifactId>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.cloudgroupId>
    33. <artifactId>spring-cloud-loadbalancerartifactId>
    34. dependency>
    35. <dependency>
    36. <groupId>ma.glasnost.orikagroupId>
    37. <artifactId>orika-coreartifactId>
    38. <version>1.4.6version>
    39. dependency>
    40. <dependency>
    41. <groupId>org.projectlombokgroupId>
    42. <artifactId>lombokartifactId>
    43. dependency>
    44. <dependency>
    45. <groupId>com.alibaba.cloudgroupId>
    46. <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
    47. dependency>
    48. <dependency>
    49. <groupId>org.springframework.cloudgroupId>
    50. <artifactId>spring-cloud-starter-bootstrapartifactId>
    51. dependency>
    52. <dependency>
    53. <groupId>org.springframework.bootgroupId>
    54. <artifactId>spring-boot-starter-webfluxartifactId>
    55. dependency>
    56. <dependency>
    57. <groupId>org.springframework.cloudgroupId>
    58. <artifactId>spring-cloud-starter-gatewayartifactId>
    59. dependency>
    60. <dependency>
    61. <groupId>org.springframework.bootgroupId>
    62. <artifactId>spring-boot-starter-actuatorartifactId>
    63. dependency>
    64. <dependency>
    65. <groupId>org.springframework.cloudgroupId>
    66. <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
    67. <version>2.2.9.RELEASEversion>
    68. dependency>
    69. <dependency>
    70. <groupId>io.projectreactorgroupId>
    71. <artifactId>reactor-testartifactId>
    72. <scope>testscope>
    73. dependency>
    74. <dependency>
    75. <groupId>com.alibabagroupId>
    76. <artifactId>fastjsonartifactId>
    77. <version>1.2.35version>
    78. dependency>
    79. dependencies>
    80. <dependencyManagement>
    81. <dependencies>
    82. <dependency>
    83. <groupId>org.springframework.bootgroupId>
    84. <artifactId>spring-boot-dependenciesartifactId>
    85. <version>${spring-boot.version}version>
    86. <type>pomtype>
    87. <scope>importscope>
    88. dependency>
    89. <dependency>
    90. <groupId>org.springframework.cloudgroupId>
    91. <artifactId>spring-cloud-dependenciesartifactId>
    92. <version>${spring-cloud.version}version>
    93. <type>pomtype>
    94. <scope>importscope>
    95. dependency>
    96. <dependency>
    97. <groupId>com.alibaba.cloudgroupId>
    98. <artifactId>spring-cloud-alibaba-dependenciesartifactId>
    99. <version>${spring-cloud-alibaba.version}version>
    100. <type>pomtype>
    101. <scope>importscope>
    102. dependency>
    103. dependencies>
    104. dependencyManagement>
    105. <build>
    106. <plugins>
    107. <plugin>
    108. <groupId>org.springframework.bootgroupId>
    109. <artifactId>spring-boot-maven-pluginartifactId>
    110. plugin>
    111. plugins>
    112. build>
    113. project>

        2.2 application.yml文件

    1. server:
    2. port: 8084
    3. spring:
    4. application:
    5. name: nacos-gateway
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: 127.0.0.1:8848

        2.3 启动类配置

    1. package com.jmh.nacos_gateway;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    5. @SpringBootApplication
    6. @EnableDiscoveryClient
    7. @SuppressWarnings("all")
    8. public class NacosGatewayApplication {
    9. public static void main(String[] args) {
    10. SpringApplication.run(NacosGatewayApplication.class, args);
    11. }
    12. }

       2.4 方式一

    • application.yml文件 
    1. server:
    2. port: 8084
    3. spring:
    4. application:
    5. name: nacos-gateway
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: 127.0.0.1:8848
    10. gateway:
    11. discovery:
    12. locator:
    13. #是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
    14. #为true代表开启基于服务发现的路由规则。
    15. enabled: true
    16. #配置之后访问时service-id无需大写
    17. lower-case-service-id: true

       2.5 方式二

    •  application.yml文件 
    1. server:
    2. port: 8084
    3. spring:
    4. application:
    5. name: nacos-gateway
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: 127.0.0.1:8848
    10. gateway:
    11. discovery:
    12. locator:
    13. #是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
    14. #为true代表开启基于服务发现的路由规则。
    15. enabled: false
    16. #配置之后访问时service-id无需大写
    17. lower-case-service-id: true
    18. routes:
    19. # 路由标识(id:标识,具有唯一性)
    20. - id: user-consumer-api
    21. #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
    22. uri: lb://nacos-consumer
    23. #优先级,越小越优先
    24. #order: 999
    25. #路由条件(predicates:断言)
    26. predicates:
    27. # 路径匹配,
    28. - Path=/aa/**
    29. filters:
    30. #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
    31. #前缀过滤,请求地址:http://localhost:8084/usr/hello
    32. #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
    33. #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
    34. - StripPrefix=1
    35. # 路由标识(id:标识,具有唯一性)
    36. - id: user-provider-api
    37. #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
    38. uri: lb://nacos-provider
    39. #优先级,越小越优先
    40. #order: 999
    41. #路由条件(predicates:断言)
    42. predicates:
    43. # 路径匹配,
    44. - Path=/bb/**
    45. filters:
    46. #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
    47. #前缀过滤,请求地址:http://localhost:8084/usr/hello
    48. #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
    49. #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
    50. - StripPrefix=1

        2.6 方式三(动态路由)

             2.6.1. application.yml文件

    1. server:
    2. port: 8084
    3. spring:
    4. application:
    5. name: nacos-gateway
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: 127.0.0.1:8848
    10. gateway:
    11. discovery:
    12. locator:
    13. #是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
    14. #为true代表开启基于服务发现的路由规则。
    15. enabled: false
    16. #配置之后访问时service-id无需大写
    17. lower-case-service-id: true
    18. #自定义配置
    19. gateway:
    20. nacos:
    21. server-addr: ${spring.cloud.nacos.discovery.server-addr}
    22. # namespace: xxx-xx-xx-xx #可在这里设置获取是哪一个命名空间的文件 不设置默认公开的publie
    23. data-id: gateway.json #这个文件是nacos外部文件名称
    24. group: DEFAULT_GROUP

              2.6.2 nacos外部配置文件数据

    • gateway.json(注!文件后缀是.json是个json文件)
    1. {
    2. "refreshGatewayRoute": true,
    3. "routeList": [
    4. {
    5. "id": "consumer-api",
    6. "predicates": [
    7. {
    8. "name": "Path",
    9. "args": {
    10. "_genkey_0": "/consumer/**"
    11. }
    12. }
    13. ],
    14. "filters": [
    15. {
    16. "name": "StripPrefix",
    17. "args": {
    18. "_genkey_0": "1"
    19. }
    20. }
    21. ],
    22. "uri": "lb://nacos-consumer",
    23. "order": 0
    24. },
    25. {
    26. "id": "provider-api",
    27. "predicates": [
    28. {
    29. "name": "Path",
    30. "args": {
    31. "_genkey_0": "/provider/**"
    32. }
    33. }
    34. ],
    35. "filters": [
    36. {
    37. "name": "StripPrefix",
    38. "args": {
    39. "_genkey_0": "1"
    40. }
    41. }
    42. ],
    43. "uri": "lb://nacos-provider",
    44. "order": 0
    45. }
    46. ]
    47. }

              2.6.3 pojo模块

    •   FilterEntity
    1. package com.jmh.nacos_gateway.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import lombok.experimental.Accessors;
    6. import java.util.LinkedHashMap;
    7. import java.util.Map;
    8. /**
    9. * @author 蒋明辉
    10. */
    11. @SuppressWarnings("all")
    12. @Data
    13. @NoArgsConstructor
    14. @AllArgsConstructor
    15. @Accessors(chain = true)
    16. public class FilterEntity {
    17. //过滤器对应的Name
    18. private String name;
    19. //路由规则
    20. private Map args = new LinkedHashMap<>();
    21. }
    •  GatewayNacosProperties
    1. package com.jmh.nacos_gateway.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import lombok.experimental.Accessors;
    6. import org.springframework.boot.context.properties.ConfigurationProperties;
    7. import org.springframework.stereotype.Component;
    8. @SuppressWarnings("all")
    9. @Data
    10. @NoArgsConstructor
    11. @AllArgsConstructor
    12. @Accessors(chain = true)
    13. @ConfigurationProperties(prefix = "gateway.nacos")
    14. @Component
    15. public class GatewayNacosProperties {
    16. private String serverAddr;
    17. private String dataId;
    18. private String namespace;
    19. private String group;
    20. }
    •  PredicateEntity
    1. package com.jmh.nacos_gateway.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import lombok.experimental.Accessors;
    6. import java.util.LinkedHashMap;
    7. import java.util.Map;
    8. /**
    9. * @author 蒋明辉
    10. */
    11. @SuppressWarnings("all")
    12. @Data
    13. @NoArgsConstructor
    14. @AllArgsConstructor
    15. @Accessors(chain = true)
    16. public class PredicateEntity {
    17. //断言对应的Name
    18. private String name;
    19. //断言规则
    20. private Map args = new LinkedHashMap<>();
    21. }
    •  RouteEntity
    1. package com.jmh.nacos_gateway.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import lombok.experimental.Accessors;
    6. import java.util.ArrayList;
    7. import java.util.List;
    8. /**
    9. * @author 蒋明辉
    10. */
    11. @SuppressWarnings("all")
    12. @Data
    13. @NoArgsConstructor
    14. @AllArgsConstructor
    15. @Accessors(chain = true)
    16. public class RouteEntity {
    17. //路由id
    18. private String id;
    19. //路由断言集合
    20. private List predicates = new ArrayList<>();
    21. //路由过滤器集合
    22. private List filters = new ArrayList<>();
    23. //路由转发的目标uri
    24. private String uri;
    25. //路由执行的顺序
    26. private int order = 0;
    27. }
    •  DynamicRoutingConfig
    1. package com.jmh.nacos_gateway;
    2. import com.alibaba.fastjson.JSON;
    3. import com.alibaba.fastjson.JSONObject;
    4. import com.alibaba.nacos.api.NacosFactory;
    5. import com.alibaba.nacos.api.PropertyKeyConst;
    6. import com.alibaba.nacos.api.config.ConfigService;
    7. import com.alibaba.nacos.api.config.listener.Listener;
    8. import com.alibaba.nacos.api.exception.NacosException;
    9. import com.fasterxml.jackson.databind.ObjectMapper;
    10. import com.jmh.nacos_gateway.pojo.FilterEntity;
    11. import com.jmh.nacos_gateway.pojo.GatewayNacosProperties;
    12. import com.jmh.nacos_gateway.pojo.PredicateEntity;
    13. import com.jmh.nacos_gateway.pojo.RouteEntity;
    14. import lombok.extern.slf4j.Slf4j;
    15. import org.springframework.beans.factory.annotation.Autowired;
    16. import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
    17. import org.springframework.cloud.gateway.filter.FilterDefinition;
    18. import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
    19. import org.springframework.cloud.gateway.route.RouteDefinition;
    20. import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
    21. import org.springframework.context.ApplicationEventPublisher;
    22. import org.springframework.context.ApplicationEventPublisherAware;
    23. import org.springframework.context.annotation.Bean;
    24. import org.springframework.stereotype.Component;
    25. import org.springframework.web.util.UriComponentsBuilder;
    26. import reactor.core.publisher.Mono;
    27. import java.net.URI;
    28. import java.util.ArrayList;
    29. import java.util.List;
    30. import java.util.Properties;
    31. import java.util.concurrent.Executor;
    32. /**
    33. * 此类实现了Spring Cloud Gateway + nacos 的动态路由,
    34. * 它实现一个Spring提供的事件推送接口ApplicationEventPublisherAware
    35. */
    36. @SuppressWarnings("all")
    37. @Slf4j
    38. @Component
    39. public class DynamicRoutingConfig implements ApplicationEventPublisherAware {
    40. @Autowired
    41. private RouteDefinitionWriter routeDefinitionWriter;
    42. @Autowired
    43. private GatewayNacosProperties gatewayProperties;
    44. private ApplicationEventPublisher applicationEventPublisher;
    45. @Override
    46. public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    47. this.applicationEventPublisher = applicationEventPublisher;
    48. }
    49. /**
    50. * 这个方法主要负责监听Nacos的配置变化,这里先使用参数构建一个ConfigService,
    51. * 再使用ConfigService开启一个监听,
    52. * 并且在监听的方法中刷新路由信息。
    53. */
    54. @Bean
    55. public void refreshRouting() throws NacosException {
    56. //创建Properties配置类
    57. Properties properties = new Properties();
    58. System.out.println(gatewayProperties);
    59. //设置nacos的服务器地址,从配置类GatewayProperties中获取
    60. properties.put(PropertyKeyConst.SERVER_ADDR, gatewayProperties.getServerAddr());
    61. //设置nacos的命名空间,表示从具体的命名空间中获取配置信息,不填代表默认从public获得
    62. if (gatewayProperties.getNamespace() != null) {
    63. properties.put(PropertyKeyConst.NAMESPACE, gatewayProperties.getNamespace());
    64. }
    65. //根据Properties配置创建ConfigService类
    66. ConfigService configService = NacosFactory.createConfigService(properties);
    67. //获得nacos中已有的路由配置
    68. String json = configService.getConfig(gatewayProperties.getDataId(), gatewayProperties.getGroup(), 5000);
    69. if(null==json){
    70. log.warn("路由配置为空");
    71. return;
    72. }
    73. this.parseJson(json);
    74. //添加监听器,监听nacos中的数据修改事件
    75. configService.addListener(gatewayProperties.getDataId(), gatewayProperties.getGroup(), new Listener() {
    76. @Override
    77. public Executor getExecutor() {
    78. return null;
    79. }
    80. /**
    81. * 用于接收远端nacos中数据修改后的回调方法
    82. */
    83. @Override
    84. public void receiveConfigInfo(String configInfo) {
    85. log.warn(configInfo);
    86. //获取nacos中修改的数据并进行转换
    87. parseJson(configInfo);
    88. }
    89. });
    90. }
    91. /**
    92. * 解析从nacos读取的路由配置信息(json格式)
    93. */
    94. public void parseJson(String json) {
    95. log.warn("从Nacos返回的路由配置(JSON格式):" + json);
    96. boolean refreshGatewayRoute = JSONObject.parseObject(json).getBoolean("refreshGatewayRoute");
    97. if (refreshGatewayRoute) {
    98. List list = JSON.parseArray(JSONObject.parseObject(json).getString("routeList")).toJavaList(RouteEntity.class);
    99. for (RouteEntity route : list) {
    100. update(assembleRouteDefinition(route));
    101. }
    102. } else {
    103. log.warn("路由未发生变更");
    104. }
    105. }
    106. /**
    107. * 路由更新
    108. */
    109. public void update(RouteDefinition routeDefinition) {
    110. try {
    111. this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
    112. log.warn("路由删除成功:" + routeDefinition.getId());
    113. } catch (Exception e) {
    114. log.error(e.getMessage(), e);
    115. }
    116. try {
    117. routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
    118. this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
    119. log.warn("路由更新成功:" + routeDefinition.getId());
    120. } catch (Exception e) {
    121. log.error(e.getMessage(), e);
    122. }
    123. }
    124. /**
    125. * 路由定义
    126. */
    127. public RouteDefinition assembleRouteDefinition(RouteEntity routeEntity) {
    128. RouteDefinition definition = new RouteDefinition();
    129. // ID
    130. definition.setId(routeEntity.getId());
    131. // Predicates
    132. List pdList = new ArrayList<>();
    133. for (PredicateEntity predicateEntity : routeEntity.getPredicates()) {
    134. PredicateDefinition predicateDefinition = new PredicateDefinition();
    135. predicateDefinition.setArgs(predicateEntity.getArgs());
    136. predicateDefinition.setName(predicateEntity.getName());
    137. pdList.add(predicateDefinition);
    138. }
    139. definition.setPredicates(pdList);
    140. // Filters
    141. List fdList = new ArrayList<>();
    142. for (FilterEntity filterEntity : routeEntity.getFilters()) {
    143. FilterDefinition filterDefinition = new FilterDefinition();
    144. filterDefinition.setArgs(filterEntity.getArgs());
    145. filterDefinition.setName(filterEntity.getName());
    146. fdList.add(filterDefinition);
    147. }
    148. definition.setFilters(fdList);
    149. // URI
    150. URI uri = UriComponentsBuilder.fromUriString(routeEntity.getUri()).build().toUri();
    151. definition.setUri(uri);
    152. return definition;
    153. }
    154. }
  • 相关阅读:
    Ubuntu 安装 GDAL C++库
    基于Qt4的电机连续性测试软件开发
    从今天起,换一种轻松有趣的方式学习计算机底层技术!
    如何使用 PowerShell 锁定、解锁、启用和禁用 AD 帐户
    DVWA - Brute Force
    阿里云App备案详细流程_APP备案问题解答
    https下载图片
    C++头文件定义变量
    5.1 创建个人中心页面-后端部分
    DDD架构为什么应该首选六边形架构?
  • 原文地址:https://blog.csdn.net/m0_63300795/article/details/127762069