SpringCloud Gateway—高并发场景微服务实战(十三)

你好,我是程序员Alan,很高兴遇见你。

我们在《系统架构设计—高并发场景微服务实战(三)》,将订票服务拆分成了很多子服务,其中很多子服务都需要用户验证、权限验证、流量控制等,那么我们要在每个子服务中重复编写相关的逻辑吗?

为什么需要网关

单体架构——客户端直接调用

它的特点是所有的服务都来自一个应用,客户端直接向服务端发送请求。

微服务架构——客户端直接调用

微服务架构中,一个大的应用被拆分成一个个小的服务,客户端直接调用会直接带来很多问题,例如:

  • 鉴权、日志记录等公共操作,每个子服务都需要单独实现。
  • 服务直接对外暴露,安全风险增加
  • 后端服务变动前端也要相应变动

微服务架构——引入网关

在网关层针对公共操作做统一处理,避免了重复造轮子;并通过网关对外提供统一的入口供客户端访问,隐藏系统架构实现的细节;另外我们还可以对外的API使用HTTP协议,对内使用性能更高的通信协议。

 

建立SpringCloud Gateway服务

引入依赖

因为我们已经在父工程管理了SpingCloud版本,所以在子服务中不需要写版本号

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

配置路由

SpringCloud支持很多种路由方式,例如时间匹配,IP地址匹配,请求方式匹配,请求路径匹配等等。

今天我们使用请求路径匹配做一个简单例子。

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=gateway-env, springcloud-gateway
      routes:
        - id: air-shenzhen
          uri: http://127.0.0.1:18802  #若使用了注册中心可以使用服务名 lb://air-shenzhen
          predicates:
            - Path=/api/shenzhen/**
        - id: air-xiamen
          uri: http://127.0.0.1:18801
          predicates:
            - Path=/api/xiamen/**

代码解释:

  • default-filters: 在请求中加入一个自定义的header,注明这个请求经过了此网关。
  • routes: 路由配置,配置了两个路由,id是服务名,uri是路由转发的地址,predicates是匹配规则

此时一个简单的SpringCloud Gateway服务就已经可以启动了,它的功能是将url为/api/shenzhen/**的请求转发到http://127.0.0.1:18802/**,将url为/api/xiamen/**的请求转发到http://127.0.0.1:18801/**,前端直接访问网关调用对应服务,不必再关心子服务的服务名、服务端口等情况。

服务限流

Gateway 组件内部默认实现了 Redis + Lua 进行限流,可以通过自定义的方式来指定是根据 IP、用户或是 URI 来进行限流。

引入相关jar包

<!--基于 reactive stream 的 redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

配置基于 IP 进行限流。

 - name: RequestRateLimiter
          args: 
            redis-rate-limiter.replenishRate: 3 #允许用户每秒处理多少个请求
            redis-rate-limiter.burstCapacity: 5 #令牌桶的容量,允许在一秒钟内完成的最大请求数
            key-resolver: "#{@remoteAddrKeyResolver}" #SPEL 表达式去的对应的 bean

上文的 KeyResolver 配置项是用来定义按什么规则来限流,比如本次采用 IP 进行限流,编写对应的实现类实现此接口:

public class AddrKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

在启动类进行 @Bean 定义:

@Bean
public AddrKeyResolver addrKeyResolver() {
    return new AddrKeyResolver();
}

跨域支持

代码方式

@Configuration
public class CORSConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(Boolean.TRUE);
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addExposedHeader("setToken");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

配置文件配置

spring:
  cloud:
    gateway:
      discovery:
      # 跨域
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            # 为保证请求的安全,项目中只支持 get 或 post 请求,其它请求全部屏蔽,以免导致多余的问题
            allowedMethods:
            - POST

站在巨人的肩膀上:

  • 码闻强—《SpringCloud微服务实战》
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值