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

ASP.NET2.0网站开发全程解析河南省郑州市金水区

ASP.NET2.0网站开发全程解析,河南省郑州市金水区,学风建设网站的优势,个人网页网站制作模板目录 1. 过滤器的作用 2. Spring Cloud Gateway 过滤器的类型 2.1 内置过滤器 2.1.1 AddResponseHeader 2.1.2 AddRequestHeader 2.1.3 PrefixPath 2.1.4 RequestRateLimiter 2.1.5 Retry 2.2 自定义过滤器 1. 过滤器的作用 过滤器通常用于拦截、处理或修改数据流和事…

目录

1. 过滤器的作用

2. Spring Cloud Gateway 过滤器的类型

2.1 内置过滤器

2.1.1 AddResponseHeader

2.1.2 AddRequestHeader

2.1.3 PrefixPath

2.1.4 RequestRateLimiter

2.1.5 Retry

2.2 自定义过滤器


1. 过滤器的作用

过滤器通常用于拦截、处理或修改数据流和事件流,在数据流中执行特定的操作或转换。

过滤器主要在以下几个方面发挥作用:

  1. 功能扩展和定制:过滤器允许您自定义和扩展网关的功能,以满足特定需求,如请求和响应的修改、路由规则的动态配置等。

  2. 数据校验和过滤:通过过滤器,您可以检查、验证和过滤传入或传出的数据,确保请求和响应的合法性和一致性。

  3. 安全保护:过滤器可以用于实施安全策略,如认证、授权、防止攻击等,以增强网关的安全性。

  4. 性能优化:通过过滤器,您可以对请求和响应进行性能优化,如缓存、压缩、请求路由的智能选择,以提高网关的性能。

  5. 统一处理:过滤器允许您在网关层面执行共享的处理逻辑,如日志记录、监控、审计等,以确保整个微服务体系的一致性和可维护性。

  6. 逻辑复用:通过过滤器,您可以将一些常见的操作抽象出来,以实现逻辑的复用,减少重复代码和维护工作。

2. Spring Cloud Gateway 过滤器的类型

Spring Cloud Gateway 过滤器可以分为两大类:

1. 内置过滤器

  • 局部的内置过滤器
  • 全局的内置过滤器

2. 自定义过滤器

2.1 内置过滤器

内置过滤器常见的有以下几种:

  1. AddResponseHeader
  2. AddRequestHeader
  3. AddRequestParameter(和 AddRequestHeader 相似)
  4. PrefixPath
  5. RequestRateLimiter
  6. Retry

Spring Cloud Gateway 过滤器常见有这么几种,实际上它有30多种,可以借助官方文档加以了解:Spring Cloud Gateway

过滤器又分为前置过滤器后置过滤器

在目标方法返回之前执行的过滤器就叫做前置过滤器(AddRequestXXX),在目标方法返回之后执行的过滤器就叫做后置过滤器。(AddResponseXXX)

前置工作:准备 user-service 和 order-service 两个模块,并且配置好 naocs 连接信息。

① user-service:创建一个 controller

@RestController
@RequestMapping("/user")
public class UserController {@Autowired  // 获取动态端口private ServletWebServerApplicationContext context;@RequestMapping("/getname")public String getName() {return context.getWebServer().getPort() +"--UserService:name=java-"+new Random().nextInt(100);}
}
server.port=0
spring.application.name=user-service-gateway
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos

② order-service:创建一个 controller

@RestController
@RequestMapping("/order")
public class OrderController {@RequestMapping("/getcount")public int getCount() {return new Random().nextInt(1000);}
}
server.port=0
spring.application.name=order-service-gateway
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos

2.1.1 AddResponseHeader

spring:cloud:nacos: # 配置注册中心discovery:server-addr: localhost:8848username: nacospassword: nacosgateway: # 配置网关routes:- id: userserviceuri: lb://user-service-gateway   # loadbalancerpredicates:- Path=/user/**filters:- AddResponseHeader=My-Resp-Header, www.baidu
server:port: 10086

在配置过滤器之前,我在网关服务中引入 Nacos 和 LoadBalancer 之后,使用10086 端口去访问userservice服务时,查看对应的响应头:

配置了 AddResponseHeader 过滤器之后,再去访问userservice服务时,查看对应的响应头:

上述的设置,设置的是局部过滤器,如果此时在网关服务中再新增一组 id (如下),此时再去访问order-service服务时,响应头中就不会包含 My-Resp-Header 这个标头了。

spring:cloud:gateway: # 配置网关routes:- id: userservice  # 用户服务uri: lb://user-service-gateway   # loadbalancerpredicates:- Path=/user/**filters:- AddResponseHeader=My-Resp-Header, www.baidu- id: orderservice  # 订单服务uri: lb://order-service-gatewaypredicates:- Path=/order/**

此时还想访问 orderservice 服务时,也在响应头中看到对应的标头,要么就把 filters 照搬到下面,但是这样做,代码就不具备维护性了,发生修改的时候,这将会是一个体力活;要么就使用全局过滤器。

全局过滤器的配置

spring:cloud:gateway: # 配置网关routes:- id: userservice  # 用户服务uri: lb://user-service-gateway   # loadbalancerpredicates:- Path=/user/**filters:- AddResponseHeader=My-Resp-Header, www.baidu- id: orderservice  # 订单服务uri: lb://order-service-gatewaypredicates:- Path=/order/**default-filters:  # 全局过滤器- AddResponseHeader=MyApplication-Resp-Header, gateway.org

2.1.2 AddRequestHeader

spring:cloud:nacos: # 配置注册中心discovery:server-addr: localhost:8848username: nacospassword: nacosgateway: # 配置网关routes:- id: userservice  # 用户服务uri: lb://user-service-gateway   # loadbalancerpredicates:- Path=/user/**filters:- AddResponseHeader=My-Resp-Header, www.baidudefault-filters:- AddRequestHeader=My-Req-Marking, www.baidu

如何拿到前置过滤器,可以在 userservice 服务里边写一个打印请求头的 controller:

@RequestMapping("/print-header")
public void printHeader(HttpServletRequest request) {Enumeration<String> headers = request.getHeaderNames();while(headers.hasMoreElements()) {String key = headers.nextElement();String value = request.getHeader(key);System.out.println(key +": " + value);}
}

此时运行userservice 和 gateway,去反问 print-header 接口, 查看 userservice 的控制台:

2.1.3 PrefixPath

spring:cloud:nacos: # 配置注册中心discovery:server-addr: localhost:8848username: nacospassword: nacosgateway: # 配置网关routes:- id: userserviceuri: lb://user-service-gatewaypredicates:- Path=/user/**filters:- PrefixPath=/v2

假设此时 userservice 中的 UserController 升级为了 v2 版本,但是我的接口 /user/** 已经 对外公布了,此时还想让 localhost:10086/user/getname 访问到 v2 版本的 controller,肯定是不允许再修改后端的接口了,也不能让前端跟着改,使用 PrefixPath 就可以很好的调整。

第一版代码:

@RestController
@RequestMapping("/user")
public class UserController {@Autowired  // 获取动态端口private ServletWebServerApplicationContext context;@RequestMapping("/getname")public String getName() {return context.getWebServer().getPort() +"--UserService:name=java-"+new Random().nextInt(100);}
}

第二版代码: 

@RequestMapping("/v2/user")
@RestController
public class UserControllerV2 {@Autowired  // 获取动态端口private ServletWebServerApplicationContext context;@RequestMapping("/getname")public String getName() {return context.getWebServer().getPort() +"--V2:UserService:name=java-"+new Random().nextInt(10);}
}

当我们配置了 PrefixPath 之后,再使用原来的 localhost:10086/user/getname 去访问服务的时候,就可以正常的访问到 v2 版本的 controller 了,无需再去修改前后端接口。

2.1.4 RequestRateLimiter

这是 Spring Cloud Gateway 内置的网关限流过滤器,它使用了令牌桶的限流算法。

令牌桶限流算法:令牌桶限流算法通过固定速率生成令牌放入桶中,桶满则丢弃新令牌。请求到来时消耗令牌进行处理,桶内无令牌则等待或丢弃请求,从而平滑流量,防止网络拥堵。

Spring Cloud  Gateway 当前版本支持和 Redis 一起实现限流功能,Spring Cloud Gateway 选择 Redis 作为限流方案的一个重要支撑是因为 Redis 的一些特性可以很好地满足限流中对于性能、一致性和分布式处理的要求。

  1. 分布式环境:在微服务架构中,服务实例往往是分布式部署的,Redis 由于其天然的分布式特性,能够确保在不同的服务实例之间共享限流的状态,实现全局限流。

  2. 性能:Redis 是一个高性能的内存数据库,它的读写速度非常快,可以达到每秒数十万次的读写请求。这种性能上的优势使得 Redis 成为实现限流中维护和检查速率限制状态的理想选择。

  3. 原子操作:Redis 支持多种原子操作,这对于计数器来说非常重要。例如,使用 INCRDECR 命令递增或递减计数器,可以保证即使在高并发的情况下,计数器的值也是准确的。

  4. 过期策略:Redis 允许为数据设置生存时间(TTL),这对于限流算法中的时间窗口非常有用。例如,在固定时间窗口算法中,可以设置令牌或计数器在特定时间后自动过期。

它的实现步骤总共分为三步:

  1. 添加 Redis 框架依赖
  2. 创建限流规则
  3. 配置限流过滤器

a.添加 Redis 框架依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

注意事项:Redis版本太低,此功能设置会无效,建议使用 Redis 版本 5.x+。

b.创建限流规则

限流规则,既可以针对某一个 IP 做限流,也可以针对 URL 进行限流(所有的 IP 访问 URL 都会限流)

创建一个类,根据IP进行限流:

@Component
public class IpAddressKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}
}

创建一个类,根据URL进行限流:

@Component
public class UrlKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {// 获取请求的URI路径作为限流的keyString path = exchange.getRequest().getURI().getPath();return Mono.just(path);}
}

c.设置限流过滤器

spring:cloud:nacos: # 配置注册中心discovery:server-addr: localhost:8848username: nacospassword: nacosgateway: # 配置网关routes:- id: userserviceuri: lb://user-service-gatewaypredicates:- Path=/user/**filters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1  # 每秒请求数redis-rate-limiter.burstCapacity: 1  # 最大请求数key-resolver: "#{@ipAddressKeyResolver}"  # spEL表达式data:redis:host: 127.0.0.1port: 16379database: 0

注意,内置的限流过滤器 name 必须等于"RequestRateLimiter" ,其他参数的含义如下:

1. redis-rate-limiter.replenishRate:令牌填充速度(每秒允许请求数)

2. redis-rate-limiter.burstCapacity:令牌桶容量(最大令牌数)

3. key-resolver:根据哪个 key 进行限流,它的值是 spEL 表达式。

这三步完成之后,就表示每个 IP  每秒钟只能访问一次,如果刷新页面刷新的太快,就会出现如下页面:

2.1.5 Retry

在 OpenFeign 里面呢,也有个 Retry 超时重试,而且它还可以自定义重试规则,为什么 Gateway 还要有一个 Retry 呢 ?

OpenFeign里面的重试机制是服务调用层面的,它是用来帮助服务消费者处理调用远程服务时的问题的。而Spring Cloud Gateway的重试机制是在网关层面上,主要用于对所有通过网关的服务调用提供统一的重试策略,以处理上游服务可能出现的不稳定性(网络抖动)。两者虽都提供重试功能,但服务的层次不同,因此它们在微服务架构中各有其作用。

请求重试过滤器配置案例:

spring:cloud:nacos: # 配置注册中心discovery:server-addr: localhost:8848username: nacospassword: nacosgateway: # 配置网关routes:- id: userserviceuri: lb://user-service-gatewaypredicates:- Path=/user/**filters:- name: Retry  # 重试过滤器args:retries: 3statuses: GATEWAY_TIMEOUTmethods: GETseries: SERVER_ERRORbackoff:firstBackoff: 10ms  # 第一次重试间隔maxBackoff: 50ms  # 最大重试间隔factor: 2  # firstBack * (factor ^ n)   # 重试系数basedOnPreviousValue: false  # 基于上次重试时间加上重试系数来计算

注意,重试过滤器的 name 必须等于 "Retry" ,因为 "Retry" 就是内置重试过滤器的名字,改为其他框架就无法识别了;其他参数的含义如下:

1. retries:尝试的重试次数。

2. statuses:重试的HTTP状态码。取值参考:HttpStatus (Spring Framework 6.1.2 API)

3. methods:重试的HTTP方法。取值:GET(默认值),HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE。

4. series:要重试的一系列状态码。默认值是 SERVER_ERROR,值是 5,表示 5xx,( 5开头的状态码)。共有 5 个取值:

  • 1xx:INFORMATIONAL
  • 2xx:SUCCESSFUL
  • 3xx:REDIRECTION
  • 4xx:CLIENT_ERROR
  • 5xx:SERVER_ERROR

5. backoff:配置的重试策略。

  • firstBackoff:第一次的重试间隔
  • maxBackoff:最大重试间隔
  • factor:重试系数,firstBackoff *(factor ^ n),n= 1,2,3,4...
  • basedOnPreviousValue:默认关闭,如果设为 true,就表示基于上次的重试时间加上重试系数来计算,例如 firstBackoff 为 10,假设上一次重试是 10 * 2 ^ 1,那么下一次就不是 10 * 2 ^ 2,而是 20 * 2 ^ 2。

【案例演示】

在 userservice 服务中,写一个接口去触发 GATEWAY_TIMEOUT:

@RequestMapping("/504")
public void return504(HttpServletResponse response) {System.out.println("------- Do return504 method. ------");response.setStatus(504);
}

启动 userservice 模块和 gateway 模块,此时 userservice 服务自动注入到 nacos 中,使用原生服务接口访问:

原生服务接口:192.168.10.83:63129/user/504,触发 504 

此时查看控制台 :打印了一次

再使用 Gateway 网关去访问 userservice 服务, localhost:10086/user/504,触发 504

此时查看控制台:打印了 4 次(清除上面的打印后)

可见重试过滤器确实生效了。

【注意事项】

1. 此处的超时重试和 OpenFeign 里面的超时重试不太一样,这里设置重试 3 次,就是真的重试 3 次,加上触发重试的 1 次,总共就是打印 4 次,而 OpenFeign 里面的超时重试,重试次数的下标是从 1 开始的,所以在 OpenFeign 里面,这样设置,只会重试 2 次,打印 3 次。

2. 上面重试过滤器的配置,像 method、series 这种参数,它都是有默认值的,比如说 series 的默认值是 5 开头的状态码,那么即使我们不设置这个参数,当我们触发 5 开头的异常时,并且没有与其他设置的参数相悖的时候,也会触发超时重试功能。

2.2 自定义过滤器

代码案例:使用 Spring Cloud Gateway 提供的全局过滤器实现统一认证授权。

@Component
public class AuthFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange,   // 执行的事件GatewayFilterChain chain)     // 过滤器链{// 未登录判断逻辑,当参数中 username=admin && password=admin 继续执行,// 否则退出执行// 得到 Request 对象 (reactive web)ServerHttpRequest request = exchange.getRequest();// 得到 Response 对象 (reactive web)ServerHttpResponse response = exchange.getResponse();String username = request.getQueryParams().getFirst("username");String password = request.getQueryParams().getFirst("password");if (username != null && username.equals("admin")&& password != null && password.equals("admin")) {// 已经登录,执行下一步return chain.filter(exchange);} else {// 设置无权限 401response.setStatusCode(HttpStatus.UNAUTHORIZED);// 执行完成,不用继续执行后续流程了return response.setComplete();}}
}

在访问相对应服务的时候,可以先不加用户名密码试一次,它会触发 401,再加上 username=admin&password=admin,就可以正常访问到相应服务了。

当有多个过滤器时,我们还可以给过滤器指定它的执行顺序:

假如说,此时有两个过滤器,一个用来验证登录,一个用来验证是否有权限。那么这个时候,需要先验证登录,才会再去验证是否有权限。如何实现?

  1. 实现 Ordered 接口
  2. 重写 getOrder 方法
@Override
public int getOrder() {// 此值越小越先执行return 1;
}

http://www.dt0577.cn/news/18473.html

相关文章:

  • 温州做网店的网站百度客户端下载安装
  • 购物网站制作教程seo搜索规则
  • 合肥装饰公司做的好的网站seo排名优化排行
  • 广东深圳网站建设微信商城开发站长工具seo综合查询论坛
  • 海安做网站青岛seo网络推广
  • 网站开发好公司熊猫关键词工具官网
  • 遵义市住房和城乡建设局网站爱网站关键词查询工具
  • 视频作为网站背景关键词优化排名软件s
  • 一键网站制作app淘宝流量助手平台
  • 解放军工程建设协会网站百度推广怎么收费标准案例
  • 自建网站怎么做推广seo快速排名软件网址
  • 企业网站建设方案书前言郑州网站推广哪家专业
  • 石家庄小学网站建设cms建站
  • 可以做免费广告的网站网络营销策划方案格式
  • 历史上的今天 网站如何做最好的推广平台是什么软件
  • 莱芜区平台公司seo查询5118
  • 广州市政府门户网站建设的缺点哪里可以做
  • 学网站建设与管理有用吗网址查询网站
  • 响应式网站建站系统友链交易平台
  • 做传奇网站云服务器地域改选哪里网络热词2021
  • 新加坡网站建设公司seo优化是怎么回事呢
  • 网站的建设与推广百度人工客服在线咨询电话
  • 苏州网站建设兼职搜索广告和信息流广告区别
  • 天水做网站的qq群排名优化软件购买
  • 利用cms怎么做网站品牌网站建设制作
  • 做的好的网站着陆页公司推广策划方案
  • 网站如何做反链宁德市
  • 上海专业做网站公司报价保定网站建设报价
  • 石家庄市建设南大街小学网站网页制作代码大全
  • 做外贸需要做网站吗留手机号广告