欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

http请求报文挂起案例

程序员文章站 2024-02-08 18:18:40
...

问题描述

最近在生产上出现了多次java应用服务器挂死的情况。

问题分析

从堆栈中可以看到大量的线程挂在

     at java.net.SocketOutputStream.socketWrite0(Native Method)
     at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)

通过查看代码,发现是通过HttpUrlConnection进行http请求的,并且有超时设置。如下所示:

HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();
urlCon.setConnectTimeout(30000);
urlCon.setReadTimeout(30000);

通常情况下,阻塞在socket的write是比较少见的,也没有api可以专门设置写超时。看业务,主要是通过http发送图片数据给平台G进行图像识别,图片数据基本上需要数十K到数百K,在这种情况下,是有可能出现这种情况的。

为了提高效率,socket有读写缓冲区,当socket调用write的时候,会先将数据写入本端的写缓冲区,然后由底层的tcp协议负责将数据传输到对端的读缓冲区,从而腾出写缓冲区。如果数据很大,写缓冲区不够写,就存在等待的情况,如果对端没有及时处理数据,那么这个wrtie可能就会阻塞很长一段时间。

不幸的是,java普通的socket并没有提供写超时的设置参数,所以在设计上应该谨慎考虑传输大批量数据。不过,好在可以考虑nio来处理,例如使用httpclient4.x的异步http调用,是可以避免这种write阻塞情况的,参数设置如下:

private RequestConfig requestConfig = RequestConfig.custom() 
    .setSocketTimeout(SOCKET_TIMEOUT)  //可对应读写超时
    .setConnectTimeout(CONNECTION_TIMEOUT)  
    .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)  
    .build();  

转载于:https://my.oschina.net/bonyfish/blog/846552