前言
在微服务架构下,业务系统的功能是由大量的微服务组成,例如:一个电商购物平台下单环节就需要订单服务、库存服务、短信服务和物流服务等逐级调用。但是每个服务是由不同的研发团队负责的,部署在成百上千台服务器上。
在这么复杂的数据传递过程中最怕发生系统故障,因为很难去快速定位到问题。所以就要引入服务间的链路追踪。
在技术调研过程中大致有以下几种方案:
1、基于 Sleuth + Zipkin 方案
2、通过 SkyWalking 实施链路追踪
3、自建链路追踪
这里选择了自建链路追踪的方式,至于为啥不用1、2 就不多讲了,这次的坑是在自建过程中采用的是通过 OpenFeign 来作为服务间远程数据交换,通过在HTTP请求的Header 总增加TraceId 参数来作为服务间的链路追踪。
OpenFeign调用传递Header方案
import feign.RequestInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
@Configuration
@Slf4j
public class FeignClientConfig {
@Bean
public RequestInterceptor headerInterceptor() {
return template -> {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (null != attributes) {
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
template.header(name, values);
}
}
}
};
}
}
问题
上面说到有些服务是其他团队负责研发的,有自己的网关、鉴权等。那么在通过OpenFeign调用的时候出现了返回乱码,具体如下:
{
"code": "200",
"message": "请求成功",
"result": "\u0015\u0013\u0001\u0000??Y[???3Y????\u000E??H?GHВ?????Y\u0018H??%?@?@?m??\u001BL%???\u0019u\u000Ev-+??8&t???\t<?\u001EW0002?\t?eZ?\u0004?Xk,??lt5\u0010\u0004V\u0000*???D?*?0??\u0000[???\u0005????y???\u001B\b?,r?C\u0012\u000G?3?m??<?v\"?]?m??`??p1^?J??h\u00M#?$\u001F?<?\r?Hf[?\u0002"
}
比较奇怪的是只有个别服务是有问题的,也没有办法去看对方的代码。
原因分析
最终定位到的原因是Request 的Header 中设置Accept-Encoding:gzip, deflate, br;的问题,如果加上就会返回乱码。
最开始的时候以为是编码的问题,所以小编尝试了各种编码,但是始终无法解决问题。
后来想到 Accept-Encoding 不参与数据传递就OK啦!
增加代码:
总结:
之所以添加:"Accept-Encoding" = "gzip, deflate, br"
是因为,浏览器对于从服务器中返回的对应的gzip压缩的网页,会自动解压缩,所以Request的时候,添加对应的Header信息,表示接收压缩后的数据。
而此代码中,如果也添加此头信息,结果就是,返回的压缩后的数据,由于没有解码,客户端将压缩后的数据当做普通的html文本来处理,当前显示出来的内容,是乱码了。
小编选择的是排除掉 Accept-Encoding ,当然也可以只去掉 gzip参数。