Spring Cloud Gateway is an intelligent and programmable router based on Project Reactor.html
在云架构中运行着众多客户端和服务端,API网关的存在提供了保护和路由消息,隐藏服务,限制负载等等功能。git
Spring Cloud Gateway
提供了一个在Spring生态系统之上构建的API网关,包括:Spring 5,Spring Boot 2和Project Reactor。 Spring Cloud Gateway旨在提供一种简单而有效的方法来对API进行路由,提供精准控制。web
为了提高网关的性能,Spring Cloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通讯框架Netty。正则表达式
SpringCloud Gateway的目标是:提供统一的路由方式且基于FilterChain的方式提供网关基本的功能,例如:安全,监控/指标,弹性,限流等等。spring
路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言Predicates和过滤器Filters组成,若是断言为true,则匹配该路由。shell
断言:参考Java8的java.util.function.Predicate,开发人员能够匹配HTTP请求中的全部内容,例如请求头或请求参数,若是请求与断言相匹配则进行路由。安全
过滤:Spring框架中GatewayFilter的实例,使用过滤器,能够载请求被路由前或者后对请求进行修改。cookie
一个web请求,经过一些匹配条件,定位到真正的服务节点,在这个转发的过程当中,进行一些精细化的控制。架构
- predicate就是匹配条件
- filter就是拦截器
- predicate + filter + 目标uri实现路由route
下图整体上描述了Spring Cloud Gateway的工做流程:
客户端向Spring Cloud Gateway发出请求。
若是Gateway Handler Mapping肯定请求与路由匹配,则将其发送到Gateway Web Handler。
Handler经过指定的过滤器链将请求发送到咱们实际的服务执行业务逻辑,而后返回。
过滤器由虚线分隔的缘由是,过滤器能够在发送代理请求以前或以后执行逻辑。
核心:路由转发+过滤器链
引入spring-cloud-starter-gateway
核心组件,其次,这个服务自己也许要注册进Eureka,所以引入spring-cloud-starter-netflix-eureka-client
。
<!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
注意:不能引入spring-boot-starter-web依赖
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态建立路由的功能,利用微服务名进行路由 routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/** # 断言,路径相匹配的进行路由 - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai] #- Cookie=username,zzyy #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性而且值为整数的正则表达式 eureka: instance: hostname: cloud-gateway-service instance-id: gateway9527 prefer-ip-address: true client: #服务提供者provider注册进eureka服务列表内 service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
这段yml配置内容比较多:
@SpringBootApplication @EnableEurekaClient public class GatewayMain9527 { public static void main(String[] args) { SpringApplication.run(GatewayMain9527.class, args); } }
依次启动7001注册中心,8001服务和9527网关服务,访问localhost:7001/
因为网关的存在,咱们能够访问:http://localhost:9527/payment/1
,可以成功访问到8001服务的接口。
咱们以前已经配置过了:
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态建立路由的功能,利用微服务名进行路由 routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/** # 断言,路径相匹配的进行路由
@Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_route", r -> r.path("/guonei") .uri("http://news.baidu.com/guonei")).build(); return routes.build(); } }
原理:默认状况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径建立动态动态路由进行转发,从而实现动态路由的功能。
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态建立路由的功能,利用微服务名进行路由 routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/** # 断言,路径相匹配的进行路由 - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai] #- Cookie=username,zzyy #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性而且值为整数的正则表达式
访问localhost:9527/payment/lb
,根据获取到的服务的路由地址,动态切换路由。
Spring Cloud Gateway matches routes as part of the Spring WebFlux
HandlerMapping
infrastructure. Spring Cloud Gateway includes many built-in route predicate factories. All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with logicaland
statements.
SpringCloud Gateway将路由匹配做为Spring WebFlux HandlerMapping基础架构的一部分。
Spring Cloud Gateway包括许多内置的Route Predicate工厂,全部这些Predicate都与HTTP请求的不一样属性匹配,多个RoutePredicate工厂能够进行组合。
SpringCloud Gateway建立Route对象时,使用RoutePredicateFactory建立Predicate对象,Predicate对象能够赋值给Route。
你能够经过and逻辑组合多种route predicate factories。举几个例子:
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态建立路由的功能,利用微服务名进行路由 routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 #uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/** # 断言,路径相匹配的进行路由 - Before=2020-11-26T21:27:26.256+08:00[Asia/Shanghai] - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求惟一,建议配合服务名 #uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - After=2020-11-25T22:42:23.608+08:00[Asia/Shanghai] - Cookie=username,hyh
cookie能够经过curl命令测试:
$ curl http://localhost:9527/payment/lb --cookie "username=hyh"
header测试:
$ http://localhost:9527/payment/lb --H "X-Request-Id:123"
predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver] # 在..以前能够匹配 - After=2017-01-20T17:42:47.789-07:00[America/Denver] # 在..以后能够匹配 - Between=xxx,xxx # 在..之间能够匹配 - Cookie=chocolate, ch.p # 带cookie - Header=X-Request-Id, \d+ # 规定header - Host=**.somehost.org,**.anotherhost.org # 规定host - Method=GET,POST # 规定请求方法 - Path=/red/{segment},/blue/{segment} # 规定请求路径 - Query=green # 规定请求参数 - RemoteAddr=192.168.1.1/24 # 规定remoteAddr # 将80%的流量转到weighthigh.org,20%转到weightlow.org - id: weight_high uri: https://weighthigh.org predicates: - Weight=group1, 8 - id: weight_low uri: https://weightlow.org predicates: - Weight=group1, 2
Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner. Route filters are scoped to a particular route. Spring Cloud Gateway includes many built-in GatewayFilter Factories.
路由过滤器容许以某种方式修改传入的HTTP请求或传出的HTTP响应。
路由过滤器适用于特定路由。
Spring Cloud Gateway包括许多内置的GatewayFilter工厂,感兴趣能够查看官网。
@Slf4j @Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("================come in myGlobalFilter" + new Date() + "=================="); String name = exchange.getRequest().getQueryParams().getFirst("name"); if (name == null || name.length() == 0) { log.info("=======================非法用户,name为null=============================="); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } log.info("=======welcome! name = " + name + "======================="); return chain.filter(exchange); } @Override public int getOrder() { return -1; } }
本系列文章为《尚硅谷SpringCloud教程》的学习笔记【版本稍微有些不一样,后续遇到bug再作相关说明】,主要作一个长期的记录,为之后学习的同窗提供示例,代码同步更新到Gitee:https://gitee.com/tqbx/spring-cloud-learning,而且以标签的形式详细区分每一个步骤,这个系列文章也会同步更新。