做网站开发有哪些优点呢,免费的黄冈网站有哪些平台,山东省技术标准创新中心,固镇县住房和城乡建设局网站目录
一、概述
1#xff09;为什么需要网关
2#xff09;SpringCloud Gateway
二、gateway快速入门
搭建网关服务
1、创建新的module#xff0c;引入SpringCloudGateway的依赖和nacos的服务发现依赖#xff1a;
2、编写路由配置和nacos地址
三、断言工厂
路由… 目录
一、概述
1为什么需要网关
2SpringCloud Gateway
二、gateway快速入门
搭建网关服务
1、创建新的module引入SpringCloudGateway的依赖和nacos的服务发现依赖
2、编写路由配置和nacos地址
三、断言工厂
路由断言工厂Route Predicate Factory
四、过滤器工厂
路由过滤器 GatewayFilter
五、全局过滤器
全局过滤器 GlobalFilter
过滤器执行顺序
网关自定义过滤器
六、跨域问题
七、限流过滤器
1限流过滤器-计数器算法
2限流过滤器-漏桶算法
3限流过滤器-令牌桶算法 一、概述
1为什么需要网关 网关功能 身份认证和权限校验服务路由、负载均衡请求限流 2SpringCloud Gateway 在SpringCloud微服务体系中有个很重要的组件就是网关在1.x版本中都是采用的Zuul网关但在2.x版本中zuul的升级一直跳票SpringCloud最后自己研发了一个网关替代Zuul那就是SpringCloud Gateway 网上很多地方都说Zuul是阻塞的Gateway是非阻塞的这么说是不严谨的准确的讲Zuul1.x是阻塞的而在2.x的版本中Zuul也是基于Netty也是非阻塞的如果一定要说性能其实这个真没多大差距。 而官方出过一个测试项目创建了一个benchmark的测试项目 spring-cloud-gateway-bench其中对比了 Spring Cloud GatewayZuul1.xLinkerd Proxy Avg Latency Avg Req/Sec/Thread gateway 6.61ms 3.24k linkered 7.62ms 2.82k zuul 12.56ms 2.09k none 2.09ms 11.77k 还有一点就是Gateway是基于WebFlux的。这里引出了WebFlux名词那什么是WebFlux 左侧是传统的基于Servlet的Spring Web MVC框架 传统的Web框架比如说struts2springmvc等都是基于Servlet API与Servlet容器基础之上运行的在Servlet3.1之后才有了异步非阻塞的支持。 右侧是5.0版本新引入的基于Reactive Streams的Spring WebFlux框架从上到下依次是Router FunctionsWebFluxReactive Streams三个新组件。 Router Functions: 对标ControllerRequestMapping等标准的Spring MVC注解提供一套函数式风格的API用于创建RouterHandler和Filter。 WebFlux: 核心组件协调上下游各个组件提供响应式编程支持。 Reactive Streams: 一种支持背压Backpressure的异步数据流处理标准主流实现有RxJava和ReactorSpring WebFlux默认集成的是Reactor。 在Web容器的选择上Spring WebFlux既支持像TomcatJetty这样的的传统容器前提是支持Servlet 3.1 Non-Blocking IO API又支持像NettyUndertow那样的异步容器。不管是何种容器Spring WebFlux都会将其输入输出流适配成FluxDataBuffer格式以便进行统一处理。 值得一提的是除了新的Router Functions接口Spring WebFlux同时支持使用老的Spring MVC注解声明Reactive Controller。和传统的MVC Controller不同Reactive Controller操作的是非阻塞的ServerHttpRequest和ServerHttpResponse而不再是Spring MVC里的HttpServletRequest和HttpServletResponse。 根据官方的说法webflux主要在如下两方面体现出独有的优势 1、非阻塞式 其实在servlet3.1提供了非阻塞的APIWebFlux提供了一种比其更完美的解决方案。使用非阻塞的方式可以利用较小的线程或硬件资源来处理并发进而提高其可伸缩性 2、函数式编程端点 老生常谈的编程方式了Spring5必须让你使用java8那么函数式编程就是java8重要的特点之一而WebFlux支持函数式编程来定义路由端点处理请求。 二、gateway快速入门
搭建网关服务
搭建网关服务的步骤
1、创建新的module引入SpringCloudGateway的依赖和nacos的服务发现依赖
!--网关依赖--
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId
/dependency
!--nacos服务发现依赖--
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery
/artifactId /dependency2、编写路由配置和nacos地址
server:port: 10010 # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由id自定义只要唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址uri: lb://userservice # 路由的目标地址 lb就是负载均衡后面跟服务名称predicates: # 路由断言也就是判断请求是否符合路由规则的条件- Path/user/** # 这个是按照路径匹配只要以/user/开头就符合要求 三、断言工厂
路由断言工厂Route Predicate Factory 网关路由可以配置的内容包括 路由id路由唯一标示uri路由目的地支持lb和http两种predicates路由断言判断请求是否符合要求符合则转发到路由目的地filters路由过滤器处理请求或响应我们在配置文件中写的断言规则只是字符串这些字符串会被Predicate Factory读取并处理转变为路由判断的条件例如Path/user/**是按照路径匹配这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的像这样的断言工厂在SpringCloudGateway还有十几个 Spring Cloud Gateway 名称 说明 示例 After 是某个时间点后的请求 - After2037-01-20T17:42:47.789-07:00[America/Denver] Before 是某个时间点之前的请求 - Before2031-04-13T15:14:47.43308:00[Asia/Shanghai] Between 是某两个时间点之前的请求 - Between2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] Cookie 请求必须包含某些cookie - Cookiechocolate, ch.p Header 请求必须包含某些header - HeaderX-Request-Id, \d Host 请求必须是访问某个host域名 - Host**.somehost.org,**.anotherhost.org Method 请求方式必须是指定方式 - MethodGET,POST Path 请求路径必须符合指定规则 - Path/red/{segment},/blue/** Query 请求参数必须包含指定参数 - Queryname, Jack或者- Queryname RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr192.168.1.1/24 Weight 权重处理 server:port: 10010 #网关端口
spring:application:name: gateway #服务名称cloud:nacos:server-addr: localhost:10086 #nacos地址gateway:routes:- id: user-service #路由id自定义只要唯一就行
# uri: http://localhost:8881 #路由的目标地址http就是固定地址uri: lb://userservice #路由的目标地址 lb就是负载均衡后面接服务名称predicates: #路由断言也就是判断请求符合路由的规则- Path/user/** #这个是按照路由路径匹配只要以 /user/开头就符合要求- id: order-serviceuri: lb://orderservicepredicates:- Path/order/**- After2023-01-20T17:42:47.789-07:00[America/Denver]四、过滤器工厂
路由过滤器 GatewayFilter GatewayFilter是网关中提供的一种过滤器可以对进入网关的请求和微服务返回的响应做处理 Spring提供了31种不同的路由过滤器工厂。例如 名称 说明 AddRequestHeader 给当前请求添加一个请求头 RemoveRequestHeader 移除请求中的一个请求头 AddResponseHeader 给响应结果中添加一个响应头 RemoveResponseHeader 从响应结果中移除有一个响应头 RequestRateLimiter 限制请求的流量 ... 给单个微服务添加过滤器 spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgpredicates:- Path/red/{segment}filters:- AddRequestHeaderX-Request-Red, Blue-{segment} 默认过滤器 server:port: 10010 #网关端口
spring:application:name: gateway #服务名称cloud:nacos:server-addr: localhost:10086 #nacos地址gateway:routes:- id: user-service #路由id自定义只要唯一就行
# uri: http://localhost:8881 #路由的目标地址http就是固定地址uri: lb://userservice #路由的目标地址 lb就是负载均衡后面接服务名称predicates: #路由断言也就是判断请求符合路由的规则- Path/user/** #这个是按照路由路径匹配只要以 /user/开头就符合要求
# filters:
# - AddRequestHeaderMyHead,jizhibing- id: order-serviceuri: lb://orderservicepredicates:- Path/order/**- After2023-01-20T17:42:47.789-07:00[America/Denver]default-filters:- AddRequestHeaderMyHead,jizhibing Slf4j
RestController
RequestMapping(/user)
public class UserController {Autowiredprivate UserService userService;/*** 路径 /user/110** param id 用户id* return 用户*/GetMapping(/{id})public User queryById(PathVariable(id) Long id,RequestHeader(value MyHead,required false) String myHead) {System.out.println(MyHead : myHead);return userService.queryById(id);}
} 显示效果 04-23 08:00:03:112 INFO 95612 --- [nio-8880-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet dispatcherServlet
04-23 08:00:03:112 INFO 95612 --- [nio-8880-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet dispatcherServlet
04-23 08:00:03:116 INFO 95612 --- [nio-8880-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms
MyHead : jizhibing
2
04-23 08:00:03:155 INFO 95612 --- [nio-8880-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
04-23 08:00:03:331 INFO 95612 --- [nio-8880-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.五、全局过滤器
全局过滤器 GlobalFilter 全局过滤器的作用也是处理一切进入网关的请求和微服务响应与GatewayFilter的作用一样。 区别在于GatewayFilter通过配置定义处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。 定义方式是实现GlobalFilter接口。 public interface GlobalFilter { /** * 处理当前请求有必要的话通过{link GatewayFilterChain}将请求交给下一个过滤器处理** param exchange 请求上下文里面可以获取Request、Response等信息 * param chain 用来把请求委托给下一个过滤器 * return {code MonoVoid} 返回标示当前过滤器业务结束 */ MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain);} 过滤器执行顺序 请求进入网关会碰到三类过滤器当前路由的过滤器、DefaultFilter、GlobalFilter 请求路由后会将当前路由过滤器和DefaultFilter、GlobalFilter合并到一个过滤器链集合中排序后依次执行每个过滤器 每一个过滤器都必须指定一个int类型的order值order值越小优先级越高执行顺序越靠前。GlobalFilter通过实现Ordered接口或者添加Order注解来指定order值由我们自己指定 路由过滤器和defaultFilter的order由Spring指定默认是按照声明顺序从1递增。当过滤器的order值一样时会按照 defaultFilter 路由过滤器 GlobalFilter的顺序执行。 可以参考下面几个类的源码来查看 org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters() 方法是先加载defaultFilters然后再加载某个route的filters然后合并。 private ListGatewayFilter getFilters(RouteDefinition routeDefinition) {ListGatewayFilter filters new ArrayList();if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {filters.addAll(this.loadGatewayFilters(defaultFilters, new ArrayList(this.gatewayProperties.getDefaultFilters())));}if (!routeDefinition.getFilters().isEmpty()) {filters.addAll(this.loadGatewayFilters(routeDefinition.getId(), new ArrayList(routeDefinition.getFilters())));}AnnotationAwareOrderComparator.sort(filters);return filters;}org.springframework.cloud.gateway.handler.FilteringWebHandler#handle() 方法会加载全局过滤器与前面的过滤器合并后根据order排序组织过滤器链 public MonoVoid handle(ServerWebExchange exchange) {Route route (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);ListGatewayFilter gatewayFilters route.getFilters();ListGatewayFilter combined new ArrayList(this.globalFilters);combined.addAll(gatewayFilters);AnnotationAwareOrderComparator.sort(combined);if (logger.isDebugEnabled()) {logger.debug(Sorted gatewayFilterFactories: combined);}return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);}网关自定义过滤器 模拟用户登陆权限过滤器 package com.cloud.gateway;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.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** author jizhibing* date Created in 2022/4/23* description*/
//Order(-1)
Component
public class AuthorizeFilter implements GlobalFilter ,Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1、获取请求参数ServerHttpRequest request exchange.getRequest();MultiValueMapString, String queryParams request.getQueryParams();//2、获取请求中的authorization参数String authorization queryParams.getFirst(authorization);//3、判断参数值是否等于 adminif(admin.equals(authorization)){//4、是 放行return chain.filter(exchange);}//5、否 拦截//5.1设置状态码 401exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//5.2请求拦截return exchange.getResponse().setComplete();}Overridepublic int getOrder() {return -1;}
}不加请求头授权信息 authorization 添加请求头授权信息 authorization admin 六、跨域问题 跨域域名不一致就是跨域主要包括 域名不同 www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com域名相同端口不同localhost:8080和localhost8081 跨域问题浏览器禁止请求的发起者与服务端发生跨域ajax请求请求被浏览器拦截的问题 解决方案CORS 网关处理跨域采用的同样是CORS方案并且只需要简单配置即可实现 spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:[/**]:allowedOrigins: # 允许哪些网站的跨域请求- http://localhost:8090- http://www.leyou.comallowedMethods: # 允许的跨域ajax的请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期 七、限流过滤器
限流对应用服务器的请求做限制避免因过多请求而导致服务器过载甚至宕机。限流算法常见的包括两种
计数器算法又包括窗口计数器算法、滑动窗口计数器算法漏桶算法(Leaky Bucket)令牌桶算法Token Bucket
1限流过滤器-计数器算法 固定窗口计数器算法概念如下 将时间划分为多个窗口在每个窗口内每有一次请求就将计数器加一当时间到达下一个窗口时计数器重置如果计数器超过了限制数量则本窗口内所有的请求都被丢弃。 2限流过滤器-漏桶算法 漏桶算法说明 将每个请求视作水滴放入漏桶进行存储漏桶以固定速率向外漏出请求来执行如果漏桶空了则停止漏水”如果漏桶满了则多余的水滴会被直接丢弃。 3限流过滤器-令牌桶算法 漏桶算法说明 以固定的速率生成令牌存入令牌桶中如果令牌桶满了以后多余令牌丢弃请求进入后必须先尝试从桶中获取令牌获取到令牌后才可以被处理如果令牌桶中没有令牌则请求等待或丢弃