线上异常排查汇总【1】

异常1、NoSuchMethodError
最近有一个文件上传功能一直失败,测试预发环境都正常,一到线上就不正常,然后catch不到任何异常,想来应该是Error了,后来catch Throwable,终于打印了错误日志

java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString([B)Ljava/lang/String;
	at org.apache.commons.codec.digest.HmacUtils.hmacSha1Hex(HmacUtils.java:403) ~[commons-codec-1.10.jar:1.10]

这个和NoClassDefFound类似,应该是版本冲突引起的。但是查了半天lib,maven,都只有一个1.10的版本。
最后是查到了/tomcat/lib/shared/ 路径下有个一个自带的commons-codec,版本是1.3,且确实没有错误信息中的方法。

想来应该是应用代码编译的时候使用了1.10。但是在应用启动的时候采用了tomcat的自带包,导致错误了。

关于NoClassDefFoundError和ClassNotFoundException的不同,可以参考通俗解释:
https://blog.csdn.net/zzp448561636/article/details/84854887

异常2、最近在做图片合并,用到如下代码,读取背景图片,其中在read的时候报错

Image bg = ImageIO.read(defaultFile);
int bgW = bg.getWidth(null);
int bgH = bg.getHeight(null);
BufferedImage bgImg = new BufferedImage(bgW, bgH, BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics g = bgImg.getGraphics();
g.drawImage(bg, 0, 0, bgW, bgH, null);
javax.imageio.IIOException: Can't read input file!
        at javax.imageio.ImageIO.read(ImageIO.java:1301) ~[na:1.7.0_76]

经查,是传入的default文件不存在。这里记录下spring 中读取文件的几种方式
方式1,读取到的路径是/XXX/webapps/ROOT/WEB-INF/classes/。如果应用是部署在ROOT文件下,如果是项目名那就是项目名

Thread.currentThread().getContextClassLoader().getResource("").getPath()

方法2,获取的是项目路径,/XXX,连后面的/webapps/ROOT都没有

System.getProperty("user.dir")

实际上我的图片是放在工程webapp/ 路径下,暂时就写成了

System.getProperty("user.dir") + "/webapps/ROOT/default.png"

方法3,这个方法理论是那个应该返回到/XXX/webapps/ROOT/,

request.getContextPath()

但是测试了一下打印出来是空,看了下注释,如果应用部署在ROO下,这个方法返回的是空

For servlets in the default (root) context, this method returns "".

方法4,如果是jar包形式部署,通过getResources资源流的方式获取
现在pom文件中的resources标签下增加以下内容,表示哪个路径下的资源可以被作为resources读取

<resource>
    <directory>${basedir}/src/main/webapp</directory>
    <targetPath>resources</targetPath>
    <includes>
        <include>**/**</include>
    </includes>
</resource>

使用的时候如下,其中/resources/是上面配置的targetPath路径

getClass().getResourceAsStream("/resources/template/default_code.png");

异常3、
最近在做应用拆分,从普通spring应用中拆出业务作为微服务,剩余业务还在老系统中,在老系统中做了一个中转。上线之后出现如下错误

2018-05-10 10:49:42,919 [http-nio-8011-exec-129] ERROR [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]] [DirectJDKLog.java:182] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap' - maybe not public?] with root cause []
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap' - maybe not public?
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:226)
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81)
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:121)
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:262)
        at org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$ExpressionResolver.resolvePlaceholder(ErrorMvcAutoConfiguration.java:288)
        at org.springframework.boot.autoconfigure.web.NonRecursivePropertyPlaceholderHelper$NonRecursivePlaceholderResolver.resolvePlaceholder(NonRecursivePropertyPlaceholderHelper.java:56)
        at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:147)
        at org.springframework.boot.autoconfigure.web.NonRecursivePropertyPlaceholderHelper.parseStringValue(NonRecursivePropertyPlaceholderHelper.java:38)
        at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
        at org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView.render(ErrorMvcAutoConfiguration.java:226)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286)
        at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)

经过排查原因如下:原有系统中Controller层有异常处理,直接return “error”。正常情况下会去渲染error.vm文件,但是拆除去的系统中没有这个文件,就报错了。推而广之,如果返回的不存在视图应该都会报错
参考链接:http://www.cnblogs.com/FlyAway2013/p/8027259.html

异常4
这个异常没啥好说, 就目前碰见的几次情况来看,都是因为请求超时了。A服务请求B服务,B服务处理时间过长,A因为超时主动断开链接,B要往回写数据的时候,流通道关闭了。这个应该放在http请求协议上来看,三次握手建立链接,然后传输数据,最后断开链接。现在数据还没写链接就断了。

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
        at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:370)
        at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:334)
        at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:101)
        at com.fasterxml.jackson.core.json.UTF8JsonGenerator.flush(UTF8JsonGenerator.java:1054)
        at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:953)
        at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:286)
        at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:106)
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:231)
        at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174)
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at com.zhongan.jarvis.meeting.component.interceptor.ThreadLocalFilter.doFilter(ThreadLocalFilter.java:49)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1775)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1734)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

异常5
这个都不是线上异常, 是开发中遇见的异常,接收的参数是个List,直接写成

@RequestMapping(value = "test", method = RequestMethod.GET)
@ResponseBody
public Result checkTest(List<String> strList) {}

报错如下

org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface

我看网上的解决方案,是两种,一种是把list包在VO对象里,一种是写成String,用某种分隔符分隔,后台自行处理
以上两种方法经测试可以。我来另外测试了一种方法,controller里写成ArrayList,报错倒是不报错了,但是前端请求的参数后台接收不到。

异常6、
场景:文件上传,然后异步线程读取文件内容,执行任务,出现如下错误

Exception in thread "pool-2-thread-3" java.lang.IllegalStateException: File has been moved - cannot be read again
	at org.springframework.web.multipart.commons.CommonsMultipartFile.getInputStream(CommonsMultipartFile.java:146)
	at com.XXX.XXX.XXX.SystemController$1.run(SystemController.java:177)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

按照网上的说法,原因是上传的文件超过了maxInMemorySize大小,采用了临时文件的方式存储,线程1执行完毕,还没有删除临时文件,线程2又上传了一个文件,两次的文件名是一样的,然后这个时候线程1删除了文件,导致线程2出现这个异常。
除了上面这个情况之外,还有一种异常,线程1还没有执行完,临时文件也没有删除,同时请求2上传一个相同文件名的文件,也是采用临时文件的存储方案,开启线程2执行读取文件执行任务,线程2就会采用了线程1的文件内容+线程2的变量执行任务。
这个异常有两种解决方案

  • 设置maxInMemorySize,这种方法是并没有解决掉 File has been moved - cannot be read again问题,而是避开了这个问题。将文件流不再写入到临时文件,而是用内存存储。
<bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    <property name="defaultEncoding" value="utf-8"></property>  
    //允许最大可上传的文件大小  
    <property name="maxUploadSize" value="10485760000"></property>  
    //上传文件超出这个大小就会用于创建临时文件存储,而不使用内存存储  
    <property name="maxInMemorySize" value="4194304"></property>  
</bean>  
  • 改成随机的文件名,controller读到文件先重命名保存一下文件,或者把读取文件放在主线程里,尽快执行完

参考链接:https://www.cnblogs.com/yxh1008/p/6537863.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值