第二十节--GateWay服务网关

Gatway现在已替换zuul
是什么?
   Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单、有效和统一的API路由管理方式,Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等
 
能干嘛?
   反向代理,流量监控,熔断,日志监控,鉴权等
 
Gateway的特性:
   动态路由:能够匹配任何请求属性,
   可以对路由指定predicate(断言)和Filter(过滤器)
   集成spring cloud服务发现功能
   易于编写的predicate(断言)和Filter(过滤器)
   请求限流功能
   支持路径重写
 
Gateway三大核心概念
   Route(路由):构建网关的基本模块,它有ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
 
   Predicate(断言):参考的是java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
 
   Filter(过滤):指spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由或者之后对请求进行修改。
 
 

 
使用的提供者是cloud-provider-payment8001,路由的使用开始
 
第一步:新建工程cloud-gateway-gateway9527,pom.xml文件
<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!-- 将微服务provider注册进eureka:引入eureka客户端 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>com.hx.springcloud</groupId>
        <artifactId>cloud-api-commos</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--热部署  -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
</dependencies>

第二步:yml文件

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment-routh #路由的ID 没有固定规则但要求唯一 建议配合服务名
          uri: http://localhost:8001 #匹配后提供的路由地址
          predicates:
            - Path=/admin/findPaymentById/** #断言 路径相匹配的进行路由


        - id: payment-routh2 #路由的ID 没有固定规则但要求唯一 建议配合服务名
          uri: http://localhost:8001 #匹配后提供的路由地址
          predicates:
            - Path=/admin/findPaymentList/** #断言 路径相匹配的进行路由


eureka:
  instance:
    instance-id: cloud-gateway9527   #改变客户端在服务端显示的名称
    prefer-ip-address: true #访问路径显示IP地址
  client: #讲客户端注册到服务器
    service-url:
      #defaultZone: http://eureka7001:7001/eureka/,http://eureka7002:7002/eureka/,http://eureka7003:7003/eureka/
      defaultZone: http://eureka7001:7001/eureka/,http://eureka7002:7002/eureka/

 

第三步:主启动类
@EnableEurekaClient
@SpringBootApplication
public class Gateway9527 {
    public static void main(String[] args) {
        SpringApplication.run(Gateway9527.class,args);
    }
}
第四步:启动eureka,gateway9527,cloud-provider-payment8001
    1 .使用8001访问
 
   2 .使用9527访问
 
 
目的主要是为了保护8001端口,访问提供者时不使用8001暴露,根据网关过滤从而保护
 

 
gateway配置有两种方法
第一种:yml配置
cloud:
  gateway:
    routes:
      - id: payment-routh #路由的ID 没有固定规则但要求唯一 建议配合服务名
        uri: http://localhost:8001 #匹配后提供的路由地址
        predicates:
          - Path=/admin/findPaymentById/** #断言 路径相匹配的进行路由

      - id: payment-routh2 #路由的ID 没有固定规则但要求唯一 建议配合服务名
        uri: http://localhost:8001 #匹配后提供的路由地址
        predicates:
          - Path=/admin/findPaymentList/** #断言 路径相匹配的进行路由
第二种:直接写java代码配置,自己写一个
   业务需求:通过9527网关访问到外网的百度新闻网址
   1 .别写一个配置类GatewayConfig
@Configuration
public class GatewayConfig {

/**
* 发送localhost:9527/guonei 请求时,将会转发到国内百度官网
*/
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_hx",
r->r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
routes.route("path_route_hx1",
r->r.path("/guoji")//跳到国际
.uri("http://news.baidu.com/guoji")).build();
return routes.build();

}

}
 
 
 
 

 
 
当前存在的问题? 一个端口就需要写一个id与之对应,如果存在N个端口,就不好维护,如何改进
 
  - id: payment-routh #路由的ID 没有固定规则但要求唯一 建议配合服务名
    uri: http://localhost:8001 #匹配后提供的路由地址
    predicates:
     - Path=/admin/findPaymentById/** #断言 路径相匹配的进行路由
 
只需要修改和添加以下即可
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: payment-routh #路由的ID 没有固定规则但要求唯一 建议配合服务名
         # uri: http://localhost:8001 #匹配后提供的路由地址
          uri: lb://cloud-payment-service #匹配之后提供服务的路由地址
          predicates:
            #- Path=/admin/findPaymentById/** #断言 路径相匹配的进行路由
            - Path=/admin/** #访问包含admin的config目前被Nacos替代所有路径


        - id: payment-routh2 #路由的ID 没有固定规则但要求唯一 建议配合服务名
          #uri: http://localhost:8001 #匹配后提供的路由地址
          uri: lb://cloud-payment-service #匹配之后提供服务的路由地址
          predicates:
            - Path=/admin/findPaymentList/** #断言 路径相匹配的进行路由
 

 
Predicate的使用开始
 
predicates: 断言其实也就是验证地址是否通过,比如  - Path=/admin/**地址中没有带有admin的就不会让它通过
   #- Path=/admin/findPaymentById/** #断言 路径相匹配的进行路由
   - Path=/admin/** #访问包含admin的所有路径
   Path:只是其中一个属性
 
 

 
Gateway的Filter
 是什么?
   路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用
   

简介

网关经常需要对路由请求进行过滤,进行一些操作,如鉴权之后构造头部之类的,过滤的种类很多,如增加请求头、增加请求 参数 、增加响应头和断路器等等功能,这就用到了Spring Cloud Gateway 的 Filter。

作用

当我们有很多个服务时,比如下图中的user-service、goods-service、sales-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如鉴权、限流、日志输出等。
对于这样重复的工作,可以在微服务的上一层加一个全局的权限控制、限流、日志输出的Api Gateway服务,然后再将请求转发到具体的业务服务层。这个Api Gateway服务就是起到一个服务边界的作用,外界的请求访问系统,必须先通过网关层。

生命周期

Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:“pre” 和 “post”。
  • PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

分类

Spring Cloud Gateway 的 Filter 从作用范围可分为另外两种GatewayFilter 与 GlobalFilter。
  • GatewayFilter:应用到单个路由或者一个分组的路由上。
  • GlobalFilter:应用到所有的路由上。

Gateway filter

过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。过滤器的作用域为特定路由。Spring Cloud Gateway包含许多内置的GatewayFilter工厂。

第一步:cloud-gateway-gateway9527工程中,写一个MyGatewayFilter类,只需要实现两个接口implements GlobalFilter,Ordered
 
@Component
@Slf4j
public class MyGatewayFilter implements GlobalFilter,Ordered {


/**
* 如果带有id的这个参数并且参数值大于0则通过,否则不通过
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("gateway拦截器执行开始");
String id=exchange.getRequest().getQueryParams().getFirst("id");
if(Integer.parseInt(id)<0){
log.info("输入的参数非法,请重新输入");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}

@Override
public int getOrder() {
return 0;
}
}
 
第二步:启动eureka,8001,9527工程测试
 
 带参数小于0时
带参数大于0时
posted @ 2020-09-16 22:42  hexu_blog  阅读(364)  评论(0编辑  收藏  举报