OpenFeign get请求传递参数异常

文摘   2023-12-11 14:30   江苏  
  1. 前置

  2. 为了简化对外部服务的远程调用,本人使用了openfeign,关于如何使用,前面我写了《Feign的一小步,我的一大步》和《Spring OpenFeign动态URL实战》二篇,阁下若有时间,不妨浏览一下,这样故事比较完整。

  3. 背景

    一直运行良好的程序,突然有同学给找到我反馈,通过走我的服务调用高德‘驾车路径规划’接口和直联高德调用同一接口返回结果不一致,作为程序员,第一反应是当然是让对方确认参数是不是都一致,对方这时候甩了证据过来,直接将我一军,这样我不得不出手了,有问题解决问题……

  4. 质疑

    首先从同学那里拿到原始请求参数,自己先定位看看是否能复现,这里得知同学调用传了一个非必填的参数(途经点):

    # 途径点mid_posi= [        [120.75994045, 30.74934149],        [120.757983398438, 30.749307996962],        [120.752908799914, 30.744759657119],        [120.752017686632, 30.743729926216],        [120.751150444879, 30.741030544705],        [120.75113207, 30.74087210],    ]r = requests.get(    url=url,    params={        "origin": start_posi,        "destination": end_posi,        "strategy": 2,        "waypoints": mid_posi,        "extensions": "all",        "show_fields": "tmcs,navi,polyline",        "fixed": "true",    },)



    初步怀疑是参数没有按接口文档的给的方式出入导致,于是我自己拼好请求之后试了一下得到如下结果:


    看样子这口锅不背是不行了!问题倒是复现了,好在以前的代码加了日志(这里省去了不少时间,在我看来日志可以说是程序员的拐杖),可以直接看到应用日志输出调用高德服务前拼接的完整请求和直连拼接的一样,该如何解释呢?再往下没有应用代码会改变相关参数直接就到框架底层代码,把请求发出去然后拿结果。这个时候灵机一动,找高德开工单问一下客服,也许有答案


    对方这时候估计跟我一样,先怀疑客户端用户自身错了,直接给了个貌似正确的答案,我一边转给我的下游试图解释,一边怀疑这些请求基本都是同一时间触发,短时间路况不会发生太大的变化,所以发起第二击:


    对方的心路历程可以说和我一毛一样,甩不掉了才玩儿真的,所以让我提供请求串,他们想要眼见为实,但这里由于我的服务是需要拨VPN才能内网访问,所以我的服务对高德同学来说其实是无法访问的,于是我转变思路想让对方从日志来分析原因,但这个前提是需要我提供gisd


    一开始也不知道问题会这么大,没有在请求中放也没有从响应中解析,这玩意儿突然让我提供,自然是有点过分的。对方抱着客户问题不能不解决的态度,以经验之谈给我回复可能是途经点有问题,但我自然是不承认

  5. 固定证据

    这个问题在双方太极之下没有定位根因,我在想是否还有比日志更具有说明力的证据证明调用前的情况,准备用代码实时debug,看看高德服务响应是啥……


    一行一行调试,结果还是跟线上一样!由于对方是技术,我想这些够说明问题了吧,再次联系对方,我将debug用的测试key给对方总能排查了吧,结果对方一口咬死,非我提供gsid才行


    看样子是绕不过了,现在问题变成一定要有gsid,如何获取呢?高德客服说在Response Header中,但我的代码是用String来接收高德Response,该如何是好呢?

    @FeignClient(name = "proxyServiceFeign")public interface ProxyServiceFeign {    /**     * post     * @param uri uri     */    @RequestLine("POST")    String post(URI uri);
    /**      * 高德现在请求都是get请求,我们现在调用都是从这里出去 * @param uri uri */ @RequestLine("GET") String get(URI uri);}



    一个String肯定是无法取到gsid,这里要先改一下代码,用Feign包下的Response来接收:

    原来String代表的结果需要从body中获取,gsid就可以从Response Header中解析出来:

    Response resp = proxyServiceFeign.get(uri);String body = resp.body().toString();// 获取gisdString gsid = resp.header("gsid")


    将gisd给对方后,最终确定发生问题的原因就是给定的途径点参数异常:




    发起调用前的n个途径点对方收到后被拆开了,这肯定就是Feign的杰作了!并非张开就来,有理有据

  6. 理解

    再次一行行debug,揭开了本次事故的神秘面纱,说feign全责一点不为过,举证如下:

    如何解决呢?我这边是底层框架,无法改动,高德那边处理一下也不是不可以,但高德技术从职业素养出发,委(yi)婉(zheng)(yan)(ci)——no way


  7. 解决

    既然依靠别人不行,只好自己上了。提issue明显时间上来不及,feign的底层我又改不了,但用不用的决定权在我手里,所以决定换其它网络请求工具先试一下:

    URI uri = URI.create("url"); // 放弃feign/*Response resp = proxyServiceFeign.get(uri);String body = resp.body().toString();*///  改为其它请求框架HttpResponse resp = HttpRequest.get(uri.toString()).execute();String body = resp.body();

    再次运行代码查看结果,发现与直连高德API响应一致,至此问题得以解决

  8. 收获

    我理解问题导致的原因、理解客服回复的拒绝升版、理解高德同学最初遇到问题跟我一样的反应。回头一想,其实本质还是自己的问题,没有正视它、直面它,试图躲避,这样不但解决不了问题,还可能浪费了团队的时间、影响了其它同学对你的看法。最开始定位出来我回复下游同学,是框架的因素无法改动,都以为无解的时候,大脑突然反应过来是不是可以换请求组件,本次除了解决问题,这是最大的收获。感谢反馈问题的同学、感谢高德客服的拒绝


    看到的同学觉得有用,点赞、关注、转发搞一个阔以不

晚霞程序员
一位需要不断学习的30+程序员……