微服务实战系列之Filter

前言

Filter,又名过滤器,当然不是我们日常中见到的,诸如此类构件:
在这里插入图片描述

而应该是微服务中常使用的,诸如此类(图片来自官网,点击可查看原图):

在这里插入图片描述
一般用于字符编码转换,日志处理等场景。而我们今天提到的Filter是基于springcloud gateway而言的。


一、Gateway Filter

1. 按生命周期划分

通过springcloud gateway的工作原理图,我们可以发现,过滤器在数据的请求和返回的过程中发挥它应有的作用。此类过滤器生命周期有两类:

过滤器阶段过滤器作用
Pre-req业务逻辑请求前(pre-request),完成相关操作
Post-req业务逻辑请求后(post-request),完成相关操作

2. 按职责范围划分

过滤器名称过滤器简介
GateWayFilter单一过滤器,即仅可完成单一功能的Filter,一般可建多个
GlobalFilter全局过滤器,可完成所有路由功能的Filter,一般只建1个

其他内容可参考官网,这里不再赘述。如需请速戳:springcloud gateway

当然不管是什么生命周期,还是什么职责范围,过滤器都会按照指定的路由执行,否则那不乱成一锅粥了。

因此,每个过滤器都应指定一个顺序Order值。

二、Gateway Filter Order

一句话总结:Order值越小,优先级越高,执行越靠前。

以下是springcloud gateway filter中的order定义:

public interface Ordered {

	/**
	 * Useful constant for the highest precedence value.
	 * @see java.lang.Integer#MIN_VALUE
	 */
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;

	/**
	 * Useful constant for the lowest precedence value.
	 * @see java.lang.Integer#MAX_VALUE
	 */
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;


	/**
	 * Get the order value of this object.
	 * <p>Higher values are interpreted as lower priority. As a consequence,
	 * the object with the lowest value has the highest priority (somewhat
	 * analogous to Servlet {@code load-on-startup} values).
	 * <p>Same order values will result in arbitrary sort positions for the
	 * affected objects.
	 * @return the order value
	 * @see #HIGHEST_PRECEDENCE
	 * @see #LOWEST_PRECEDENCE
	 */
	int getOrder();

}

而我们在使用的过程中,一般这样定义顺序:

@Component
public class TestGlobalFilter implements GlobalFilter, Ordered {
 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange);
    }
 
    @Override
    public int getOrder() {
        return 123;
    }
}

三、问题案例

因为我们在项目开发过程中, 为完成某些特定功能,会经常使用过滤器,所以难免遇到一些问题。而今天博主重点介绍其中的一个问题:请求体丢失,即只能消费一次的问题。

废话无需多言,直接参考以下代码,即可满足你的需要:

1. 缓存requestbody

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 定义一个全局过滤器,实现requestbody缓存
 * @date 2024/01/07 09:06
 */
@Component
public class ReqGlobalFilter implements Ordered, GlobalFilter {

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		if (exchange.getRequest().getHeaders().getContentType() == null) {
			return chain.filter(exchange);
		} else {
			return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
				DataBufferUtils.retain(dataBuffer);
				Flux<DataBuffer> cachedFlux = Flux
						.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
				ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {

					@Override
					public Flux<DataBuffer> getBody() {
						return cachedFlux;
					}
				};
				return chain.filter(exchange.mutate().request(mutatedRequest).build());
			});
		}
	}

	@Override
	public int getOrder() {
		return -10000;//也可设置为最高优先级
	}
}

2. 获取requestbody

在其他过滤器中,引用以下代码,实现requestbody获取:

 private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest)
 {
        // 获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        AtomicReference<String> bodyRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyRef.set(charBuffer.toString());
        });
        return bodyRef.get();
 }

结语

Filter是完成业务逻辑前或后应有操作的必要环节,也是实现统一服务的典型武器,所以我们应该了解它、学习它、掌握它。

好了,今日话题到此为止,下一篇是啥,继续期待!


历史回顾


在这里插入图片描述

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
SpringCloudAlibaba是一个基于SpringCloud的微服务开发框架,其包含了多个组件,包括服务注册与发现(Nacos)、服务调用(Feign和RestTemplate)、熔断器(Sentinel)等,这些组件的整合使得微服务开发变得更加高效和灵活。 SpringCloudAlibaba微服务的原理是通过服务注册与发现,服务调用和负载均衡、断路器等多个功能实现了分布式系统的管理和连接。在SpringCloudAlibaba中,使用Nacos作为服务注册和发现中心,将每个微服务注册到Nacos中。服务提供方在注册到Nacos之后,服务消费方可以通过Nacos利用Feign或者RestTemplate来发现并调用这些服务。同时,Sentinel也可以用来实现熔断机制,防止因为某个服务出现问题而影响整个系统的运行。 SpringCloudAlibaba的实战也十分简单,首先需要引入相关的依赖。例如,在使用Nacos作为服务注册和发现中心时,可以在pom.xml中添加以下相关依赖: <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.1.RELEASE</version> </dependency> 然后在启动类上添加@EnableDiscoveryClient注解,即可让该微服务进行注册。接下来,就可以使用Feign或者RestTemplate来实现服务的调用,例如: @FeignClient(value ="user-service") public interface UserServiceClient { @GetMapping("/user/{id}") User getUserById(@PathVariable("id") int id); } 最后,使用Sentinel实现熔断机制也十分简单。只需要在pom.xml中添加相关依赖,然后添加相应的配置即可。例如: spring.cloud.sentinel.datasource.file.path: classpath:/META-INF/spring/cloud/nacos- flow Rule.json spring.cloud.sentinel.filter.order: -1 其中,nacos-flow Rule.json是一个配置文件,存放了所有需要被熔断的服务和其对应的规则。 综上所述,SpringCloudAlibaba作为一个高效灵活的微服务开发框架,通过多个功能组件的整合,实现了分布式系统的管理和连接。其实战也十分简单,只需要引入相关依赖并添加相应配置即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值