好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

/**

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

  * @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<String> 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<String, Collection<String>> 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<String, Collection<String>> queries) {

         // 叶子节点

         if (!jsonNode.isContainerNode()) {

             if (jsonNode.isNull()) {

                 return ;

             }

             Collection<String> values = queries.get(path);

             if ( null == values) {

                 values = new ArrayList<>();

                 queries.put(path, values);

             }

             values.add(jsonNode.asText());

             return ;

         }

         // 数组节点

         if (jsonNode.isArray()) {

             Iterator<JsonNode> it = jsonNode.elements();

             while (it.hasNext()) {

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

             }

         } else {

             Iterator<Map.Entry<String, JsonNode>> it;

             it = jsonNode.fields();

             while (it.hasNext()) {

                 Map.Entry<String, JsonNode> 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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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.net.HdhCmsTestprotocol.http.HttpURLConnection$StreamingOutputStream.write(HttpURLConnection.java: 3574 ) ~[na: 1.8 .0_212]

     at sun.net.HdhCmsTestprotocol.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(RetryableFeignLoadBalancer.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.netflix.client.AbstractLoadBalancerAwareClient$ 1 .call(AbstractLoadBalancerAwareClient.java: 104 ) ~[ribbon-loadbalancer- 2.3 . 0 .jar!/: 2.3 . 0 ]

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

     at com.netflix.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.netflix.loadbalancer.reactive.LoadBalancerCommand$ 1 .call(LoadBalancerCommand.java: 185 ) ~[ribbon-loadbalancer- 2.3 . 0 .jar!/: 2.3 . 0 ]

     at com.netflix.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(ScalarSynchronousObservable.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就跳过

解决方式:更改复制逻辑

?

1

2

3

4

5

6

7

8

9

while (headerNames.hasMoreElements()) {

                String name = headerNames.nextElement();

                // 跳过 content-length

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

                    continue ;

                }

                String values = request.getHeader(name);

                template.header(name, values);

            }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/zhuwei_clark/article/details/108467024

查看更多关于openFeign服务之间调用保持请求头信息处理方式的详细内容...

  阅读:15次