博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud Gateway 拦截响应(数据截断问题)
阅读量:2216 次
发布时间:2019-05-07

本文共 3797 字,大约阅读时间需要 12 分钟。

最近因为上链路追踪后发现如果在服务层将异常拦截掉,在链路追踪界面上就不会显示异常链路信息,除了服务异常意外,系统的异常不会触发链路error,所以对服务层做了个变更,将所有未处理异常直接捕获后统一封装完抛出,这个时候就需要在网关层统一处理那么网关需要对响应数据进行拦截如果是 9999错误码,则封装后返回,如果是其它响应码或者其它数据直接返回。

起初写法测试后发现数据过长时被截断。

return super.writeWith(fluxBody.map(dataBuffer -> {		byte[] content = new byte[dataBuffer.readableByteCount()];		dataBuffer.read(content);	// 释放掉内存	DataBufferUtils.release(dataBuffer);	String str = new String(content, Charset.forName("UTF-8"));	originalResponse.getHeaders().setContentLength(str.getBytes().length);	log.error("gateway catch service exception error:"+ str);		JsonResult result = new JsonResult();	result.setCode(ErrorCode.SYS_EXCEPTION.getCode());	result.setMessage(ErrorCode.SYS_EXCEPTION.getMsg());		return bufferFactory.wrap(str.getBytes());}));

 

查询api后发现存在一个DataBufferFactory可以一次性join完所有数据后拼接就不会产生截断问题。

DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();

于是修改代码如下

package com.server.gateway.filters;import java.nio.charset.Charset;import java.util.concurrent.atomic.AtomicReference;import org.apache.http.protocol.HTTP;import org.reactivestreams.Publisher;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.DataBufferFactory;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.core.io.buffer.DefaultDataBufferFactory;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.http.server.reactive.ServerHttpResponseDecorator;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import com.framework.common.enums.ErrorCode;import com.framework.common.web.JsonResult;import lombok.extern.slf4j.Slf4j;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono; @Component@Slf4jpublic class WrapperResponseGlobalFilter implements GlobalFilter, Ordered{	@Override	public int getOrder() {		// -1 is response write filter, must be called before that		return -2;	}	@Override	public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponse originalResponse = exchange.getResponse(); DataBufferFactory bufferFactory = originalResponse.bufferFactory(); ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { @Override public Mono
writeWith(Publisher
body) { AtomicReference
bodyRef = new AtomicReference<>(); if (body instanceof Flux) { Flux
fluxBody = (Flux
) body; return super.writeWith(fluxBody.buffer().map(dataBuffers -> { DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); DataBuffer join = dataBufferFactory.join(dataBuffers); byte[] content = new byte[join.readableByteCount()]; join.read(content); // 释放掉内存 DataBufferUtils.release(join); String str = new String(content, Charset.forName("UTF-8")); originalResponse.getHeaders().setContentLength(str.getBytes().length); log.error("gateway catch service exception error:"+ str); JsonResult result = new JsonResult(); result.setCode(ErrorCode.SYS_EXCEPTION.getCode()); result.setMessage(ErrorCode.SYS_EXCEPTION.getMsg()); return bufferFactory.wrap(str.getBytes()); })); } // if body is not a flux. never got there. return super.writeWith(body); } }; // replace response with decorator return chain.filter(exchange.mutate().response(decoratedResponse).build()); }}

经过如上修改后链路追踪可以实现哪个服务出错就立马出现链路异常马上可以定位到哪个服务出现了未处理异常

 

转载地址:http://likfb.baihongyu.com/

你可能感兴趣的文章
分布式系统理论基础8:zookeeper分布式协调服务
查看>>
搞懂分布式技术1:分布式系统的一些基本概念
查看>>
搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法
查看>>
搞懂分布式技术3:初探分布式协调服务zookeeper
查看>>
搞懂分布式技术4:ZAB协议概述与选主流程详解
查看>>
搞懂分布式技术5:Zookeeper的配置与集群管理实战
查看>>
搞懂分布式技术6:Zookeeper典型应用场景及实践
查看>>
搞懂分布式技术10:LVS实现负载均衡的原理与实践
查看>>
搞懂分布式技术11:分布式session解决方案与一致性hash
查看>>
搞懂分布式技术12:分布式ID生成方案
查看>>
搞懂分布式技术13:缓存的那些事
查看>>
搞懂分布式技术14:Spring Boot使用注解集成Redis缓存
查看>>
搞懂分布式技术15:缓存更新的套路
查看>>
搞懂分布式技术16:浅谈分布式锁的几种方案
查看>>
搞懂分布式技术17:浅析分布式事务
查看>>
搞懂分布式技术18:分布式事务常用解决方案
查看>>
搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务
查看>>
搞懂分布式技术20:消息队列因何而生
查看>>
搞懂分布式技术21:浅谈分布式消息技术 Kafka
查看>>
后端技术杂谈1:搜索引擎基础倒排索引
查看>>