SpringCloud快速入门--GateWay路由网关与Config配置中心

GateWay路由网关

一般情况下,不是所有微服务都需要直接暴露给外部调用,这时可以使用路由机制,添加一层防护,让所有请求全部通过路由来转发到各个微服务,并且转发给多个微服务实例也可以实现负载均衡。

部署网关步骤如下:

  1. 创建一个新模块,添加如下依赖:

    xml 复制代码
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    1. 编写配置文件

      yaml 复制代码
      server:
        port: 8500
      spring:
        application:
          name: gateway-service
      eureka:
        # 修改客户端设置
        client:
          # 指向eureka服务端
          service-url:
            defaultZone: http://localhost:8801/eureka,http://localhost:8802/eureka
      1. 编写启动类

        java 复制代码
        @SpringBootApplication
        public class AppGateway
        {
            public static void main( String[] args )
            {
                SpringApplication.run(AppGateway.class, args);
            }
        }

        这时就可以启动网关服务了。

    2. 配置路由服务:

      yaml 复制代码
      spring:
        application:
          name: gateway-service
        cloud:
          gateway:
            # 配置路由,这是一个列表
            routes:
            - id: borrow-service  # 路由名称
              uri: lb://borrow-service # 路由的地址,lb表示使用负载均衡到微服务。也可以使用HTTP正常转发
              predicates: # 路由规则,断言什么请求会被路由
              - Path=/borrow/** #只要是访问这个路径,一律都都被路由到上面指定的服务

      此时,当我们访问借阅服务时,可以直接访问http://localhost:8500/borrow/1 此时会通过网关访问borrow-service服务。

      而且使用原来的地址http://localhost:8301/borrow/1 也可以访问。

路由过滤器

路由过滤器支持以某种方式修改传入的HTTP请求或返回的HTTP响应,路由过滤器的范围是某一个理由,跟之前的断言一样。Spring Cloud Gateway 内置很多的路由过滤器。

比如我们希望在请求到达时,在请求头中添加一些信息再转发给我们的服务,这时候就可以使用路由过滤器来完成,只需要对配置文件进行修改:

yaml 复制代码
spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      # 配置路由,这是一个列表
      routes:
      - id: borrow-service  # 路由名称
        uri: lb://borrow-service # 路由的地址,lb表示使用负载均衡到微服务。也可以使用HTTP正常转发
        predicates: # 路由规则,断言什么请求会被路由
        - Path=/borrow/** #只要是访问这个路径,一律都都被路由到上面指定的服务
      # 继续添加新的路由配置,这里以书籍管理服务为例
      - id: book-service
        uri: lb://book-service
        predicates:
        - Path=/book/**
        filters: # 添加过滤器
          # 添加请求头信息
        - AddRequestHeader=Test, HelloWorld!

此时通过网关访问book-service服务,会自动给请求头添加Test=HelloWorld! 信息。

访问地址是:http://localhost:8500/book/1

除了针对某一个路由配置过滤器之外,也可以自定义全局过滤器。但是需要我们编写代码,比如要实现拦截没有携带指定请求参数的请求(在gateway网关项目中编写一个类实现GlobalFilter接口):

java 复制代码
@Component
public class TestFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 先获取ServerHttpRequest 对象,这里不是HttpServletRequest
        ServerHttpRequest request = exchange.getRequest();
        // 获取所有请求的参数
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        // 判断是否包含test参数
        List<String> test = queryParams.get("test");
        if (test != null && test.contains("1")) {
            // 将ServerWebExchange对象传递到下一个过滤连
            return chain.filter(exchange);
        }else{
            // 不再向下传递,直接返回响应
            return exchange.getResponse().setComplete();
        }
    }
}

然后重启gateway服务即可生效。

过滤器可以存在多个,我们可以指定过滤器之间的顺序,需要编写一个类,实现Ordered接口:

java 复制代码
@Component
public class TestFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 先获取ServerHttpRequest 对象,这里不是HttpServletRequest
        ServerHttpRequest request = exchange.getRequest();
        // 获取所有请求的参数
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        // 判断是否包含test参数
        List<String> test = queryParams.get("test");
        if (test != null && test.contains("1")) {
            // 将ServerWebExchange对象传递到下一个过滤连
            return chain.filter(exchange);
        }else{
            // 不再向下传递,直接返回响应
            return exchange.getResponse().setComplete();
        }
    }

    // 指定此过滤器的优先级,值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

order值越小,优先级越高。无论全局过滤器还是配置文件中的单个过滤器,都受到order值的影响(单个路由过滤器order值从上往下的顺序从1开始递增),最终都是按order顺序执行。当order一样是,全局过滤器优先于单独的路由过滤器。

Config配置中心

微服务项目需要部署很多个实例,每个实例都有自己的配置文件,这样手动改起来非常麻烦,这时就需要一种配置文件管理工具,集中的对配置文件进行配置。

Spring cloud Config 为分布式系统中的外部配置提供服务器端和客户端的支持。使用Config Server 集中管理所有环境中应用程序的外部配置。

实际上 Spring Cloud Config就是一个配置中心,所有的服务都可以从配置中心取出配置,而配置中心又可以从Github远程仓库中获取云端的配置文件,这样只需要修改Github中的配置就可以对所有服务进行配置管理。

部署配置中心的步骤如下:

  1. 新建一个模块,并导入依赖:

    xml 复制代码
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    1. 编写启动类

      java 复制代码
      @SpringBootApplication
      @EnableConfigServer
      public class AppConfig
      {
          public static void main( String[] args )
          {
              SpringApplication.run(AppConfig.class, args);
          }
      }
      1. 编写配置文件

        yaml 复制代码
        server:
          port: 8700
        spring:
          application:
            name: config-service
        eureka:
          # 修改客户端设置
          client:
            # 指向eureka服务端
            service-url:
              defaultZone: http://localhost:8801/eureka,http://localhost:8802/eureka
  2. 创建一个git本地仓库,然后再文件夹中创建一些配置文件,名称最好是【服务名称】-【环境】.yml.

    然后将配置信息写入配置文件中,然后提交文件。
    5. 修改git配置信息

    yaml 复制代码
    spring:
      application:
        name: config-service
      cloud:
        config:
          server:
            git:
              # 这里是本地仓库地址,远程仓库的话直接填写远程仓库地址http://git....
              uri: file://D:/1_ali/code/springCloudConfig
              # 设置默认分支
              default-label: master

    然后启动config服务,可通过以下格式访问:

    客户端配置

    现在可以从服务器端读取配置,可以删除本地的application.yml文件(也可以不删除,这样服务器配置和本地配置都会加载),改用bootstrap.yml(在application.yml之前加载)

    1. 先在微服务模块引入相关依赖:

      xml 复制代码
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-config</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-bootstrap</artifactId>
      </dependency>
      1. 编辑bootstrap.yml文件内容:

        yaml 复制代码
        spring:
          cloud:
            config:
              # 名称,其实就是文件名称
              name: book-service
              # 配置服务器的地址
              uri: http://localhost:8700
              # 环境
              profile: dev
              # 分支
              label: master
    2. 启动服务即可生效。

    微服务CAP原则

    CAP原则又称CAP定理,指在一个分布式系统中,存在Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可同时保证。最多只能保证其中的两者

    一致性(C):分布式系统中的所有数据备份,在同一时刻都是同样的值(所有节点无论何时访问都能拿到最新的值)

    可用性(A): 系统中非故障节点收到的每个请求都必须得到响应

    分区容错性(P): 分布式系统中,节点之间的网络是连通的,然而可能因为一些故障(网络丢包),使节点之间不连通,导致整个网络分成了几块区域,数据就散布在了这些不联通的区域中(这样可能会导致某些分区节点的数据访问失败,我们需要容忍这些不可靠的情况)。

    总的来说,数据存放的节点越多,分区容忍性越高,但是复制更新的次数就越多,一致性就会降低。同时为了保持一致性,更新所有节点数据所需要的时间就越长,那么可用性就会降低。

    所以说,只能存在以下三种方案:

    选型 特点 典型系统 适用场景
    CP 分区时强一致,但可能拒绝请求(不可用) ZooKeeper、etcd、HBase 金融、支付、配置中心
    AP 分区时高可用,但数据可能不一致(最终一致) Cassandra、DynamoDB、Redis 集群 电商、社交、缓存
    CA 放弃 P,仅在无分区时同时满足 C 和 A 单机数据库、小型局域网 非分布式、无网络风险场景
相关推荐
云烟成雨TD21 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Java成神之路-1 天前
SpringMVC 响应实战指南:页面、文本、JSON 返回全流程(Spring系列13)
java·spring·json
砍材农夫1 天前
spring-ai 第六模型介绍-聊天模型
java·人工智能·spring
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【5】ReactAgent 构建器深度源码解析
java·人工智能·spring
Flittly1 天前
【SpringAIAlibaba新手村系列】(15)MCP Client 调用本地服务
java·笔记·spring·ai·springboot
Flittly1 天前
【SpringAIAlibaba新手村系列】(14)MCP 本地服务与工具集成
java·spring boot·笔记·spring·ai
mfxcyh1 天前
基于xml、注解、JavaConfig实现spring的ioc
xml·java·spring
Flittly1 天前
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
java·spring boot·spring·ai
xdscode1 天前
Spring 依赖注入方式全景解析
java·后端·spring