赞
踩
Spring Cloud Gateway
是 Spring 官网基于 Spring 5.0
、 Spring Boot 2.0
、Project Reactor
等技术开发的网关服务。
Spring Cloud Gateway
基于Filter链提供网关基本功能:安全、监控/埋点、限流等。
Spring Cloud Gateway
为微服务架构提供简单、有效且统一的API路由管理方式。
Spring Cloud Gateway
是替代 Netflix Zuul 的一套解决方案。
路由(route): 路由信息由 一个ID
、一个目的URL
、一组断言工厂
、一组Filter
组成。如果路由断言为 真,说明请求URL和配置路由匹配,就可以通过路由去匹配对应的服务,否则不允通过。
断言(Predicate):断言函数输入类型是 Spring 5.0框架 中的 ServerWebExchange
,允许开发者去定义匹配来自于HTTP Request中的任何信息比如请求头和参数。
过滤器(Filter): Spring Cloud Gateway中的 Filter 分为两种类型,分别是Gateway Filter和Global Filter,过滤器将会对匹配到的 请求 和 响应 进行修改处理 。
网关的核心功能是:过滤器链 和 路由转发 。
Spring Cloud Gateway
组件的 核心 是一系列的 过滤器,通过过滤器链可以将客户端发送的请求转发(路由)到对应的微服务。 网关是加在整个微服务最前沿的防火墙和代理器,隐藏微服务 结点 IP 端口信息, 从而加强对服务端口的安全保护。
网关本身也是一个微服务,也需要将其注册到服务注册中心。
不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都可经过网关,然后再由网关来实现 鉴权、动态路由 等等操作。
网关就是整个服务的统一入口,来自各个地方请求通过网关之后在进行下一步的调度转发。
在配置好 服务中心,具体服务提供 之后,重新添加一个项目模块,项目名自定义。
网关只需要在服务中心进行注册,然后通过网关服务调取其他的服务接口,完成请求的转发即可。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>bill-manager-springCloud</artifactId> <groupId>com.beordie</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>gateway</artifactId> <dependencies> <!--网关依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--中心服务--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project>
通过 springboot 注解启动,添加服务中心的扫描注解。
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
主要配置相应的 服务中心地址 、路由规则 ,以及涉及 跨域资源请求 的配置。
# 配置端口信息 server: port: 8086 tomcat: uri-encoding: UTF-8 spring: application: name: gateway cloud: gateway: routes: - id: bill-service-route # 代理的服务地址 uri: lb://bill-service # 路由断言,可以配置映射路径 predicates: - Path=/api/** filters: # 添加请求路径的前缀 - StripPrefix=1 globalcors: corsConfigurations: '[/**]': allowedOrigins: "*" allowedMethods: - GET eureka: client: service-url: defaultZone: HTTP://127.0.0.1:10086/eureka instance: prefer-ip-address: true
- id: bill-service-route
表示当前设置路由的标识,可以随便进行定义。
uri: HTTP://127.0.0.1:9091
uri: lb://bill-service
将符合 Path
规则的一切请求,都代理到 uri
参数指定的地址,也就是代理到 http://127.0.0.1:9091 的服务。
在刚才的路由规则中,把路径对应的服务地址写死了!如果同一服务有多个实例的话,这样做显然不合理。
使用 lb://bill-service
这样的形式,通过 lb:
加上服务的名字,也就是在对应服务配置文件中指定的 application-name
,也可以从服务中心注册的服务名找。
uri: lb://bill-service
为例),gateway 将使用 LoadBalancerClient 把 bill-service 通过 eureka 解析为实际的主机和端口,并进行 ribbon 负载均衡。- Path=/api/**
定义请求当前路由的 url格式
,也就是说 HTTP://127.0.0.1:8086/api/
下面的所有请求都会朱发到当前路由进行处理。
功能和名字意义相同,就是配置路由的过滤器的一些功能。
- PrefixPath=/bill
- StripPrefix=1
在 js 请求访问中,如果访问的地址与当前服务器的 域名
、 ip
或者 端口号
不一致则称为跨域请求。若不解决则不能获取到对应地址的返回结果(能够请求,但是结果会被浏览器所拦截)。
一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。
表示对所有访问到网关服务器的请求地址都进行跨域设置。
globalcors:
corsConfigurations:
'[/**]':
指定允许访问的服务器地址,如:http://localhost:10000 也是可以的, 如果使用 * 就表示所有的访问都可以。
allowedOrigins: "*"
指定可以访问的请求方式,可以指定多种。
allowedMethods:
- GET
- POST
- HEAD
Gateway 作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现的。前面的 路由功能 也是使用过滤器实现的。
Gateway自带过滤器有几十个,常见自带过滤器有:
过滤器名称 | 功能 |
---|---|
AddRequestHeader | 对匹配上的请求加上Header |
AddRequestParameters | 对匹配上的请求路由添加参数 |
AddResponseHeader | 对从网关返回的响应添加Header |
StripPrefix | 对匹配上的请求路径去除前缀 |
这些自带的过滤器的使用和路由配置时的方法一致,也可以将这些过滤器配置成不只是针对某个路由,而是可以对所有路由生效,也就是配置默认过滤器。
# 默认过滤器,对所有路由都生效
default-filters:
- AddResponseHeader=X-Response-Foo, Bar
- AddResponseHeader=name, beordie
和上面一样的配置完成之后,每次的请求响应都会携带两个请求头信息,对应的名称和参数和配置的一致,可以在浏览器中对 Response Header
进行查看。
GatewayFilterFactory
结尾。package com.beordie.filters; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.*; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; @Component public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> { static final String PARAM_NAME = "param"; public MyParamGatewayFilterFactory() { super(Config.class); } public List<String> shortcutFieldOrder() { return Arrays.asList(PARAM_NAME); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { //获取请求参数中param对应的参数名 的参数值 ServerHttpRequest request = exchange.getRequest(); if(request.getQueryParams().containsKey(config.param)){ request.getQueryParams().get(config.param). forEach(value -> System.out.printf("------------局部过滤器--------%s = %s------", config.param, value)); } return chain.filter(exchange); }; } public static class Config{ //对应在配置过滤器的时候指定的参数名 private String param; public String getParam() { return param; } public void setParam(String param) { this.param = param; } } }
然后就可以在配置文件对拦截器进行使用。
- MyParam=name
请求在通过时,过滤去就会试图去查找参数名叫做 name
的携带参数,并且进行控制台的打印操作。
全局过滤器不需要在配置文件中进行配置,直接定义将会配置在程序中
需要实现 GlobalFilter
, Ordered
两个接口。
package com.beordie.filters; import org.apache.commons.lang.StringUtils; import org.springframework.boot.web.servlet.filter.OrderedFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * @Description * @Date 2021/8/22 17:21 * @Created 30500 */ public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("--------------全局过滤器MyGlobalFilter------------------"); String token = exchange.getRequest().getHeaders().getFirst("token"); if(StringUtils.isBlank(token)){ //设置响应状态码为未授权 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { // 值越小,全局控制器的执行就越靠前 return 1; } }
Gateway中默认就已经集成了 Ribbon
负载均衡和 Hystrix
熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置.
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 #服务降级超时时间,默认1S
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务
启动多个 Gateway 服务,自动注册到Eureka,形成集群。如果是服务内部访问,访问Gateway,自动负载均衡,没问题。
但是,Gateway更多是外部访问,PC端、移动端等。它们无法通过Eureka进行负载均衡,那么该怎么办? 此时, 可以使用其它的服务网关,来对Gateway进行代理。比如:Nginx 。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。