openFeign服务之间调用保持请求头信息处理方式

网友投稿 1070 2023-01-05

openFeign服务之间调用保持请求头信息处理方式

openFeign服务之间调用保持请求头信息处理方式

openFeign服务间调用保持请求头信息处理

1、注意特殊情况,在定时任务或者内部之间调用,没有request的时候,不要处理直接返回。

2、在GET请求,参数确放在Body里面传递的情况,restTemplate是不认识的,所以这里要转化下处理,然后清空body数据

3、在请求过程中如果出现java.io.IOException: too many bytes written异常,请参考保持请求头造成请求头和content-length不一致

/**

* 解决服务调用丢失请求头的问题

* @author 大仙

*

*/

@Component

public class FeignConfiguration implements RequestInterceptor{

private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired

private ObjectMapper objectMapper;

@Override

public void apply(RequestTemplate template) {

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder

.getRequestAttributes();

// 注意: RequestContextHolder依赖于 ThreadLocal, 所以在hystrix的隔离策略为THREAD、MQ的消费者、定时任务调用feignClient时,此处应为null

if (attributes == null) {

return;

}

HttpServletRequest request = attributes.getRequest();

Enumeration headerNames = request.getHeaderNames();

if (headerNames != null) {

while (headerNames.hasMoreElements()) {

String name = headerNames.nextElement();

String values = request.getHeader(name);

template.header(name, values);

}

}

logger.info("保持请求头");

//feign 不支持 GET 方法传 POJO, json body转query

if (template.method().equals("GET") && template.requestBody().asBytes() != null) {

try {

JsonNode jsonNode = objectMapper.readTree(template.requestBody().asBytes());

Request.Body.empty();

Map> queries = new HashMap<>();

buildQuery(jsonNode, "", queries);

template.queries(queries);

} catch (IOException e) {

//提示:根据实践项目情况处理此处异常,这里不做扩展。

e.printStackTrace();

}

}

}

/**

* 改造

* @param jsonNode

* @param path

* @param queries

*/

private void buildQuery(JsonNode jsonNode, String path, Map> queries) {

// 叶子节点

if (!jsonNode.isContainerNode()) {

if (jsonNode.isNull()) {

return;

}

Collection values = queries.get(path);

if (null == values) {

values = new ArrayList<>();

queries.put(path, values);

}

values.add(jsonNode.asText());

return;

}

// 数组节点

if (jsonNode.isArray()) {

Iterator it = jsonNode.elements();

while (it.hasNext()) {

buildQuery(it.next(), path, queries);

}

} else {

Iterator> it;

it = jsonNode.fields();

while (it.hasNext()) {

Map.Entry entry = it.next();

if (StringUtils.hasText(path)) {

buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);

} else {

// 根节点

buildQuery(entry.getValue(), entry.getKey(), queries);

}

}

}

}

}

保持请求头造成请求头和content-length不一致

Request processin g failed; nested exception is feign.RetryableException: too many bytes written

2020-09-08 14:07:14.718 ERROR 16146 --- [io-12000-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processin

g failed; nested exception is feign.RetryableException: too many bytes written executing POST http://pay/wx/create] with root cause

java.io.IOException: too many bytes written

at sun-.protocol.http.HttpURLConnection$StreamingOutputStream.write(HttpURLConnection.java:3574) ~[na:1.8.0_212]

at sun-.protocol.http.HttpURLConnection$StreamingOutputStream.write(HttpURLConnection.java:3565) ~[na:1.8.0_212]

at feign.Client$Default.convertAndSend(Client.java:181) ~[feign-core-10.4.0.jar!/:na]

at feign.Client$Default.execute(Client.java:77) ~[feign-core-10.4.0.jar!/:na]

at org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer$1.doWithRetry(RetryableFeignLoadBalancer.java:114) ~[spring-cloud-openfeign-core-2.1.5.RELEASE.jar!/:2.1.5.RELEASE]

at org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer$1.doWithRetry(RetryableFeignLoadBalapyrQlncer.java:94) ~[spring-cloud-openfeign-core-2.1.5.RELEASE.jar!/:2.1.5.RELEASE]

at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287) ~[spring-retry-1.2.5.RELEASE.jar!/:na]

at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:180) ~[spring-retry-1.2.5.RELEASE.jar!/:na]

at org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer.execute(RetryableFeignLoadBalancer.java:94) ~[spring-cloud-openfeign-core-2.1.5.RELEASE.jar!/:2.1.5.RELEASE]

at org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer.execute(RetryableFeignLoadBalancer.java:54) ~[spring-cloud-openfeign-core-2.1.5.RELEASE.jar!/:2.1.5.RELEASE]

at com-flix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:104) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0]

at com-flix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0]

at com-flix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0]

at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144) ~[rxjava-1.3.8.jar!/:1.3.8]

at com-flix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0]

at com-flix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0]

at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.Subscriber.setProducer(Subscriber.java:209) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarShttp://ynchronousObservable.java:138) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.3.8.jar!/:1.3.8]

at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.3.8.jar!/:1.3.8

原因是:body是跟Content-Length 有关系

复制的时候是所有头都复制的,可能导致Content-length长度跟body不一致. 所以只需要判断如果是Content-length就跳过

解决方式:更改复制逻辑

while (headerNames.hasMoreElements()) {

String name = headerNames.nextElement();

// 跳过 content-length

if (name.equals("content-length")){

continue;

}

String values = request.getHeader(name);

template.header(name, values);

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:物联网移动应用开发安卓(物联网移动应用开发安卓版)
下一篇:塔城企业app开发制作(塔城企业app开发制作公司)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~