Api网关(Spring cloud Gateway)

1. Spring cloud Gateway网关
  • 什么是网关?

网关就是网络请求的统一入口。gateway是spring cloud的第二代网关,未来会取代zuul,其性能是zuul的1.6倍左右,其内部是基于netty、reactor、webflux进行构建的。gateway需要从注册中心获取服务,然后通过网关来调用对应的服务。注意gate不在web环境下运行,也就是说不能打成war包放在tomcat下运行。

  • 为什么需要网关?

从服务器与后端两个维度来谈一下为什么需要网关:1.如果我们有成千上万个服务,我们在请求每个服务的时候都需要认证,难度可想而知;2.如果没有统一的入口,那么前端与服务端交互的时候定位到各个服务,假设服务端进行服务的重构(比如改变访问接口),那么前端也得跟着一起修改。

2. 应用环境

注意查看官网(https://spring.io/projects/spring-cloud-alibaba)最新适配环境

Spring Cloud VersionSpring Cloud AlibabaVersion Spring Boot Version
Spring Cloud Greenwich2.1.x.RELEASE2.1.x.RELEASE
Spring Cloud Finchley2.0.x.RELEASE2.0.x.RELEASE
Spring Cloud Edgware1.5.x.RELEASE1.5.x.RELEASE
    如上官方给出的最新适配版本为:
    Spring Boot:2.1.0
    Spring Cloud:Greenwich.SR2
    Spring Cloud Alibab:2.1.0.RELEASE
    注意:如果使用最新而没有适配的版本,可能会出现以下问题:无法通过API网关访问服务,Sentinel限流中链路失败
3. 上手使用
1. 添加依赖
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
		<exclusions>
            <!-- 排除掉springmvc相关的配置信息 -->
			<exclusion>
				<groupId>org.springframework</groupId>
				<artifactId>spring-webmvc</artifactId>
			</exclusion>
            <!-- 排除掉tomcat相关的配置 -->
			<exclusion>
				<groupId>org.springframework.bootk</groupId>
				<artifactId>spring-boot-starter-tomcat</artifactId>
			</exclusion>
			<exclusion>
				<groupId>org.apache.tomcat.embed</groupId>
				<artifactId>tomcat-embed-core</artifactId>
			</exclusion>
			<exclusion>
				<groupId>org.apache.tomcat.embed</groupId>
				<artifactId>tomcat-embed-el</artifactId>
			</exclusion>
			<exclusion>
				<groupId>org.apache.tomcat.embed</groupId>
				<artifactId>tomcat-embed-websocket</artifactId>
			</exclusion>
			</exclusions>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
	</dependency>
    <!-- 网关相关配置 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-gateway</artifactId>
	</dependency>
</dependencies>
2. yml文件配置
server:
  port: 9090

spring:
  application:
    # 服务名
    name: alibaba-gateway
  cloud:
    nacos:
      discovery:
        register-enabled: true
        server-addr: 172.18.96.177:8848
    gateway:
      discovery:
        locator:
          # 可以使用服务名的方式访问,例如
          #   http://localhost:9090/alibaba-provider/user
          enabled: true
3. 术语
  • Route路由:gateway的基本构建模块。它由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。
  • Predicate断言:谓词(predicate)是gateway内置的的一下关于请求相关的处理
  • Filter过滤器:GateWay提供了很多内置的过滤器让我们使用,具体的过滤器在spring-cloud-gateway-core-2.1.2.RELEASE.jar下的org.springframework.cloud.gateway.filter.factory包下。也可以自定义过滤器在返回请求之前或之后修改请求和响应的内容。
spring:
  application:
    # 服务名
    name: alibaba-gateway
  cloud:
    gateway:
      discovery:
        locator:
          # 可以使用服务名的方式访问,例如
          #   http://localhost:9090/alibaba-consumer/all/user?origin=abc
          #   http://localhost:9090/alibaba-provider/user
          # true表示开始,false表示关闭
          enabled: false
      routes:
        - id: alibaba-consumer
          #如果要定位到微服务中的某个服务,要使用 lb:// 开头
          uri: lb://alibaba-consumer
          predicates:
            # 路径匹配
            - Path=/all/user,/student/**
            # 表示请求的参数中必须包含origin而且参数的值必须是  数字字母或_组成的字符串
            - Query=origin,\w+
            # 请求方式必须为get请求
            - Method=get
            - After=2019-11-12T00:00:00+08:00[Asia/Shanghai]
            - Before=2019-12-31T00:00:00+08:00[Asia/Shanghai]
            # 请求头中必须包含token
            #- Header=token,\w+
            # 描述从172.18.96.1~172.18.96.255的ip地址才可以访问
            - RemoteAddr=172.18.96.0/24
          filters:
            # (?) 表示将这一组数据抽取出来,<abc>将抽取的数据赋值给abc
            # /ac/users/23   abc=/users/23 ${abc}
            # http://localhost:9091/ac/users
            - RewritePath=/ac(?<abc>/?.*),$\{abc}
            - Customize=abc,XYZ
          filters:
            - name: RequestRateLimiter
              args:
             # key-resolver是用于限流的bean对象,通过SpEL的方式 #{@XXX} 取出spring容器中的bean
                keyResolver: '#{@hostAddrKeyResolver}'
                # 每秒往令牌桶中存放的数量
                redis-rate-limiter.replenishRate: 1
                # 令牌桶初始容量
                redis-rate-limiter.burstCapacity: 3
  redis:
    host: localhost
    port: 6379
    password: admin

id: 可以配置很多的路由信息,但是每个路由都有一个唯一的id来标识。

uri: 转发的地址,lb://开头标识转发到微服务的内部的某个服务。

predicates: 配置谓词。

Path: 配置请求的路径

Query: 请求的参数

Method: 请求的方式,大小写不敏感

After: 在指定的时间之后

Before: 在指定的时间之前

Header: 请求头中要包含的信息

RemoteAddr: 请求的IP的来源

4. 过滤器
  1. 内置过滤器RewritePathGatewayFilterFactory

在Nginx服务启中有一个非常强大的功能就是重写路径,Spring Cloud Gateway默认也提供了这样的功能,这个功能是Zuul没有的。

    gateway:
      routes:
      - id: rewritepath_route
        uri: https://blog.csdn.net
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}
    /**上面的配置表示所有的/foo/**开始的路径都会到转发
    *到https://blog.csdn.net/forezp的页面
    */
  1. 自定义局部过滤器
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * spring5.X 版本之后加入 webflux模块, 该模块主要用于反应式编程。
 *    如果要返回单个值(例如User), return Mono;
 *    如果要返回列表:return Flux;
 */
@Component
public class CustomizeGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    /**
     * Customize=abc,XYZ
     */
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        // 针对如上的配置,config.getName() 为abc, config.getValue()为XYZ
//        System.out.println(config.getName() + ":::" + config.getValue());

        GatewayFilter gatewayFilter = new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                String username = request.getQueryParams().get("username").get(0);
                System.out.println(username);

                //该代码的意思是向请求头中添加信息  auth abcdef
                request.mutate().header("auth", "abcdef");

                // mutate是修改的意思, 将修改之后的request加入新的请求中
                ServerWebExchange serverWebExchange = exchange.mutate().request(request).build();

                return chain.filter(serverWebExchange);
            }
        };

        return gatewayFilter;
    }
}

配置:

      routes:
        - id: alibaba-consumer
          uri: lb://alibaba-consumer
          predicates:
            - Path=/ac/users
          filters:
            # (?) 表示将这一组数据抽取出来,<abc>将抽取的数据赋值给abc
            # /ac/users/23   abc=/users/23 ${abc}
            # http://localhost:9091/ac/users
            - RewritePath=/ac/(?<abc>/?.*),$\{abc}
            - Customize=abc,XYZ
  1. 自定义全局过滤器
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 因为在网关内部过滤器的顺序都是整数,我们自己在定义过滤器的时候,采用负数,数字越小越先执行
 */
@Configuration
public class GatewayConfig {

    @Bean
    @Order(-1)
    public GlobalFilter globalFilter() {
        return new GlobalFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("全局过滤器1");
                return chain.filter(exchange);
            }
        };
    }

    @Bean
    @Order(-2)
    public GlobalFilter secondGlobalFilter() {
        return new GlobalFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("全局过滤器2");
                return chain.filter(exchange);
            }
        };
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值