你好,我是程序员Alan,很高兴遇见你。
我们在《系统架构设计—高并发场景微服务实战(三)》,将订票服务拆分成了很多子服务,其中很多子服务都需要用户验证、权限验证、流量控制等,那么我们要在每个子服务中重复编写相关的逻辑吗?
单体架构——客户端直接调用
它的特点是所有的服务都来自一个应用,客户端直接向服务端发送请求。

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

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

引入依赖
因为我们已经在父工程管理了SpingCloud版本,所以在子服务中不需要写版本号
-
org.springframework.cloud -
spring-cloud-starter-gateway
配置路由
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/**
代码解释:
此时一个简单的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包
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
- 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
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