平时遇到的开发问题
开发问题一:Broken Pipe
问题描述:
Caused by: java.io.IOException: Broken pipe
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:134)
at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1225)
at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:743)
at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:696)
at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:686)
at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:553)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.flush(ChunkedOutputFilter.java:157)
at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:216)
at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1149)
at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:394)
at org.apache.coyote.Response.action(Response.java:209)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:294)
Caused by: java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:134)
at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1225)
at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:743)
at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:696)
at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:686)
at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:553)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.flush(ChunkedOutputFilter.java:157)
at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:216)
at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1149)
问题原因:
这个异常是客户端读取超时关闭了连接,这时候服务器端再向客户端已经断开的连接写数据时就发生了broken pipe异常!出现问题的情形是对100件商品的批量上架操作,后端接口还未响应结束,前端就已经断开的连接。
解决办法:
我采用了开启多线程的方式进行处理的,既然响应超时那就多开几条线程处理,看情况而定,别滥用线程!!!
开发问题二:跨域问题 No ‘Access-Control-Allow-Origin’ header is present on the requested resource
问题描述:
Access to XMLHttpRequest at ‘http://192.168.2.170:8000/external/statistics/function’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
问题原因:
说明Origin指定的域名不在许可范围内,需要在前端和后端添加允许跨域访问的配置,这种情况在开开发时经常会遇到。
解决办法:
在前后端分别调整请求头headers,以后端为例,主要是设置参数:Access-Control-Allow-Origin的值,值为*表示接受任意域名的请求
@Component
public class CrossFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(CrossFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
logger.debug("跨域请求进来了。。。");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletRequest.getSession();
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "*");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie");
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Content-type", "application/json");
httpResponse.setHeader("Cache-Control", "no-cache, must-revalidate");
chain.doFilter(request, httpResponse);
}
}
参考:解决CROS跨域问题
开发问题三:oom:out of memory
问题描述:
org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'run' on target class [class com.kingdee.finance.data.credit.ydreport.task.YdReportAppendixInfoTask] failed; nested exception is java.lang.OutOfMemoryError: Java heap space
问题原因:
- 有可能是内存分配确实过小,而正常业务使用了大量内存
- 某一个对象被频繁申请,却没有释放,内存不断泄漏,导致内存耗尽
- 某一个资源被频繁申请,系统资源耗尽,例如:不断创建线程,不断发起网络连接
解决办法:
- 确认是不是内存本身就分配过小
jmap -heap port
可以查看新生代,老生代堆内存的分配大小以及使用情况,看是否本身分配过小。
- 找到最耗内存的对象
jmap -histo:live port | more
输入命令后,会以表格的形式显示存活对象的信息,并按照所占内存大小排序:
- 实例数
- 所占内存大小
- 类名
是不是很直观?对于实例数较多,占用内存大小较多的实例/类,相关的代码就要针对性review了。
- 确认是否是资源耗尽
工具:
- pstree
- netstat
查看进程创建的线程数,以及网络连接数,如果资源耗尽,也可能出现OOM。
另一种方法,通过:
/proc/${PID}/fd
/proc/${PID}/task
可以分别查看句柄详情和线程数。
作为一个后端工程师,对日常工作的一些异常和错误要有一个积累总结,一是总结整理之后,下次遇到同样的问题自己不会很茫然不知所措,尤其是在上线时,其他同事都在等着你解决问题的时候,你吭吭唧唧那就不太好了,二是在面试时也会经常被问到类似的问题,作为社招有经验的工程师,更不能再以校招的面试作为自己的标准了,要有自己的经验积累,随时准备面对不确定的情况!