网关是将所有面向用户的服务接口统一管理的代理服务器,所有内部服务的远程调用都是在局域网内部,而网关是在公网中。
一、依赖
通过访问网关调用项目中的服务,需要使用Eureka,网关服务器需要在Eureka服务注册它自己,本身也就是一个Eureka Client。
远程调用服务自然也离不开熔断降级的保护机制,使用Hystrix
网关是对所有访问的统一入口,面对恶意攻击,大量并发的情况,通常使用令牌桶机制来处理,令牌储存在redis中。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version></parent><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR12</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency></dependencies>
二、基本配置
gateway解析自己配置时,- 代表了创建一个对象:
id: 路由名称
uri: 调用的服务主机名
predicates:代理地址
代理本身只解析主机名ip端口号,和代理地址做拼接,需要手动将/abc去除。
Vue3中代理配置也一样:
Filter:
因为所有Filter都以GatewayFilterFactory结尾,所有该结尾省略不写。
- StripPrefix=1
//简写形式 name =StripPrefixGatewayFilterFactory,参数为1
- name: RequestRateLimiter //通用的写法
args:...
server:port: 9999 eureka:client:service-url:defaultZone: http://localhost:8761/eureka/ spring:redis:host: localhostapplication:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: falselower-case-service-id: trueroutes:- id: rateLimiteruri: lb://application-servicepredicates:- Path=/abc/**filters:- StripPrefix=1
三、令牌桶过滤器
实现KeyResolver接口的resolve()方法
@Component public class MyKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();return Mono.just(ip);} }
filters:- StripPrefix=1- name: RequestRateLimiterargs:keyResolver: '#{@myKeyResolver}' # 表达式, #{} 从容器找对象, @beanIdredis-rate-limiter.replenishRate: 1 # 每秒令牌生成速率redis-rate-limiter.burstCapacity: 2 # 令牌桶容量上限
四、熔断降级过滤器
配置HystrixGatewayFilterFactory对象,自定义降级的uri
filters:- StripPrefix=1- name: RequestRateLimiterargs:keyResolver: '#{@myKeyResolver}' # 表达式, #{} 从容器找对象, @beanIdredis-rate-limiter.replenishRate: 1 # 每秒令牌生成速率redis-rate-limiter.burstCapacity: 2 # 令牌桶容量上限- name: Hystrixargs:name: fallback # 随意定义的名称。相当于@HystrixCommand注解中的commandKey属性。fallbackUri: forward:/fallback # 如果转发
五、全局过滤器和自定义过滤器:
全局过滤器:
实现GlobalFilter的filter()方法
@Component public class MyGlobalFilter implements GlobalFilter {/*** 过滤方法。* 实现上,只有唯一的要求。必须调用方法chain.filter(exchange),并把方法的返回值,返回。* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("前置全局过滤");Mono<Void> result = chain.filter(exchange);System.out.println("后置全局过滤");return result;} }
自定义过滤器:
1.仿照其他Gateway提供的过滤器,创建一个LoggerFilterGatewayFilterFactory继承AbstractGatewayFilterFactory<LoggerFilterGatewayFilterFactory.Config>
@Component public class LoggerFilterGatewayFilterFactoryextends AbstractGatewayFilterFactory<LoggerFilterGatewayFilterFactory.Config> {/*** 建议提供2个构造方法。一个无参数。一个有参数,参数类型就是当前类型中的Config静态内部类的类对象类型。* 父类型,可以帮助解析配置文件,并创建Config对象。*/public LoggerFilterGatewayFilterFactory(){this(Config.class);}public LoggerFilterGatewayFilterFactory(Class<Config> configClass){super(configClass);}/*** 如果需要简化配置方案。提供方法shortcutFieldOrder* 有当前方法,配置文件使用,可以简化配置为 LoggerFilter=abc* 没有当前方法,配置文件完整编写,内容是:* name: LoggerFilter* args:* remark: abc*/@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("remark");}/*** 创建网关过滤器的方法。* @param config 就是配置文件中的内容,就是当前类型中的静态内部类对象。* @return 一般使用匿名内部类,创建GatewayFilter接口的实现对象。*/@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {/*** 过滤方法。要求必须调用chain.filter(exchange),并返回方法的返回结果* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("前置 - 日志过滤器 - config.remark = " + config.getRemark());Mono<Void> result = chain.filter(exchange);System.out.println("后置 - 日志过滤器 - config.remark = " + config.getRemark());return result;}};}/*** 定义静态内部类,作为配置对象* 定义的每个属性,都是用于在配置文件中配置的对应属性。* 必须提供getter和setter方法。*/public static class Config{private String remark;public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}} }
2.配置文件编写该自定义过滤器对象配置信息
filters:- StripPrefix=1- name: RequestRateLimiterargs:keyResolver: '#{@myKeyResolver}' # 表达式, #{} 从容器找对象, @beanIdredis-rate-limiter.replenishRate: 1 # 每秒令牌生成速率redis-rate-limiter.burstCapacity: 2 # 令牌桶容量上限- name: Hystrixargs:name: fallback # 随意定义的名称。相当于@HystrixCommand注解中的commandKey属性。fallbackUri: forward:/fallback # 如果转发- name: LoggerFilterargs:remark: fullyTestGatewayFilter