spring cloud微服务实践七

在spring cloud 2.x以后,由于zuul一直停滞在1.x版本,所以spring官方就自己开发了一个项目 Spring Cloud Gateway.作为spring cloud微服务的网关组件.

注:这一个系列的开发环境版本为 java1.8, spring boot2.x, spring cloud Greenwich.SR2, IDE为 Intelli IDEA

spring cloud gateway 入门

根据官方的简介,它是spring mvc基础之上,旨在提供一个简单有效的路由管理方式,如 安全,监控/指标,和限流等.

相关概念

  • Route(路由):这是网关的基本构建部分。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
  • Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
  • Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。

工作流程

客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

Spring Cloud Gateway 的特征:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 易于编写的 Predicates 和 Filters
  • 限流
  • 路径重写

注: 以上引自: http://www.ityouknow.com

简单使用

添加依赖

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

配置文件

spring cloud gateway底层使用netty+webflux, 不再依赖web了

server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
      - id: iyk_route
        uri: http://www.ityouknow.com
        predicates:
        - Path=/spring-cloud

说明下该配置:

  • id:自定义的路由 ID,保持唯一
  • uri:目标服务地址
  • predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
  • filters:过滤规则

同样的,转发功能也可以使用代码来实现:

// 直接写在启动类中
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/about")
                        .uri("http://ityouknow.com"))
                .build();
    }

注: 虽然两种方法都可以,但还是建议写在配置文件中

路由规则

Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。

predicates

Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

接下来我们就来看看这些规则的具体使用方法:

时间匹配

predicate 支持设置一个时间,以这个时间为分界线,这个时间前的不能访问,这个时间之后的可以访问.

spring:
  cloud:
    gateway:
      routes:
       - id: time_route
        uri: http://example.com
        predicates:
         - After=2019-08-17T12:00:00+08:00[Asia/Shanghai]

Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai

After Route Predicate 是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在 2018年1月20日6点6分6秒之后的所有请求都转发到地址http://example.com。+08:00是指时间和UTC时间相差八个小时,时间地区为Asia/Shanghai

添加完路由规则之后,访问地址http://localhost:8080会自动转发到http://example.com。

Before Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的 After 改为 Before,如下:

spring:
  cloud:
    gateway:
      routes:
       - id: before_route
        uri: http://example.com
        predicates:
         - Before=2019-08-17T12:00:00+08:00[Asia/Shanghai]

既然有这个时间前After和这个时间后Before,predicate还支持在一段时间之内匹配,那就需要使用Between

spring:
  cloud:
    gateway:
      routes:
       - id: after_route
        uri: http://example.com
        predicates:
         - Between=2019-08-17T08:00:00+08:00[Asia/Shanghai], 2019-08-17T09:00:00+08:00[Asia/Shanghai]

这个功能刚好可以使用在一些抢购活动中.

Cookie 匹配

Cookie Route Predicate 可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。

spring:
  cloud:
    gateway:
      routes:
       - id: cookie_route
         uri: http://example.com
         predicates:
         - Cookie=a,b.c

这表示请求的cookie需要携带 a=b.c 才可以访问,否则就报404错误,可以使用 curl http://localhost:8080 --cookie "a=b.c"

Header 匹配

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中的属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://example.com
        predicates:
        - Header=X-Request-Id, \d+

同样的可以使用命令url http://localhost:8080 --header "X-Request-Id:11"来测试.

Host 匹配

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://example.com
        predicates:
        - Host=**.example.com

请求方法匹配

可以通过请求方式GET,POST,PATH和DELETE方法进行匹配:

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET

请求路径匹配

predicate接受两个参数,一个PathMatcher 表达式 和一个可选参数 matchOptionalTrailingSeparator

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Path=/foo/{segment},/bar/{segment}

能匹配到/foo/1, /foo/bar/bar/baz等路径。
同时也可以使用代码获取:

Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");

请求参数匹配

Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=baz

ip地址匹配

RemoteAddr Route Predicate 支持匹配相应的ip地址,如(IPv4 or IPv6),或者一个网段192.168.0.1/16,一个地址192.168.0.1

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

权重匹配

Weight Route Predicate 接受两个参数,分组和权重:

spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2

组合使用

除此之外,这些匹配还可以组合起来使用

spring:
  cloud:
    gateway:
      routes:
       - id: host_foo_path_headers_to_httpbin
        uri: http://example.com
        predicates:
        - Host=**.foo.org
        - Path=/headers
        - Method=GET
        - Header=X-Request-Id, \d+
        - Query=foo, ba.
        - Query=baz
        - Cookie=chocolate, ch.p
        - After=2019-08-18T12:00:00+08:00[Asia/Shanghai]

各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发

服务化

前面已经介绍了spring cloud gateway 的简单使用,现在我们就把它融入到微服务中,

添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置文件

修改配置文件,添加discovery的配置

server:
  port: 8888
spring:
  application:
    name: gateway
  cloud:
    gateway:
     discovery:
        locator:
         enabled: true
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/
logging:
  level:
    org.springframework.cloud.gateway: debug

配置说明:

  • spring.cloud.gateway.discovery.locator.enabled:是否与服务注册于发现组件进行结合,通过 serviceId 转发到具体的服务实例。默认为 false,设为 true 便开启通过服务中心的自动根据 serviceId 创建路由的功能。
  • eureka.client.service-url.defaultZone指定注册中心的地址,以便使用服务发现功能
  • logging.level.org.springframework.cloud.gateway 调整相 gateway 包的 log 级别,以便排查问题

修改完成后启动项目,访问注册中心地址 http://localhost:8000/ 即可看到名为GATEWAY的服务。

测试

将 spring cloud gateway 注册到服务中心之后,网关会自动代理所有的在注册中心的服务,访问这些服务的语法为:http://网关地址:端口/服务中心注册serviceId/具体的url
假如 producer 有一个 hello 服务,那使用 gateway 访问就变成 http://localhost:8888/producer/hello

基于Filter实现的功能

Spring Cloud Gateway 的 Filter 的生命周期有两个:“pre” 和 “post”。

  • PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

Spring Cloud Gateway 的 Filter 分为两种:GatewayFilter 与 GlobalFilter。GlobalFilter 会应用到所有的路由上,而 GatewayFilter 将应用到单个路由或者一个分组的路由上。

Spring Cloud Gateway 内置了9种 GlobalFilter,比如 Netty Routing Filter、LoadBalancerClient Filter、Websocket Routing Filter 等,具体大家参考官网内容。
利用 GatewayFilter 可以修改请求的 Http 的请求或者响应,或者根据请求或者响应做一些特殊的限制。

修改请求参数

我们可以使用 AddRequestParameter GatewayFilter来在转发时添加请求的参数。

application.xml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: http://example.org
        filters:
        - AddRequestParameter=foo, bar

这样以来就会给每个请求都加上foo=bar

路由转发

我们在配置中,指定转发的对象都是直接使用uri的,但是我们知道微服务中服务提供者通常都是动态变化的,所以为了应对这样的情况,可以修改uri为指定应用的名称。

#格式为:lb://应用注册服务名
uri: lb://producer

这里其实默认使用了全局过滤器 LoadBalancerClient ,当路由配置中 uri 所用的协议为 lb 时(以uri: lb://producer为例),gateway 将使用 LoadBalancerClient 把 spring-cloud-producer 通过 eureka 解析为实际的主机和端口,并进行负载均衡。

修改请求路径

StripPrefix Filter 是一个请求路径截取的功能,我们可以利用这个功能来做特殊业务的转发
application.xml

原文地址:https://www.cnblogs.com/xingyys/p/11370476.html

时间: 2024-10-10 23:07:28

spring cloud微服务实践七的相关文章

spring cloud微服务实践一

最近在学习spring框架.其中spring cloud在微服务方面很火,所以在学习过程中,也做一些记录. 注:这一个系列的开发环境版本为 java1.8, spring boot2.x. IDE为 Intelli IDEA spring cloud的简介 关于spring cloud是什么,做什么的问题这里就不再详细说明了.需要的可以看 这篇文章[http://www.ityouknow.com/springcloud/2017/05/01/simple-springcloud.html] (

spring cloud微服务实践四

spring cloud的hystrix还有一个配搭的库hystrix-dashboard,它是hystrix的一款监控工具,能直观的显示hystrix响应信息,请求成功率等.但是hystrix-dashboard只能查看单机和集群的信息,如果需要将多台的信息汇总起来的话就需要使用turbine. 注:这一个系列的开发环境版本为 java1.8, spring boot2.x, spring cloud Greenwich.SR2, IDE为 Intelli IDEA hystrix-dashb

Spring Cloud微服务实践之路- Eureka Server 中的第一个异常

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE

在阿里云容器服务上开发基于Docker的Spring Cloud微服务应用

本文为阿里云容器服务Spring Cloud应用开发系列文章的第一篇. 一.在阿里云容器服务上开发Spring Cloud微服务应用(本文) 二.部署Spring Cloud应用示例 三.服务发现 四.服务间通信与集成 五.服务智能路由 六.集中配置管理 七.高可用和容错 八.监控和日志 九.服务的部署和发布策略 微服务概述 单体应用通常指在一个程序中满足多个业务或技术领域的需求,不同的需求领域内化为模块.假定我们要开发一个Web应用,通常的MVC模式可以满足要求.针对不同领域有不少代码生成工具

关于Spring Cloud微服务架构

微服务架构 Spring Cloud解决的第一个问题就是:服务与服务之间的解耦.很多公司在业务高速发展的时候,服务组件也会相应的不断增加.服务和服务之间有着复杂的相互调用关系,经常有服务A调用服务B,服务B调用服务C和服务D ...,随着服务化组件的不断增多,服务之间的调用关系成指数级别的增长,这样最容易导致的情况就是牵一发而动全身.经常出现由于某个服务更新而没有通知到其它服务,导致上线后惨案频发.这时候就应该进行服务治理,将服务之间的直接依赖转化为服务对服务中心的依赖.Spring Cloud

spring cloud微服务分布式云架构 - Spring Cloud简介

Spring Cloud是一系列框架的有序集合.利用Spring Boot的开发模式简化了分布式系统基础设施的开发,如服务发现.注册.配置中心.消息总线.负载均衡.断路器.数据监控等(这里只简单的列了一部分),都可以用Spring Boot的开发风格做到一键启动和部署.Spring Cloud将目前比较成熟.经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终整合出一套简单易懂.易部署和易维护的分布式系统架构平台. Spring Clou

(一)spring cloud微服务分布式云架构 - Spring Cloud简介

Spring Cloud是一系列框架的有序集合.利用Spring Boot的开发模式简化了分布式系统基础设施的开发,如服务发现.注册.配置中心.消息总线.负载均衡.断路器.数据监控等(这里只简单的列了一部分),都可以用Spring Boot的开发风格做到一键启动和部署.Spring Cloud将目前比较成熟.经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终整合出一套简单易懂.易部署和易维护的分布式系统架构平台. Spring Clou

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售 一.分布式服务框架的发展 1.1 第一代服务框架 代表:Dubbo(Java).Orleans(.Net)等 特点:和语言绑定紧密 1.2 第二代服务框架 代表:Spring Cloud等 现状:适合混合式开发(例如借助Steeltoe OSS可以让ASP.Net Core与Spring Cloud集成),正值当年 1.3 第三代服务框架 代表:Service Mesh(服务网格) => 例如

spring cloud微服务分布式云架构-eureka 基础

在构建项目之前,我们先学习一下eureka,这是官方的讲解,我这边再重新帮大家回顾一下: 服务发现:Eureka客户端 Spring Cloud大型企业分布式微服务云架构源码请加一七九一七四三三八零哦 服务发现是基于微服务架构的关键原则之一.尝试配置每个客户端或某种形式的约定可能非常困难,可以非常脆弱.Netflix服务发现服务器和客户端是Eureka.可以将服务器配置和部署为高可用性,每个服务器将注册服务的状态复制到其他服务器. 如何包含Eureka客户端 要在您的项目中包含Eureka客户端