三、SpringCloud Netflix-入门

前言

SpringCloud入门,本文会继续上篇文章,对SpringCloud的组件做详细介绍,并对其使用方法做实例演示说明,本章主要是对SpringCloud的组件Gataway (网关)、Config (配置中心)做详细介绍学习,欢迎评论区讨论交流。

目录

前言

第一章 网关--Gataway

1、认识Gataway

2、Gataway的核心概念  

3、实例使用 

3.1、导入依赖

3.2、yml配置  

3.3、主启动类

4、Predicate断言工厂

5、 Gateway 的 Filter 过滤器

5.1. 自定义Gateway Filter

5.2、自定义GlobalFilter

6、Gateway跨域配置

第二章 配置中心--Config

总结



第一章 网关--Gataway

1、认识Gataway

Spring Cloud Gateway是Spring Cloud自己的产物,基于Spring 5 和Spring Boot 2.0 开发,Spring Cloud Gateway的出现是为了代替zuul,在Spring Cloud 高版本中没有对zuul 2.0进行集成,SpringCloud Gateway使用了高性能的Reactor模式通信框架Netty。

特点:

  • 基于 Spring 5,Project Reactor , Spring Boot 2.0

  • 默认集成 Hystrix 断路器

  • 默认集成 Spring Cloud DiscoveryClient (EurekaClient)

  • Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters

  • 支持动态路由、限流、路径重写

2、Gataway的核心概念  

  • Filter(过滤器):

Spring Cloud Gateway的Filter和Zuul的过滤器类似,可以在请求发出前后进行一些业务上的处理 ,这里分为两种类型的Filter,分别是Gateway Filter网关filter和Global Filter全局Filter, 他们的区别在后续会讲到。

  • Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。说白了就是把url请求路由到对应的资源(服务),或者说是一个请求过来Gateway应该怎么把这个请求转发给下游的微服务,转发给谁。

  • Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。简单理解就是处理HTTP请求的匹配规则,在什么样的请情况下才能命中资源继续访问。

工作方式:

Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种,下面是官方的执行流程图:

客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链来运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。

3、实例使用 

3.1、导入依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

3.2、yml配置  

#注册到EurekaServer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:10010/eureka/ #注册地址
  instance:
    instance-id: gateway-server #实例ID
spring:
  application:
    name: gateway-server #服务名
  cloud:
    gateway:
       discovery:
        locator:
          enabled: false #开放服务名访问方式
          lower-case-service-id: true #服务名小写
      routes:
        - id: user-server #指定服务名
          uri: lb://user-server #去注册中心找这个服务名
          predicates: #断言,匹配访问的路径
            - Path=service/user/**    #服务访问路径
          filters:
            - StripPrefix=2    #请求转发的时候会去掉 /user访问路径

除了要注册到Eureak以外,还需要配置Gataway的路由

  • spring.cloud.gateway.discovery.locator.enabled=false: 不开放服务名访问方式

  • spring.cloud.gateway.discovery.locator.lower-case-service-id: true 忽略服务名大小写,大写小写都可以匹配

  • spring.cloud.gateway.routes.id : 指定了路由的服务名,可以自己定义

  • spring.cloud.gateway.routes.uri=lb://user-server : 去注册中心找服务,采用负载均衡的方式请求。其实就是找要调用的服务。

  • spring.cloud.gateway.routes.predicates: 断言,这里使用的Path=/user/**,即匹配访问的路径如果匹配/user/就可以将请求路由(分发)到user-server这个服务上。

  • spring.cloud.gateway.routes.filters :这里使用StripPrefix=1主要是处理前缀 /user ,访问目标服务的时候会去掉前缀访问。这个需要根据url情况来定义。

3.3、主启动类

@SpringBootApplication
public class GatewayApplicaton {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplicaton.class);
    }
}

4、Predicate断言工厂

在Spring Cloud Gateway中,针对不同的场景内置的路由断言工厂,比如

  • Query Route Predicate Factory:根据查询参数来做路由匹配

  • RemoteAddr Route Predicate Factory:根据ip来做路由匹配

  • Header Route Predicate Factory:根据请求头中的参数来路由匹配

  • Host Route Predicate Factory:根据主机名来进行路由匹配

  • Method Route Predicate Factory :根据方法来路由匹配

  • Cookie Route Predicate Factory:根据cookie中的属性值来匹配

  • Before Route Predicate Factory:指定时间之间才能匹配

  • After Route Predicate Factory: 指定时间之前才能匹配

  • Weight Route Predicate Factory: 根据权重把流量分发到不同的主机

5、 Gateway 的 Filter 过滤器

 Gateway的Filter的zuul的Filter有相似之处,与zuul不同的是,Gateway的filter从生命周期上可以为“pre”和“post”类型。根据作用范围可分为针对于单个路由的gateway filter,和针对于所有路由的Global Filer

5.1. 自定义Gateway Filter

在Spring Cloud Gateway自定义过滤器,过滤器需要实现GatewayFilter和Ordered这两个接口。我们下面来演示自定义filter计算请求的耗时。

*耗时计算 GatewayFilter使用  实现GatewayFilter和Ordered这两个接口*/
public class RequestTimeFilter implements GatewayFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 开始时间
        long startTime = new Date().getTime();
        // 执行完成之后
        return chain.filter(exchange).then(

                Mono.fromRunnable(()->{
                    long overTime = new Date().getTime();
                    long time = overTime - startTime;
                    System.out.println("请求路径为:"+exchange.getRequest().getURI().getRawPath()+"耗时为:"+time);
                })
        );
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

提示: getOrder返回filter的优先级,越大的值优先级越低 , 在filterI方法中计算了请求的开始时间和结束时间  

还需要把该Filter配置在对应的路由上,配置如下:

//配置Filter作用于那个访问规则上
    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {

        return builder.routes().route(r -> r.path("/service/user/**")
                //去掉2个前缀
                        .filters(f -> f.stripPrefix(2)
                        .filter(new RequestTimeFilter())
                        .addResponseHeader("X-Response-test", "test"))
                        .uri("lb://user-service")
                        .order(0)
                        .id("test-RequestTimeFilter")
                ).build();
    }

5.2、自定义GlobalFilter

GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。 这里我们模拟了一个登陆检查的Filter.

@Component
public class LoginGlobleFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 获取请求头中名为 "token" 的所有值
        List<String> token = request.getHeaders().get("token");

        // 如果请求头中的 "token" 为空或不存在
        if (token == null || token.size() == 0) {
            // 获取响应对象
            ServerHttpResponse response = exchange.getResponse();
            // 构建错误结果
            HashMap<String, Object> data = new HashMap<>();
            data.put("code", 401);
            data.put("message", "未登录");

            DataBuffer buffer = null;
            try {
                // 将 "滚去登录" 字符串转换成字节数组
                byte[] bytes = "滚去登录".getBytes("utf-8");
                // 创建 DataBuffer 用于包装字节数组作为响应体
                buffer = response.bufferFactory().wrap(bytes);

                // 设置响应的状态码为 401 (未授权)
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // 添加响应头 "Content-Type",表示响应体为 JSON 格式
                response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            // 将错误结果写入响应体并返回给客户端
            return response.writeWith(Mono.just(buffer));
        }

        // 如果 "token" 存在且不为空,继续执行后续的过滤器链
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

6、Gateway跨域配置

 所谓的跨域是因为浏览器的同源(同一个域)策略限制,其实就是同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互 ,在前后端分离的项目架构中就会出现跨域问题,因为Gateway 网关是微服务的访问入口,所以我们只需要在Gateway配置跨域即可

 globalcors: #跨域配置
      cors-configurations:
        '[/**]':
          allowedOrigins: "*" #允许的站点
          allowedMethods: #允许的请求方式
            - GET
            - POST
            - DELETE
            - PUT
            - HEAD
            - CONNECT
            - TRACE
            - OPTIONS
          allowHeaders: #允许的请求头
            - Content-Type

第二章 配置中心--Config

在分布式系统中,由于服务数量很多,为了方便服务配置文件统一管理我们需要用到置中心组件。在Spring Cloud中,分布式配置中心组件spring cloud config 它可以帮我们集中管理配置文件,修改配置无需重启服务 等,它支持配置文件放在配置服务的本地,也支持放在远程如Git仓库中集中管理。在spring cloud config 分为了服务端 config server和客户端config client 两个角色。

工作流程:

使用spring cloud config管理配置文件,我们需要把微服务的配置文件上传到Git仓库 , 然后搭建独立的ConfigServer服务,ConfigServer除了要从Git仓库拉取配置之外,还要注册到EurekaServer中,我们把ConfigServer本身也当做是一个微服务(当然ConfigServer可以脱离注册中心使用,但是如果客户端使用服务发现的方式指向配置中心就需要注册到注册中心了),至于ConfigClient这需要集成到具体的微服务中,如支付服务,订单服务等。其工作流程是,微服务通过ConfigClient向配置中心ConfigServer发起请求获取配置文件,配置中心从GIT仓库获取配置,然后再一路返回给微服务。

总结

本文对SpringCloud做了简单介绍,并对SpringCloud的常用组件Gataway (网关)、Config (配置中心)做详细介绍和它们的使用流程,文章如有雷同纯属巧合,如需转载请私信联系,本文为Java技术小白,日常分享学习心得,欢迎您的探讨和交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值