企业类网站设计,哪家公司网站制作好,安庆网站建设公司,网站开发就业方向什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址#xff0c;是当前微服务项目的统一入口。
网关能做什么#xff1f; 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文#xff1a;http://t.csdnimg.cn/SvUJh
核心概念
Router#xff08;…什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址是当前微服务项目的统一入口。
网关能做什么 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文http://t.csdnimg.cn/SvUJh
核心概念
Router路由路由时构建网关的基本模块它由ID目标URI一系列的断言和过滤器组成如果断言为true则匹配该路由。
Predicate断言断言说简单点就是请求匹配条件。断言是定义匹配条件如果请求符合条件则该请求匹配断言所属的路由。 Filter 过滤 指的是 Spring 框架中 GatewayFilter 的实例使用过滤器可以在请求被路由前或者之后对请求进行修改。 Spring Cloud Gateway 网关的搭建 创建 springboot 项目引入 jar !--网关jar--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactIdversion${spring-cloud-alibaba-version}/version/dependency!--引入nacos--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactIdversion${spring-cloud-alibaba-version}/version/dependency!--注意我这里没有引入父工程而是springboot父启动依赖也不要引入web依赖而是webflux--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependencySpring Cloud GateWay是基于 webflux 的如果非要 web 支持的话需要导入spring-boot-starter-webflux而不是spring-boot-start-web 应用启动类添加注解 EnableDiscoveryClient 编写application.yml server:port: 8070
spring:application:name: alibaba-gateway
cloud:nacos:discovery:server-addr: 127.0.0.1:3333 #注册服务到nacos注意nacos的端口号配置gateway:discovery:locator:enabled: true #表明gateway开启服务注册和发现的功能gateway为每一个服务创建了一个router这个router将以服务名开头的请求路径转发到对应的服务。lower-case-service-id: true #请求路径的服务g名改为小写 启动项目输入路径 ipGateWay 端口号 要请求的服务名 地址 如 http://127.0.0.1:8070/alibaba-user-consumer-8090/user/findUserById?id3 自定义路由 修改yml文件信息 server:port: 8070
spring:application:name: alibaba-gateway
cloud:nacos:discovery:server-addr: 127.0.0.1:3333 #注册服务到nacos注意nacos的端口号配置gateway:discovery:locator:enabled: false #表明gateway开启服务注册和发现的功能gateway为每一个服务创建了一个router这个router将以服务名开头的请求路径转发到对应的服务。lower-case-service-id: true #请求路径的服务g名改为小写routes: l- id: user-consumer #唯一 路由iduri: http://127.0.0.1:7780 #使用http:IP服务端口 或lb://alibaba-user-consumer-8090 也可以lb为负载均衡predicates: # 断言- Path/ts/** # 路径需携带tsfilters:- StripPrefix1 #路由去掉前缀信息 使用内置过滤器 路由的主要四个配置 路由idid路由目标uri 路由断言predicates判断路由的规则 路由过滤器filters对请求或响应做处理 再次启动项目 输入路径ipGateWay 端口号ts 路径 如 http://127.0.0.1:8070/ts/user/findUserById?id3 路由过滤器 客户端请求先找到路由路由匹配时经过过滤器层层筛选最终访问到微服务。 请求头过滤器配置示例局部过滤器
在yml中配置相关信息 给所有进入 user-consumer 的请求添加一个请求头。 请求头的 key 为 token value 为 test。 默认过滤器配置示例全局过滤器 default - filters 的配置和 routes 平级。 只要配置在 default - filters 下面的过滤器会对 routes 配置的所有路由都生效。 自定义全局路由过滤器 有时候SpringCloudGateWay提供的过滤器工厂不能满足自己的要求。 可能有时候需要在过滤时做一些其它的逻辑操作。 那么这时候可以选择使用Java代码自定义全局过滤器。 yml配置如图 创建 GateWayFilter 类 实现接口 GlobalFilter 与 Ordered import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** Author * Date 2023/12/25 11:11* Description:*/
//Component
//Order(1)
public class GateWayFilter implements GlobalFilter {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {String tokenexchange.getRequest().getHeaders().getFirst(token);System.out.println(token1token);if (123.equals(token)){return chain.filter(exchange);}System.out.println(错误不放行);exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);return exchange.getResponse().setComplete();}
}这里请求头携带的token为123时才允许放行。 当有多个过滤器时Order的值决定了过滤器的执行顺序。 数值越大优先级越低 负的越多 优先级越高。 设置 Order 的值有两种方式 1. 实现 Ordered 接口并且重写 getOrder 方法 2. 使用Order注解 如GateWayFilter1 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** Author * Date 2023/12/25 11:31* Description:*/
//Component
public class GateWayFilter1 implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {return null;}Overridepublic int getOrder() {return 2;}
} 网关的跨域问题 使用 CORS 方式。 CORS是一个 W3C 标准全称是 跨域资源共享 Cross-origin resource sharing 。 它允许浏览器向跨源服务器发出XMLHttpRequest 请求从而克服了 AJAX 只能同源使用的限制。 方式一配置 application.yml 文件 spring:cloud:gateway:globalcors: # 全局的跨域配置add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题# options请求 就是一种询问服务器是否浏览器可以跨域的请求# 如果每次跨域都有询问服务器是否浏览器可以跨域对性能也是损耗# 可以配置本次跨域检测的有效期maxAge# 在maxAge设置的时间范围内不去询问统统允许跨域corsConfigurations:[/**]:allowedOrigins: # 允许哪些网站的跨域请求- http://localhost:8090allowedMethods: # 允许的跨域ajax的请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求中携带的头信息allowCredentials: true # 允许在请求中携带cookiemaxAge: 360000 # 本次跨域检测的有效期(单位毫秒)# 有效期内跨域请求不会一直发option请求去增大服务器压力 方式二使用编码方式定义配置类 Configuration
public class CorsConfig {private static final String MAX_AGE 18000L;Beanpublic WebFilter corsFilter() {return (ServerWebExchange ctx, WebFilterChain chain) - {ServerHttpRequest request ctx.getRequest();// 使用SpringMvc自带的跨域检测工具类判断当前请求是否跨域if (!CorsUtils.isCorsRequest(request)) {return chain.filter(ctx);}HttpHeaders requestHeaders request.getHeaders();// 获取请求头ServerHttpResponse response ctx.getResponse();// 获取响应对象HttpMethod requestMethod requestHeaders.getAccessControlRequestMethod(); // 获取请求方式对象HttpHeaders headers response.getHeaders();// 获取响应头headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,requestHeaders.getOrigin()); // 把请求头中的请求源协议ip端口添加到响应头中相当于yml中的allowedOrigins)headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,requestHeaders.getAccessControlRequestHeaders());if (requestMethod ! null) {headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,requestMethod.name()); // 允许被响应的方法GET/POST等相当于yml中的allowedMethods)}headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, true);// 允许在请求中携带cookie相当于yml中的allowCredentialsheaders.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, *);// 允许在请求中携带的头信息相当于yml中的allowedHeadersheaders.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);// 本次跨域检测的有效期(单位毫秒相当于yml中的maxAge)if (request.getMethod() HttpMethod.OPTIONS) {// 直接给option请求反回结果response.setStatusCode(HttpStatus.OK);return Mono.empty();}return chain.filter(ctx);// 不是option请求则放行};}
} 网关限流 网关可以做很多的事情比如限流当我们的系统被频繁的请求的时候就有可能将系统压垮所以为了解决这个问题需要在每一个微服务中做限流操作但是如果有了网关那么就可以在网关系统做限流因为所有的请求都需要先通过网关系统才能路由到微服务中。 令牌桶算法是比较常见的限流算法之一大概描述如下 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理 根据限流大小设置按照一定的速率往桶里添加令牌 桶设置最大的放置令牌限制当桶满时、新添加的令牌就被丢弃或者拒绝 请求达到后首先要获取令牌桶中的令牌拿着令牌才可以进行其他的业务逻辑处理完业务逻辑之后将令牌直接删除 令牌桶有最低限额当桶中的令牌达到最低限额的时候请求处理完之后将不会删除令牌以此保证足够的限流 网关限流代码实现 需求每个 ip 地址 1 秒内只能发送 1 次请求多出来的请求返回 429 错误。 spring cloud gateway 默认使用 redis 的 RateLimter 限流算法来实现。所以我们要使用首先需要引 入 redis 的依赖 jar包引入 !--redis 限流--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactIdversion2.1.3.RELEASE/version/dependency 定义 KeyResolver Configuration
public class KeyResolverConfiguration {Beanpublic KeyResolver ipKeyResolver(){return new KeyResolver() {Overridepublic MonoString resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}};}
} 修改yml中的配置项指定限制流量的配置以及redis的配置 routes:- id: cloud-user-consumeruri: http://127.0.0.1:7780predicates: # 断言- Path/ts/** # 路径需携带tsfilters:- StripPrefix1 #路由去掉前缀信息 使用内置过滤器- AddRequestHeadertoken,123 #添加请求头- name: RequestRateLimiter #请求数限流 名字不能随便写args:key-resolver: #{ipKeyResolver} #用于限流的键的解析器的 Bean 对象的名字。它使用SpEL 表达式根据#{beanName}从 Spring 容器中获取 Bean 对象redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率redis-rate-limiter.burstCapacity: 1 #令牌桶总容量。 burstCapacity 令牌桶总容量。 replenishRate 令牌桶每秒填充平均速率。 key - resolver 用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据 #{beanName} 从 Spring 容器中获取 Bean 对象。