写了一个rest接口,接口接受json数据解析批量入索引。入索引的频率和大都挺大的,每天看日志都会有几条写入失败,原因是收到client端的数据不完整,是一个被截断的json。如图:
我是通过httprequest的getInputStream自己解析的,解析出来就成这个样子了。长度我也记录了一下,65k多,不可能是超过tomcat接受post请求体大小限制导致的,maxPostSize我配置了50M。
客户端使用httpclient传输的,一开始担心是客户端的问题,我在客户端做了json校验,但凡客户端不是json格式直接返回失败抛出异常,但是产生这条日志的时候,客户端并没有抛异常。而且客户端是把json字符串封装成一个实体作为api,然后再反序列化成字符串传输的,如果是使用者字符串拼的有问题,肯定会在前端先报错。
那么问题就集中在服务端了,到底还有什么限制会导致服务端接受数据不全吗?我还想到一种可能,就是数据再到达我这里的时候中间经历过三次json序列化和反序列化:业务数据序列化成埋点json字符串,消费端接受mq中埋点信息反序列化成实体,通过client api序列化成json字符串传输到tomcat,几次解析都使用fastjson,所以会不会是几次解析使用的版本不一样导致的呢?tomcat用的1.2.7 client用的1.2.9
看看你的请求是否是post的方式提交的如果是get会出现长度限制的
肯定是post,否则进不了controller会不会是线程安全问题~
回复 @salvinlee:代码贴出来了,解析部分就是普通方法放在controller里面的,没用到静态的资源,除非说ServletRequest这个对象是线程共享的才会导致多线程并发的问题吧回复 @salvinlee:如果是因为线程安全问题的话我只能把读取字节流那段代码加上同步锁了。我把代码贴出来吧回复 @coder4j:之间我也遇到过类似的问题,最后定位就是线程不安全,在高并发的时候出现数据不全~怎么说呢?我是在controller里面直接读取字节流,如果有线程安全问题那就是servlet的问题了?但是我不明白直接通过getInputStream然后解析成字符串这个过程怎么会存在线程安全问题呢。1、你必须用POST请求。
2、你在使用InputStream/OutputStream时注意调用flush()保证缓冲区遗留的数据全部读完。
3、注意closeInputStream。
4、楼上提到的线程安全问题,你会不会误写了某个变量被多个线程共享读写了、导致偶尔并发了读得内容不完整。
我把读取客户端流数据的代码贴出来吧publicstaticStringgetBodyString(ServletRequestrequest){StringBuildersb=newStringBuilder();InputStreaminputStream=null;BufferedReaderreader=null;try{inputStream=request.getInputStream();reader=newBufferedReader(newInputStreamReader(inputStream,Charset.forName("UTF-8")));Stringline="";while((line=reader.readLine())!=null){sb.append(line);}}catch(IOExceptione){e.printStackTrace();}finally{if(inputStream!=null){try{inputStream.close();}catch(IOExceptione){e.printStackTrace();}}if(reader!=null){try{reader.close();}catch(IOExceptione){e.printStackTrace();}}}returnsb.toString();}看看是不ppos加大tomcat的size应该就可以了收到的很小,60K多。tomcat我给了50M换一个servlet容器试试?先确定问题。用apache工具IOUtils从request中读取数据试试?
解决了吗?坐等结果
StringBuilder是非线程安全的,检查是存在多线程调用
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。