当SpringCloud中使用open feign调用其他服务时出现IO Exception too many bytes written的问题,
首先通过查看源码知道
HttpURLConnection#StreamingOutputStream
具体的报错地方:
@Override
public void write (byte[] b, int off, int len) throws IOException {
checkError();
written += len;
// 异常是由此处抛出的,主要是written的值大于期望的值。
if (expected != -1L && written > expected) {
out.close ();
throw new IOException ("too many bytes written");
}
out.write (b, off, len);
}
解决方案是实现RequestInterceptor接口,进行获取header的Content-Length,并特殊处理。
package com.example.integration.config;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* <p>
* feign透传header
* </p>
* @author bixuan
*/
@Configuration
public class FeignConfiguration implements RequestInterceptor {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
// 跳过 content-length,解决too many bites written的问题
if (name.equalsIgnoreCase("content-length")){
continue;
}
template.header(name, values);
}
logger.info("feign interceptor header:{}",template);
}
}
}
网友评论