当前位置: 首页 > news >正文

官网网站开发asp.net网站开发第一步

官网网站开发,asp.net网站开发第一步,大连网站建设运营,没有防盗链的网站API网关是一个服务器#xff0c;是系统的唯一入口。从面向对象设计的角度看#xff0c;它与外观模式类似。API网关封装了系统内部架构#xff0c;为每个客户端提供一个定制的API。它可能还具有其它职责#xff0c;如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响…API网关是一个服务器是系统的唯一入口。从面向对象设计的角度看它与外观模式类似。API网关封装了系统内部架构为每个客户端提供一个定制的API。它可能还具有其它职责如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。API网关方式的核心要点是所有的客户端和消费端都通过统一的网关接入微服务在网关层处理所有的非业务功能。通常网关也是提供REST/HTTP的访问API。 网关应当具备以下功能 性能API高可用负载均衡容错机制。安全权限身份认证、脱敏流量清洗后端签名(保证全链路可信调用)黑名单(非法调用的限制)。日志日志记录(spainidtraceid)一旦涉及分布式全链路跟踪必不可少。缓存数据缓存。监控记录请求响应数据api耗时分析性能监控。限流流量控制错峰流控可以定义多种限流规则。灰度线上灰度部署可以减小风险。路由动态路由规则。 一、简介 SpringCloud Gateway是Spring Cloud的一个全新项目该项目是基于Spring 5.0Spring Boot 2.0和Project Reactor等技术开发的网关它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。 SpringCloud Gateway作为Spring Cloud生态系统中的网关目标是替代Zuul在Spring Cloud 2.0以上版本中没有对新版本的Zuul 2.0以上最新高性能版本进行集成仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能SpringCloud Gateway是基于WebFlux框架实现的而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。 Spring Cloud Gateway的目标不仅提供统一的路由方式并且基于Filter链的方式提供了网关基本的功能例如安全监控/指标和限流。 1.1 特征 SpringCloud官方对SpringCloud Gateway特征介绍如下 (1). 基于Spring Framework 5Project Reactor和Spring Boot 2.0 (2). 集成Hystrix断路器 (3). 集成Spring Cloud DiscoveryClient (4). Predicates和Filters作用于特定路由易于编写的Predicates和Filters (5). 具备一些网关的高级功能动态路由、限流、路径重写 从以上的特征来说和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别还是在底层的通信框架上。 简单说明一下上文中的三个术语 (1). Filter(过滤器)和Zuul的过滤器在概念上类似可以使用它拦截和修改请求并且对上游的响应进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。 (2). Route(路由)网关配置的基本组成模块和Zuul的路由配置模块类似。一个Route模块由一个ID一个目标URI一组断言和一组过滤器定义。如果断言为真则路由匹配目标URI会被访问。 (3). Predicate(断言)这是一个Java 8的Predicate可以使用它来匹配来自HTTP请求的任何内容例如headers或参数。断言的输入类型是一个ServerWebExchange。 1.2 架构 Spring在2017年下半年迎来了WebfluxWebflux的出现填补了Spring在响应式编程上的空白Webflux的响应式编程不仅仅是编程风格的改变而且对于一系列的著名框架都提供了响应式访问的开发包比如Netty、Redis等等。 SpringCloud Gateway使用的Webflux中的reactor-netty响应式编程组件底层使用了Netty通讯框架。 1.2.1 Zuul的IO模型 Springcloud中所集成的Zuul版本采用的是Tomcat容器使用的是传统的Servlet IO处理模型。 大家知道servlet由servlet container进行生命周期管理。container启动时构造servlet对象并调用servlet init()进行初始化container关闭时调用servlet destory()销毁servletcontainer运行时接受请求并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。 弊端servlet是一个简单的网络IO模型当请求进入servlet container时servlet container就会为其绑定一个线程在并发不高的场景下这种模型是适用的但是一旦并发上升线程数量就会上涨而线程资源代价是昂贵的(上线文切换内存消耗大)严重影响请求的处理时间。在一些简单的业务场景下不希望为每个request分配一个线程只需要1个或几个线程就能应对极大并发的请求这种业务场景下servlet模型没有优势。 所以Springcloud Zuul是基于servlet之上的一个阻塞式处理模型即spring实现了处理所有request请求的一个servlet(DispatcherServlet)并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端。虽然Zuul 2.0开始使用了Netty并且已经有了大规模Zuul 2.0集群部署的成熟案例但是Springcloud官方已经没有集成改版本的计划了。 1.2.2 Webflux服务器 Webflux模式替换了旧的Servlet线程模型。用少量的线程处理request和response io操作这些线程称为Loop线程而业务交给响应式编程框架处理响应式编程是非常灵活的用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行而不阻塞的操作依然可以在Loop线程中进行处理大大提高了Loop线程的利用率。官方结构图 Webflux虽然可以兼容多个底层的通信框架但是一般情况下底层使用的还是Netty毕竟Netty是目前业界认可的最高性能的通信框架。而Webflux的Loop线程正好就是著名的Reactor模式IO处理模型的Reactor线程如果使用的是高性能的通信框架Netty这就是Netty的EventLoop线程。 1.2.3 处理流程 客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。 二、路由配置方式 2.1 基础URI路由配置方式 如果请求的目标地址是单个的URI资源路径配置文件示例如下 server:port: 8080 spring:application:name: api-gatewaycloud:gateway:routes:-id: url-proxy-1uri: https://blog.csdn.netpredicates:-Path/csdn各字段含义如下 id我们自定义的路由ID保持唯一uri目标服务地址predicates路由条件Predicate接受一个输入参数返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如与或非)。 上面这段配置的意思是配置了一个id为url-proxy-1的URI代理规则路由的规则为 当访问地址http://localhost:8080/csdn/1.jsp时会路由到上游地址https://blog.csdn.net/1.jsp。 2.2 基于代码的路由配置方式 转发功能同样可以通过代码来实现我们可以在启动类GateWayApplication中添加方法customRouteLocator()来定制转发规则。 package com.springcloud.gateway;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean;SpringBootApplication public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route(path_route, r - r.path(/csdn).uri(https://blog.csdn.net)).build();} }我们在yaml配置文件中注销掉相关路由的配置重启服务访问链接http://localhost:8080/csdn可以看到和上面一样的页面证明我们测试成功。 上面两个示例中uri都是指向了我的CSDN博客在实际项目使用中可以将uri指向对外提供服务的项目地址统一对外输出接口。 2.3 和注册中心相结合的路由配置方式 在uri的schema协议部分为自定义的lb:类型表示从微服务注册中心(如Eureka)订阅服务并且进行服务的路由。 一个典型的示例如下 server:port: 8084 spring:cloud:gateway:routes:- id: seckill-provider-routeuri: lb://seckill-providerpredicates:- Path/seckill-provider/**- id: message-provider-routeuri: lb://message-providerpredicates:- Path/message-provider/**application:name: cloud-gatewayeureka:instance:prefer-ip-address: trueclient:service-url:defaultZone: http://localhost:8888/eureka/注册中心相结合的路由配置方式与单个URI的路由配置区别其实很小仅仅在于URI的schema协议不同。单个URI的地址的schema协议一般为http或者https协议。 三、路由匹配规则 Spring Cloud Gateway的功能很强大我们仅仅通过Predicates的设计就可以看出来前面我们只是使用了predicates进行了简单的条件匹配其实Spring Cloud Gateway帮我们内置了很多Predicates功能。 Spring Cloud Gateway是通过Spring WebFlux的HandlerMapping做为底层支持来匹配到转发路由Spring Cloud Gateway内置了很多Predicates工厂这些Predicates工厂通过不同的HTTP请求参数来匹配多个Predicates工厂可以组合使用。 gateWay的主要功能之一是转发请求转发规则的定义主要包含三个部分 Route(路由)路由是网关的基本单元由ID、URI、一组Predicate、一组Filter组成根据Predicate进行匹配转发。Predicate(谓语、断言)路由转发的判断条件目前SpringCloud Gateway支持多种方式常见如Path、Query、Method、Header等写法必须遵循keyvlue的形式。Filter(过滤器)过滤器是路由转发请求时所经过的过滤逻辑可用于修改请求、响应内容。 其中Route和Predicate必须同时申明 例子 ##通过配置文件配置 spring:cloud:gateway:routes:- id: gate_routeuri: http://localhost:9023predicates:## 当请求的路径为gate、rule开头的时转发到http://localhost:9023服务器上- Path/gate/**,/rule/**### 请求路径前加上/appfilters:- PrefixPath/app3.1 Predicate断言条件(转发规则)介绍 Predicate来源于Java 8是Java 8中引入的一个函数Predicate接受一个输入参数返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如与或非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。 在Spring Cloud Gateway中Spring利用Predicate的特性实现了各种路由匹配规则有通过Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了Spring Cloud内置的几种Predicate的实现。 说白了Predicate就是为了实现一组匹配规则方便让请求过来找到对应的Route进行处理接下来我们接下Spring Cloud GateWay内置几种Predicate的使用。 转发规则(predicates)假设转发uri都设定为http://localhost:9023 规则实例说明Path- Path/gate/,/rule/## 当请求的路径为gate、rule开头的时转发到http://localhost:9023服务器上Before- Before2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之前的请求才会被转发到 http://localhost:9023服务器上After- After2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之后的请求才会被转发Between- Between2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]在某个时间段之间的才会被转发Cookie- Cookiechocolate, ch.p名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发Header- HeaderX-Request-Id, \d携带参数X-Request-Id或者满足\d的请求头才会匹配Host- Hostwww.hd123.com当主机名为www.hd123.com的时候直接转发到http://localhost:9023服务器上Method- MethodGET只有GET方法才会匹配转发请求还可以限定POST、PUT等请求方式 3.1.1 通过时间匹配 Predicate支持设置一个时间在请求进行转发的时候可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在2019年1月1日才会转发到我的网站在这之前不进行转发我就可以这样配置 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:- id: gateway-serviceuri: https://www.baidu.compredicates:- After2018-01-20T06:06:0608:00[Asia/Shanghai]Spring是通过ZonedDateTime来对时间进行的对比ZonedDateTime是Java 8中日期时间功能里用于表示带时区的日期与时间信息的类ZonedDateTime支持通过时区来设置时间中国的时区是Asia/Shanghai。 After Route Predicate是指在这个时间之后的请求都转发到目标地址。上面的示例是指请求时间在2018年1月20日6点6分6秒之后的所有请求都转发到地址https://www.baidu.com。08:00是指时间和UTC时间相差八个小时时间地区为Asia/Shanghai。 添加完路由规则之后访问地址http://localhost:8080会自动转发到https://www.baidu.com。 Before Route Predicate刚好相反在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的After改为Before如下 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:- id: gateway-serviceuri: https://www.baidu.compredicates:- Before2018-01-20T06:06:0608:00[Asia/Shanghai]就表示在这个时间之前可以进行路由在这时间之后停止路由修改完之后重启项目再次访问地址http://localhost:8080页面会报404没有找到地址。 除过在时间之前或者之后外Gateway还支持限制路由请求在某一个时间段范围内可以使用Between Route Predicate来实现。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:- id: gateway-serviceuri: https://www.baidu.compredicates:- Between2018-01-20T06:06:0608:00[Asia/Shanghai], 2019-01-20T06:06:0608:00[Asia/Shanghai]这样设置就意味着在这个时间段内可以匹配到此路由超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷可以用在限时抢购的一些场景中。 3.1.2 通过请求参数匹配 Query Route Predicate支持传入两个参数一个是属性名一个为属性值属性值可以是正则表达式。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:-Querysmile这样配置只要请求中包含smile属性的参数即可匹配路由。使用curl测试命令行输入 curl localhost:8080?smilexid2经过测试发现只要请求汇总带有smile参数即会匹配路由不带smile参数则不会匹配。还可以将Query的值以键值对的方式进行配置这样在请求过来时会对属性值和正则进行匹配匹配上才会走路由。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:-Querykeep, pu.这样只要当请求中包含keep属性并且参数值是以pu开头的长度为三位的字符串才会进行匹配和路由。使用curl测试命令行输入: curl localhost:8080?keeppub测试可以返回页面代码将keep的属性值改为pubx再次访问就会报404证明路由需要匹配正则表达式才会进行路由。 3.1.3 通过Header属性匹配 Header Route Predicate和Cookie Route Predicate一样也是接收2个参数一个header中属性名称和一个正则表达式这个属性值和正则表达式匹配则执行。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- HeaderX-Request-Id, \d使用curl测试命令行输入: curl http://localhost:8080/ -H X-Request-Id:88则返回页面代码证明匹配成功。将参数-H X-Request-Id:88改为-H X-Request-Id:spring再次执行时返回404证明没有匹配。 3.1.4 通过Cookie匹配 Cookie Route Predicate可以接收两个参数一个是Cookie name一个是正则表达式路由规则会通过获取对应的Cookie name值和正则表达式去匹配如果匹配上就会执行路由如果没有匹配上则不执行。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- CookiesessionId, test使用curl测试命令行输入: curl http://localhost:8080 --cookie sessionIdtest则会返回页面代码如果去掉--cookie sessionIdtest后台汇报404错误。 3.1.5 通过Host匹配 Host Route Predicate接收一组参数一组匹配的域名列表这个模板是一个ant分隔的模板用.号作为分隔符。它通过参数中的主机地址作为匹配规则。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- Host**.baidu.com使用curl测试命令行输入: curl http://localhost:8080/ -H Host: www.baidu.com curl http://localhost:8080/ -H Host: md.baidu.com经测试以上两种host均可匹配到host_route路由去掉host参数则会报404错误。 3.1.6 通过请求方式匹配 可以通过是POST、GET、PUT、DELETE等不同的请求方式来进行路由。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- MethodGET使用curl测试命令行输入: # curl默认是以GET的方式去请求 curl http://localhost:8080/测试返回页面代码证明匹配到路由我们再以POST的方式请求测试。 # curl默认是以GET的方式去请求 curl -X POST http://localhost:8080/返回404没有找到证明没有匹配上路由 3.1.7 通过请求路径匹配 Path Route Predicate接收一个匹配路径的参数来判断是否走路由。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:-id: gateway-serviceuri: http://ityouknow.comorder: 0predicates:-Path/foo/{segment}如果请求路径符合要求则此路由将匹配例如/foo/1或者/foo/bar。 使用curl测试命令行输入: curl http://localhost:8080/foo/1 curl http://localhost:8080/foo/xx curl http://localhost:8080/boo/xx经过测试第一和第二条命令可以正常获取到页面返回值最后一个命令报404证明路由是通过指定路由来匹配。 3.1.8 通过请求ip地址进行匹配 Predicate也支持通过设置某个ip区间号段的请求才会路由RemoteAddr Route Predicate接受cidr符号(IPv4或IPv6)字符串的列表(最小大小为1)例如192.168.0.1/16(其中192.168.0.1是IP地址16是子网掩码)。 server:port: 8080spring:application:name: api-gatewaycloud:gateway:routes:- id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- RemoteAddr192.168.1.1/24可以将此地址设置为本机的ip地址进行测试。 curl localhost:8080如果请求的远程地址是192.168.1.10则此路由将匹配。 3.1.10 组合使用 server:port: 8080 spring:application:name: api-gatewaycloud:gateway:routes:- id: gateway-serviceuri: https://www.baidu.comorder: 0predicates:- Host**.foo.org- Path/headers- MethodGET- HeaderX-Request-Id, \d- Queryfoo, ba.- Querybaz- Cookiechocolate, ch.p各种Predicates同时存在于同一个路由时请求必须同时满足所有的条件才被这个路由匹配。 一个请求满足多个路由的断言条件时请求只会被首个成功匹配的路由转发 3.2 过滤器规则(Filter) 过滤规则实例说明PrefixPath- PrefixPath/app在请求路径前加上appRewritePath- RewritePath/test, /app/test访问localhost:9022/test请求会转发到localhost:8001/app/testSetPathSetPath/app/通过模板设置路径转发的规则时会在路径前增加app{path}表示原请求路径RedirectTo重定向RemoveRequestHeader去掉某个请求头信息 注当配置多个filter时优先定义的会被调用剩余的filter将不会生效 3.2.1 StripPrefix StripPrefix是一个请求路径截取的功能我们可以利用这个功能来做特殊业务的转发。上面这个配置的例子表示当请求路径匹配到/name/**会将包含name和后边的字符串接去掉转发StripPrefix2就代表截取路径的个数这样配置后当请求/name/bar/foo后端匹配到的请求路径就会变成http://nameservice/foo。 跳过指定路径。 spring:cloud:gateway:routes:- id: nameRooturi: https://nameservicepredicates:- Path/name/**filters:- StripPrefix2请求/name/blue/red会转发到/red。 3.2.2 PrefixPath 对所有的请求路径添加前缀 spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- PrefixPath/mypath访问/hello的请求被发送到https://example.org/mypath/hello。 3.2.3 RedirectTo 重定向配置包含重定向的返回码和地址 spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- RedirectTo302, https://acme.org3.2.3 RemoveRequestHeader 去掉某个请求头信息 spring:cloud:gateway:routes:- id: removerequestheader_routeuri: https://example.orgfilters:- RemoveRequestHeaderX-Request-Foo去掉请求头信息X-Request-Foo 3.2.4 RemoveResponseHeader 去掉某个回执头信息 spring:cloud:gateway:routes:- id: removerequestheader_routeuri: https://example.orgfilters:- RemoveResponseHeaderX-Request-Foo3.2.5 RemoveRequestParameter 去掉某个请求参数信息 spring:cloud:gateway:routes:- id: removerequestparameter_routeuri: https://example.orgfilters:- RemoveRequestParameterred3.2.6 RewritePath 改写路径 spring:cloud:gateway:routes:- id: rewrite_filteruri: http://localhost:8081predicates:- Path/test/**filters:- RewritePath/where(?segment/?.*), /test(?segment/?.*)/where/...改成test/... 使用代码改下路径 RouteLocatorBuilder.Builder builder routeLocatorBuilder.routes(); builder.route(path_rote_at_guigu, r - r.path(/guonei).uri(http://news.baidu.com/guonei)).route(csdn_route, r - r.path(/csdn).uri(https://blog.csdn.net)).route(blog3_rewrite_filter, r - r.path(/blog3/**).filters(f - f.rewritePath(/blog3/(?segment.*), /$\\{segment})).uri(https://blog.csdn.net)).route(rewritepath_route, r - r.path(/baidu/**).filters(f - f.rewritePath(/baidu/(?segment.*), /$\\{segment})).uri(http://www.baidu.com)).build();3.2.7 SetPath 设置请求路径与RewritePath类似。 spring:cloud:gateway:routes:- id: setpath_routeuri: https://example.orgpredicates:- Path/red/{segment}filters:- SetPath/{segment}如/red/blue的请求被转发到/blue。 3.2.8 SetRequestHeader 设置请求头信息。 spring:cloud:gateway:routes:- id: setrequestheader_routeuri: https://example.orgfilters:- SetRequestHeaderX-Request-Red, Blue3.2.9 SetStatus 设置回执状态码。 spring:cloud:gateway:routes:- id: setstatusint_routeuri: https://example.orgfilters:- SetStatus4013.2.10 RequestSize 请求大小。 spring:cloud:gateway:routes:- id: request_size_routeuri: http://localhost:8080/uploadpredicates:- Path/uploadfilters:- name: RequestSizeargs:maxSize: 5000000超过5M的请求会返回413错误。 3.2.11 Default-filters 对所有请求添加过滤器。 spring:cloud:gateway:default-filters:- AddResponseHeaderX-Response-Default-Red, Default-Blue- PrefixPath/httpbin3.3 通过代码进行配置 通过代码进行配置将路由规则设置为一个Bean即可 Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route(path_route, r - r.path(/get).uri(http://httpbin.org)).route(host_route, r - r.host(*.myhost.org).uri(http://httpbin.org)).route(rewrite_route, r - r.host(*.rewrite.org).filters(f - f.rewritePath(/foo/(?segment.*), /${segment})).uri(http://httpbin.org)).route(hystrix_route, r - r.host(*.hystrix.org).filters(f - f.hystrix(c - c.setName(slowcmd))).uri(http://httpbin.org)).route(hystrix_fallback_route, r - r.host(*.hystrixfallback.org).filters(f - f.hystrix(c - c.setName(slowcmd).setFallbackUri(forward:/hystrixfallback))).uri(http://httpbin.org)).route(limit_route, r - r.host(*.limited.org).and().path(/anything/**).filters(f - f.requestRateLimiter(c - c.setRateLimiter(redisRateLimiter()))).uri(http://httpbin.org)).build(); }3.4 实现熔断降级 为什么要实现熔断降级 在分布式系统中网关作为流量的入口因此会有大量的请求进入网关向其他服务发起调用其他服务不可避免的会出现调用失败(超时、异常)失败时不能让请求堆积在网关上需要快速失败并返回给客户端想要实现这个要求就必须在网关上做熔断、降级操作。 为什么在网关上请求失败需要快速返回给客户端 因为当一个客户端请求发生故障的时候这个请求会一直堆积在网关上当然只有一个这种请求网关肯定没有问题(如果一个请求就能造成整个系统瘫痪那这个系统可以下架了)但是网关上堆积多了就会给网关乃至整个服务都造成巨大的压力甚至整个服务宕掉。因此要对一些服务和页面进行有策略的降级以此缓解服务器资源的的压力以保证核心业务的正常运行同时也保持了客户和大部分客户的得到正确的相应所以需要网关上请求失败需要快速返回给客户端。 server.port: 8082spring:application:name: gatewayredis:host: localhostport: 6379password: 123456cloud:gateway:routes:- id: rateLimit_routeuri: http://localhost:8000order: 0predicates:- Path/test/**filters:- StripPrefix1- name: Hystrixargs:name: fallbackCmdAfallbackUri: forward:/fallbackAhystrix.command.fallbackCmdA.execution.isolation.thread.timeoutInMilliseconds: 5000这里的配置使用了两个过滤器 (1). 过滤器StripPrefix作用是去掉请求路径的最前面n个部分截取掉。StripPrefix1就代表截取路径的个数为1比如前端过来请求/test/good/1/view匹配成功后路由到后端的请求路径就会变成http://localhost:8888/good/1/view。 (2). 过滤器Hystrix作用是通过Hystrix进行熔断降级 当上游的请求进入了Hystrix熔断降级机制时就会调用fallbackUri配置的降级地址。需要注意的是还需要单独设置Hystrix的commandKey的超时时间 fallbackUri配置的降级地址的代码如下 package org.gateway.controller;import org.gateway.response.Response; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;RestController public class FallbackController {GetMapping(/fallbackA)public Response fallbackA() {Response response new Response();response.setCode(100);response.setMessage(服务暂时不可用);return response;} }四、高级配置 4.1 分布式限流 从某种意义上讲令牌桶算法是对漏桶算法的一种改进桶算法能够限制请求调用的速率而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中存在一个桶用来存放固定数量的令牌。算法中存在一种机制以一定的速率往桶中放令牌。每次请求调用需要先获取令牌只有拿到令牌才有机会继续执行否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行如果桶中令牌数达到上限就丢弃令牌所以就存在这种情况桶中一直有大量的可用令牌这时进来的请求就可以直接拿到令牌执行比如设置qps为100那么限流器初始化完成一秒后桶中就已经有100个令牌了这时服务还没完全启动好等启动完成对外提供服务时该限流器可以抵挡瞬时的100个请求。所以只有桶中没有令牌时请求才会进行等待最后相当于以一定的速率执行。 在Spring Cloud Gateway中有Filter过滤器因此可以在“pre”类型的Filter中自行实现上述三种过滤器。但是限流作为网关最基本的功能Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类适用在Redis内的通过执行Lua脚本实现了令牌桶的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类中lua脚本在如下图所示的文件夹中 首先在工程的pom文件中引入gateway的起步依赖和redis的reactive依赖代码如下 配置如下 server:port: 8081 spring:cloud:gateway:routes:- id: limit_routeuri: http://httpbin.org:80/getpredicates:- After2017-01-20T17:42:47.789-07:00[America/Denver]filters:- name: RequestRateLimiterargs:key-resolver: #{userKeyResolver}redis-rate-limiter.replenishRate: 1redis-rate-limiter.burstCapacity: 3application:name: cloud-gatewayredis:host: localhostport: 6379database: 0在上面的配置文件指定程序的端口为8081配置了redis的信息并配置了RequestRateLimiter的限流过滤器该过滤器需要配置三个参数 burstCapacity令牌桶总容量。replenishRate令牌桶每秒填充平均速率。key-resolver用于限流的键的解析器的Bean对象的名字。它使用SpEL表达式根据#{beanName}从Spring容器中获取Bean对象。 这里根据用户ID限流请求路径中必须携带userId参数 Bean KeyResolver userKeyResolver() {return exchange - Mono.just(exchange.getRequest().getQueryParams().getFirst(user)); }KeyResolver需要实现resolve方法比如根据userid进行限流则需要用userid去判断。实现完KeyResolver之后需要将这个类的Bean注册到Ioc容器中。 如果需要根据IP限流定义的获取限流Key的bean为 Bean public KeyResolver ipKeyResolver() {return exchange - Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); }通过exchange对象可以获取到请求信息这边用了HostName如果你想根据用户来做限流的话这边可以获取当前请求的用户ID或者用户名就可以了比如 如果需要根据接口的URI进行限流则需要获取请求地址的uri作为限流key定义的Bean对象为 Bean KeyResolver apiKeyResolver() {return exchange - Mono.just(exchange.getRequest().getPath().value()); }通过exchange对象可以获取到请求信息这边用了HostName如果你想根据用户来做限流的话这边可以获取当前请求的用户ID或者用户名就可以了比如 如果需要根据接口的URI进行限流则需要获取请求地址的uri作为限流key定义的Bean对象为 Bean KeyResolver apiKeyResolver() {return exchange - Mono.just(exchange.getRequest().getPath().value()); }4.2 健康检查配置 admin-client、actuator健康检查配置为之后的功能提供支持此部分比较简单不再赘述加入以下maven依赖和配置 maven依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId /dependency dependencygroupIdde.codecentric/groupIdartifactIdspring-boot-admin-starter-client/artifactIdversion2.1.0/version /dependency dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId /dependency配置文件 spring:application:name: mas-cloud-gatewayboot:admin:client:### 本地搭建的admin-serverurl: http://localhost:8011 eureka:client:registerWithEureka: truefetchRegistry: truehealthcheck:enabled: trueserviceUrl:defaultZone: http://localhost:6887/eureka/enabled: true feign:sentinel:enabled: true management:endpoints:web:exposure:include: *endpoint:health:show-details: ALWAYS若转发的目标地址为微服务中组件不为具体ip:port形式的应写成lb://mas-openapi-service形式目标地址会从注册中心直接拉取 4.3 统一配置跨域请求 现在的请求通过经过gateWay网关时需要在网关统一配置跨域请求需求所有请求通过 spring:cloud:gateway:globalcors:cors-configurations:[/**]:allowed-origins: *allowed-headers: *allow-credentials: trueallowed-methods:- GET- POST- DELETE- PUT- OPTION五、整合Nacos maven依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.1.9.RELEASE/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.example/groupIdartifactIdnacos_gateway/artifactIdversion0.0.1-SNAPSHOT/versionpackagingwar/packagingnamenacos_gateway/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version1.8/java.versionspring-cloud.versionGreenwich.SR3/spring-cloud.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!--gateway--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!--nacos dicovery--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion0.2.2.RELEASE/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project需要注意在Gateway服务中的pom.xml文件中不要存在这个jar dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-tomcat/artifactIdscopeprovided/scope /dependency否则调用接口时会报以下错误因为gateway使用的是webflux默认使用netty所以从依赖中排除tomcat相关的依赖 java.lang.ClassCastException: org.springframework.core.io.buffer.DefaultDataBufferFactory cannot be cast to org.springframework.core.io.buffer.NettyDataBufferFactoryat org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.lambda$filter$1(NettyWriteResponseFilter.java:82) ~[spring-cloud-gateway-core-2.1.3.RELEASE.jar:2.1.3.RELEASE]at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) [reactor-core-3.2.12.RELEASE.jar:3.2.12.RELEASE]错误2 是由于spring-boot-starter-web引起 服务发现配置从Nacos获取微服务提供者清单 server:port: 8087spring:application:name: nacos_gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:enabled: true #表明gateway开启服务注册和发现的功能# 并且spring cloud gateway自动根据服务发现为每一个服务创建了一个router3 这个router将以服务名开头的请求路径转发到对应的服务lower-case-service-id: true #是将请求路径上的服务名配置为小写routes:-id: apiuser#uri: lb://nacos-consumer-userpredicates:# http://localhost:6601/user/user/users/2, 必须加上StripPrefix1否则访问服务时会带上user- Path/user/** # 转发该路径#以下是配置例子# - id: 163 #网关路由到网易官网# uri: http://www.163.com/# predicates:- Path/163/**# - id: ORDER-SERVICE #网关路由到订单服务order-service# uri: lb://ORDER-SERVICE# predicates:# - Path/ORDER-SERVICE/**# - id: USER-SERVICE #网关路由到用户服务user-service# uri: lb://USER-SERVICE# predicates:# - Path/USER-SERVICE/**nacos实现动态配置 使用nacos实现动态路由以上两种方式都是实现的静态配置路径只能应对部分场景接下来配置nacos实现动态配置以及配置的存储由于gateWay并没有适配nacos需要自定义监听器 Component Slf4j public class NacosDynamicRouteService implements ApplicationEventPublisherAware {private String dataId gateway-router;private String group DEFAULT_GROUP;Value(${spring.cloud.nacos.config.server-addr})private String serverAddr;Autowiredprivate RouteDefinitionWriter routeDefinitionWriter;private ApplicationEventPublisher applicationEventPublisher;private static final ListString ROUTE_LIST new ArrayList();PostConstructpublic void dynamicRouteByNacosListener() {try {ConfigService configService NacosFactory.createConfigService(serverAddr);configService.getConfig(dataId, group, 5000);configService.addListener(dataId, group, new Listener() {Overridepublic void receiveConfigInfo(String configInfo) {clearRoute();try {if (StringUtil.isNullOrEmpty(configInfo)) {//配置被删除return;}ListRouteDefinition gatewayRouteDefinitions JSONObject.parseArray(configInfo, RouteDefinition.class);for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {addRoute(routeDefinition);}publish();} catch (Exception e) {log.error(receiveConfigInfo error e);}}Overridepublic Executor getExecutor() {return null;}});} catch (NacosException e) {log.error(dynamicRouteByNacosListener error e);}}private void clearRoute() {for (String id : ROUTE_LIST) {this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();}ROUTE_LIST.clear();}private void addRoute(RouteDefinition definition) {try {routeDefinitionWriter.save(Mono.just(definition)).subscribe();ROUTE_LIST.add(definition.getId());} catch (Exception e) {log.error(addRoute error e);}}private void publish() {this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));}Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher applicationEventPublisher;} }在nacos中增加一个规则 [{filters: [],id: baidu_route,order: 0,predicates: [{args: {pattern: /baidu},name: Path}],uri: https://www.baidu.com }]访问网关的路由规则能看到刚刚加入的规则访问http://localhost:9022/baidu时请求直接被转发到百度的首页了。 六、整合Swagger聚合微服务系统API文档 maven依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdcloud-center-alibaba/artifactIdgroupIdcom.test.springcloud/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersiongroupIdcom.test.springcloud/groupIdartifactIdspringcloud-gateway-demo/artifactIdversion1.0-SNAPSHOT/versionnamespringcloud-gateway-demo/namepackagingjar/packagingdependencies!-- gateway网关依赖内置webflux依赖 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!-- 新增sentinel --dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-spring-cloud-gateway-adapter/artifactId/dependencydependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-transport-simple-http/artifactId/dependency!-- nacos服务注册发现依赖 --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactIdexclusionsexclusiongroupIdcom.google.guava/groupIdartifactIdguava/artifactId/exclusion/exclusions/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.connector.version}/version/dependency!-- nacos配置服务依赖 --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactIdexclusionsexclusiongroupIdcom.google.guava/groupIdartifactIdguava/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion${hutool.version}/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion${swagger.version}/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-common/artifactIdversion${swagger.version}/version/dependencydependencygroupIdcom.github.xiaoymin/groupIdartifactIdswagger-bootstrap-ui/artifactIdversion${swagger-ui.version}/version/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-commons/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationmainClasscom.test.cloud.nacos.demo.gateway.starter.GatewayProviderApplication/mainClass/configurationexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions/pluginpluginartifactIdmaven-assembly-plugin/artifactIdversion2.4.1/versionconfigurationdescriptorsdescriptorsrc/main/assembly/assembly.xml/descriptor/descriptors/configurationexecutionsexecutionidmake-assembly/idphasepackage/phasegoalsgoalsingle/goal/goals/execution/executions/plugin!-- 添加docker-maven插件 --plugingroupIdcom.spotify/groupIdartifactIddocker-maven-plugin/artifactIdversion1.1.1/versionconfigurationimageNamedockerlocal:5000/${project.artifactId}:${project.version}/imageNamebaseImagedockerlocal:5000/java/baseImageentryPoint[java, -jar, /${project.build.finalName}.jar]/entryPointdockerDirectorydocker/dockerDirectoryresourcesresourcetargetPath//targetPathdirectory${project.build.directory}/directoryinclude${project.build.finalName}.jar/include/resource/resources/configuration/plugin/plugins/build /project配置文件 package com.test.cloud.nacos.demo.gateway.config;import lombok.AllArgsConstructor; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider;import java.util.ArrayList; import java.util.List;/*** ClassName SwaggerProvider* PackageName com.ruoyi.gateway.config* Description* Version 1.0*/ Component Primary AllArgsConstructor public class SwaggerConfig implements SwaggerResourcesProvider {public static final String API_URI /v2/api-docs;private final RouteLocator routeLocator;private final GatewayProperties gatewayProperties;Overridepublic ListSwaggerResource get(){/*** 网关应用名称不需要在网关的swagger上展示*/String appName springcloud-gateway;ListSwaggerResource resources new ArrayList();ListString routes new ArrayList();// 取出gateway的routerouteLocator.getRoutes().subscribe(route - routes.add(route.getId()));// 结合配置的route-路径(Path)和route过滤只获取有效的route节点// 打开下面注释可以自动扫描接入gateway的服务为了演示只扫描system// gatewayProperties.getRoutes().stream().filter(routeDefinition -// routes.contains(routeDefinition.getId()))gatewayProperties.getRoutes().stream().filter(route - route.getUri().getHost() ! null).filter(route - !appName.equals(route.getUri().getHost())).forEach(routeDefinition - routeDefinition.getPredicates().stream().filter(predicateDefinition - (Path).equalsIgnoreCase(predicateDefinition.getName())).forEach(predicateDefinition - resources.add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX 0).replace(/**, API_URI)))));return resources;}private SwaggerResource swaggerResource(String name, String location){SwaggerResource swaggerResource new SwaggerResource();swaggerResource.setName(name);swaggerResource.setLocation(location);swaggerResource.setSwaggerVersion(2.0);return swaggerResource;} }效果 七、Gateway网关的过滤器开发 7.1 过滤器的执行次序 Spring-Cloud-Gateway基于过滤器实现同zuul类似有pre和post两种方式的filter分别处理前置逻辑和后置逻辑。客户端的请求先经过pre类型的filter然后将请求转发到具体的业务服务收到业务服务的响应之后再经过post类型的filter处理最后返回响应到客户端。 过滤器执行流程如下order越大优先级越低 分为全局过滤器和局部过滤器 全局过滤器 对所有路由生效局部过滤器 对指定路由生效 7.2 定义全局过滤器 实现GlobalFilter和Ordered重写相关方法加入到spring容器管理即可无需配置全局过滤器对所有的路由都有效。 全局过滤器举例代码如下 package com.test.cloud.nacos.demo.gateway.config;import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;Configuration public class FilterConfig{BeanOrder(-1)public GlobalFilter a(){return new AFilter();}BeanOrder(0)public GlobalFilter b(){return new BFilter();}BeanOrder(1)public GlobalFilter c(){return new CFilter();}Slf4jpublic class AFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain){log.info(AFilter前置逻辑);return chain.filter(exchange).then(Mono.fromRunnable(() - {log.info(AFilter后置逻辑);}));}// 值越小优先级越高// int HIGHEST_PRECEDENCE -2147483648;// int LOWEST_PRECEDENCE 2147483647;Overridepublic int getOrder(){return HIGHEST_PRECEDENCE 100;}}Slf4jpublic class BFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain){log.info(BFilter前置逻辑);return chain.filter(exchange).then(Mono.fromRunnable(() - {log.info(BFilter后置逻辑);}));}Overridepublic int getOrder(){return HIGHEST_PRECEDENCE 200;}}Slf4jpublic class CFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain){log.info(CFilter前置逻辑);return chain.filter(exchange).then(Mono.fromRunnable(() - {log.info(CFilter后置逻辑);}));}Overridepublic int getOrder() {return HIGHEST_PRECEDENCE 300;}} }7.3 定义局部过滤器 局部过滤器举例对请求头部的user-id进行校验代码如下 需要实现GatewayFilterOrdered实现相关的方法 package com.test.cloud.nacos.demo.gateway.filter;import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilter; 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.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;//Component Slf4j public class UserIdCheckGateWayFilter implements GatewayFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {String url exchange.getRequest().getPath().pathWithinApplication().value();log.info(请求URL: url);log.info(method: exchange.getRequest().getMethod());/* String secret exchange.getRequest().getHeaders().getFirst(secret);if (StringUtils.isBlank(secret)){return chain.filter(exchange);}*/// 获取param 请求参数String uname exchange.getRequest().getQueryParams().getFirst(uname);// 获取headerString userId exchange.getRequest().getHeaders().getFirst(user-id);log.info(userId userId);if (StringUtils.isBlank(userId)) {log.info(*****头部验证不通过请在头部输入user-id);// 终止请求直接回应exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}Overridepublic int getOrder() {return HIGHEST_PRECEDENCE;} }加入到过滤器工厂并且注册到spring容器中。 package com.test.cloud.nacos.demo.gateway.config;import com.test.cloud.nacos.demo.gateway.filter.UserIdCheckGateWayFilter; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.stereotype.Component;Component public class UserIdCheckGatewayFilterFactory extends AbstractGatewayFilterFactoryObject {Overridepublic GatewayFilter apply(Object config) {return new UserIdCheckGateWayFilter();} }在配置文件中进行配置如果不配置则不启用此过滤器规则。 - id: service_provider_demo_route_filteruri: lb://service-provider-demopredicates:- Path/filter/**filters:- RewritePath/filter/(?segment.*), /provider/$\{segment}- UserIdCheck八、整合Sentinel完成流控和降级 maven依赖 使用Sentinel作为gateWay的限流、降级、系统保护工具 !--alibaba 流量卫士-- dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-core/artifactIdversion${sentinel.version}/version /dependency dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependency dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-spring-cloud-gateway-adapter/artifactIdversion1.7.1/version /dependency配置文件 客户端配置在配置文件中增加下列配置dashboard就可以轻松管理客户端了还有一种方式是在启动时加入 spring:cloud:sentinel:transport:## VM##-Djava.net.preferIPv4Stacktrue -Dcsp.sentinel.dashboard.serverlocalhost:8080## -Dcsp.sentinel.api.port8666 -Dproject.namegateway -Dcsp.sentinel.app.type1dashboard: localhost:8880port: 8880限流规则通用配置 由于sentinel的工作原理其实借助于全局的filter进行请求拦截并计算出是否进行限流、熔断等操作的增加SentinelGateWayFilter配置 Bean//拦截请求 Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter(); }sentinel不仅支持通过硬代码方式进行资源的申明还能通过注解方式进行声明为了让注解生效还需要配置切面类SentinelResourceAspect Bean public SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect(); }sentinel拦截包括了视图、静态资源等需要配置viewResolvers以及拦截之后的异常我们也可以自定义抛出异常的提示 public SentinelConfig(ObjectProviderListViewResolver viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer serverCodecConfigurer; }Bean//自定义异常 Order(Ordered.HIGHEST_PRECEDENCE) public ExceptionHandler sentinelGatewayBlockExceptionHandler() {// Register the block exception handler for Spring Cloud Gateway.return new ExceptionHandler(viewResolvers, serverCodecConfigurer); }自定义异常提示当发生限流、熔断异常时会返回定义的提示信息。 /*** 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler*/ Bean Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandlerEX(viewResolvers, serverCodecConfigurer); }不需要额外的配置sentinel就已经可以正常工作了 限流规则设置 1 资源定义定义API组 2 定义限流规则 具体请参见学习视频 网关限流参数 其中网关限流规则GatewayFlowRule的字段解释如下 resource资源名称可以是网关中的route名称或者用户自定义的API分组名称。resourceMode规则是针对API Gateway的route(RESOURCE_MODE_ROUTE_ID)还是用户在Sentinel中定义的API分组(RESOURCE_MODE_CUSTOM_API_NAME)默认是route。grade限流指标维度同限流规则的grade字段。count限流阈值intervalSec统计时间窗口单位是秒默认是1秒。controlBehavior流量整形的控制效果同限流规则的controlBehavior字段目前支持快速失败和匀速排队两种模式默认是快速失败。burst应对突发请求时额外允许的请求数目。maxQueueingTimeoutMs匀速排队模式下的最长排队时间单位是毫秒仅在匀速排队模式下生效。paramItem参数限流配置。若不提供则代表不针对参数进行限流该网关规则将会被转换成普通流控规则否则会转换成热点规则。其中的字段 parseStrategy从请求中提取参数的策略目前支持提取来源IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意Header(PARAM_PARSE_STRATEGY_HEADER)和任意URL参数(PARAM_PARSE_STRATEGY_URL_PARAM)四种模式。fieldName若提取策略选择Header模式或URL参数模式则需要指定对应的header名称或URL参数名称。pattern参数值的匹配模式只有匹配该模式的请求属性值会纳入统计和流控若为空则统计该请求属性的所有值。(1.6.2版本开始支持)matchStrategy参数值的匹配策略目前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2版本开始支持) 用户可以通过GatewayRuleManager.loadRules(rules)手动加载网关规则或通过GatewayRuleManager.register2Property(property)注册动态规则源动态推送(推荐方式)。 参考文章 SpringCloud GatewaySpringCloud Gateway 内置的过滤器工厂SpringCloud Gateway
http://www.ho-use.cn/article/10823175.html

相关文章:

  • 西宁知名网站设计公司华为荣耀手机最新款
  • 北京建设职工大学网站wordpress自定义页面宽度
  • 网站整体建设方案设计百度网站认证
  • 宣城网站seo诊断宁波网站建设官网
  • 平面设计跟网站建设产品推广方案范例
  • 网站可以更更换空间吗网页美工培训班
  • 圣诞网站源码上海有什么seo公司
  • 贸易公司如何做英文网站零售户订烟电商网站
  • 长沙网站制作哪里好免费咨询合同范本
  • 建个人网站赚钱多吗长沙新媒体运营公司
  • 如何衡量一个网站的价值网站策划书是什么
  • 宜宾网站建设费用制作简单的网页代码
  • 看电视剧免费的网站关于网站设计的价格
  • 网站开发按工时收费wordpress网站搬迁
  • 腾讯视频网站建设维护wordpress婚庆主题公园
  • 青岛网站制作方案j2ee 网站开发
  • 张家港网站建设门店金融app开发
  • 100m做电影网站广州网站建设有哪些公司
  • 利用ps制作网站的设计乐陵市seo关键词优化
  • 做任务赚q红包的网站外包程序员的出路
  • 网站建设的前期投入wordpress 图片相册
  • 网站怎么做才有百度权重免费承接网站建设
  • 江华县网站开发科技布沙发好还是布艺沙发好
  • 成都市住房和城乡建设局官方网站公司怎么建立自己的网站
  • 网站开发方式有用python做网站怎么赚钱
  • 电子商务网站建设与管理a浏阳做网站的公司价格
  • 网站推广策划思维导图网站建设需要提供的资料
  • 在家做十字绣兼职网站百度企业号
  • 网站设计是怎么设计的适合写个人博客的平台
  • html简单网站成品免费wordpress 百度云视频