一次错误排查过程记录
公司有一个Word转图片的服务器(一个C#写的,部署在WindowsServer上),因功能需要,需要我这边在springcloud微服务里通过HTTPclient的形式进行调用。过程大致如下
1.在微服务里进行异步http请求,三个参数;第一个为Word文档的下载地址,第二个为Word转图片服务器转成图片之后,把图片发送给我这边的微服务的请求路径,第三个为windowsServer确认是否收到的一个请求路径。
2.第一步请求之后,WindowsServer会回调微服务(就是第二个参数),将图片压缩包传给我,我在代码里进行解压,并上传,将每一张图片上传之后的URL返回给Windows端。
3.最后一步,Windows端简单确认。
经过编码之后,进行验证,问题如下。
1.Windows端回调的时候,请求路径之前的host和port如果是127.0.0.1:8080,这种指定的可以正常回调,但是请求公司域名的时候则会报过不了校验。
原因:公司的springcloud微服务网关通过域名访问时会对路径进行token验证,验证此路径是否为白名单(即不需要token也可以访问),
解决方式:在URL白名单里添加此路径即可
2.如果word的页数很多,Windows回调时经常报500,导致在第二步失败。接口调用被熔断器熔断了,一开始很自信的以为是文件服务器的问题,后来一步一步验证发现并不是。
原因:自己代码里做了3此无用操作,文件服务器接收MultipartFile类型,自己做的无用操作为,先从ZipEntry中getInputStream,,然后从这个流里面读,把这个流写到一个临时文件里去,再从这个文件里读流(看到这个代码我也是醉了,这不是SB嘛),所以打断点发现果然时间都浪费在这里了,80张图片完成这三次操作要15秒作用,而且每次读流懂事InputStream.read()这种方式,一个一个字节去读,太SB了。建议通过InputStream.read(byte[],int off,int len)这种方式读
解决方式:直接通过ZipEntry.getInputStream()得到输入流,用这个流直接去构造MultipartFile对象即可,果然这次回调不会再报超时
3.图片最终入库的顺序混乱,虽然每一页都是图片,但是入库的图片不是按照顺序排的,一开始以为Windows那边传过来的zip压缩包里面的图片顺序就是乱的,但是把压缩包打开之后发现里面是按照顺讯排列的,Windows端的同学还贴心的在每张图片加了顺讯前缀,类似于1_ahdfahd.png,2_fahdfald.png这种,那肯定就是我这边的问题
原因:ZipInputStream.getNextEntry的时候获得顺序就是错乱的,我初步猜测可能网络传输时,每个图片大小不一样,导致传输速度不一样,可能第一张图片传输的比较慢,可能第N张图片都传完了,第一张图片才传完,所以造成了顺序错乱。也可能不是,因为我看本地临时的接收的压缩包里面的图片顺序是正常的,哪位大神知道原因可以留言告诉下,多谢。
解决方式:很简单,在批量上传之前,根据图片的前缀排序即可。
4.对图片List进行重排序时,使用Collection.sort(List,Comparator)方法,根据前缀排序,但是写完代码发现有的顺序还是错乱的
原因:代码里通过截取文件名字前缀为字符串,字符串比较底层是通过ACSII码值比较,所以有的顺序是错乱的。以下为说明
compareTo() 的返回值是int, 它是先比较对应字符的大小(ASCII码顺序)
1、如果字符串相等返回值0
2、如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值前字符串的值小于后字符串,正值前字符串大于后字符串)
3、如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度.
例:
String s1 = "abc";
String s2 = "abcd";
String s3 = "abcdfg";
String s4 = "1bcdfg";
String s5 = "cdfg";
System.out.println( s1.compareTo(s2) ); // -1 (前面相等,s1长度小1)
System.out.println( s1.compareTo(s3) ); // -3 (前面相等,s1长度小3)
System.out.println( s1.compareTo(s4) ); // 48 ("a"的ASCII码是97,"1"的的ASCII码是49,所以返回48)
System.out.println( s1.compareTo(s5) ); // -2 ("a"的ASCII码是97,"c"的ASCII码是99,所以返回-2)
解决方式:直接将"1","2"这种前缀转换为Integer进行比较即可
以上即为此次解决问题的过程,虽然为短短几步,但是却浪费了很多时间,不由得感叹自己也太废物了,此次回调的部分代码如下图,下面代码哪里可以优化的请大神留言指导一下,不胜感激
上一篇: Skills of debugging model
下一篇: 下载文件Utils