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


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

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

    为什么需要网关

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

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

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

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

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

    微服务架构——引入网关

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

     

    建立SpringCloud Gateway服务

    引入依赖

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

    1. org.springframework.cloud
    2. spring-cloud-starter-gateway

    配置路由

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

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

    1. spring:
    2. cloud:
    3. gateway:
    4. default-filters:
    5. - AddRequestHeader=gateway-env, springcloud-gateway
    6. routes:
    7. - id: air-shenzhen
    8. uri: http://127.0.0.1:18802 #若使用了注册中心可以使用服务名 lb://air-shenzhen
    9. predicates:
    10. - Path=/api/shenzhen/**
    11. - id: air-xiamen
    12. uri: http://127.0.0.1:18801
    13. predicates:
    14. - 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包

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
    4. dependency>

    配置基于 IP 进行限流。

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

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

    1. public class AddrKeyResolver implements KeyResolver {
    2. @Override
    3. public Mono resolve(ServerWebExchange exchange) {
    4. return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    5. }
    6. }

    在启动类进行 @Bean 定义:

    1. @Bean
    2. public AddrKeyResolver addrKeyResolver() {
    3. return new AddrKeyResolver();
    4. }

    跨域支持

    代码方式

    1. @Configuration
    2. public class CORSConfiguration {
    3. @Bean
    4. public CorsWebFilter corsWebFilter() {
    5. CorsConfiguration config = new CorsConfiguration();
    6. config.setAllowCredentials(Boolean.TRUE);
    7. config.addAllowedMethod("*");
    8. config.addAllowedOrigin("*");
    9. config.addAllowedHeader("*");
    10. config.addExposedHeader("setToken");
    11. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
    12. source.registerCorsConfiguration("/**", config);
    13. return new CorsWebFilter(source);
    14. }
    15. }

    配置文件配置

    1. spring:
    2. cloud:
    3. gateway:
    4. discovery:
    5. # 跨域
    6. globalcors:
    7. corsConfigurations:
    8. '[/**]':
    9. allowedHeaders: "*"
    10. allowedOrigins: "*"
    11. # 为保证请求的安全,项目中只支持 get 或 post 请求,其它请求全部屏蔽,以免导致多余的问题
    12. allowedMethods:
    13. - POST

    站在巨人的肩膀上:

    • 码闻强—《SpringCloud微服务实战》
  • 相关阅读:
    「随笔」浅谈2023年云计算的发展趋势
    Linux基础操作命令详解
    晶体管的 栅极gate 材料选用 多晶硅polysilicon,并采用 自对准工艺 self-aligned IC后端版图 【VLSI】
    NFT遇冷,盘点6 大项目
    mysql“数据不存在插入,存在则更新”实现
    Redis(一)入门:五大数据类型的学习和理解①
    页面关闭前,如何发送一个可靠请求
    浅述蓝牙Mesh的配网流程
    Symmetric Encoding(Round 946)
    EI会议列表-IEEE主办-计算机方向国际学术会议推荐
  • 原文地址:https://blog.csdn.net/weixin_45645846/article/details/127586195