侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

tomcat应用拒绝服务解决过程

2023-11-15 星期三 / 0 评论 / 0 点赞 / 42 阅读 / 4001 字

问题现象: 应用跑在tomcat上,近期遇到个问题,运行一段时间后就拒绝服务, 其他程序连接不上应用, 出问题后,tomcat和应用不记录任何日志,重启tomcat后,服务恢复。 第一次出现问题时,

问题现象: 应用跑在tomcat上,近期遇到个问题,运行一段时间后就拒绝服务, 其他程序连接不上应用, 出问题后,tomcat和应用不记录任何日志,重启tomcat后,服务恢复。

第一次出现问题时, 根据经验判断是tomcat的线程数满了, 在服务器上查看链接数的确很多, 就修改了tomcat的最大连接数,从 400 改成 800,修改后应用持续到当天晚上21点,又挂了。

为了不影响业务,将最大连接数改成2000, 重启。 

重启后,跟踪链接使用情况,发现从该应用到JOS平台的连接居多,都是ESTABLISHED 状态,并且持续增加,由此可判断问题出在这里。这种问题的第一反应就是,程序里有没有关闭链接的地方,于是开始翻代码,结果发现应用到JOS的连接都是JOS提供的SDK处理的,看了SDK中处理链接的地方,没看出什么问题(此时的关注点还在链接是否被关闭的问题上),代码如下:

public static String doPost(String url, String ctype, byte[] content, int connectTimeout, int readTimeout) throws IOException {    HttpURLConnection conn = null;    OutputStream out = null;    String rsp = null;    try {        conn = getConnection(new URL(url), "POST", ctype);        conn.setConnectTimeout(connectTimeout);        conn.setReadTimeout(readTimeout);        out = conn.getOutputStream();        out.write(content);        rsp = getResponseAsString(conn);    } finally {        if(out != null) {            out.close();        }        if(conn != null) {            conn.disconnect();        }    }    return rsp;}

又看了N遍代码,终于发现一个线索,应用程序中初始化jos client方法是这样的:

JdClient client=new DefaultJdClient(Constant.JDURL,sessionkey,appkey,secret);

JOS sdk里的代码是这样的:

public class DefaultJdClient implements JdClient {    ... ...    public DefaultJdClient(String serverUrl, String accessToken, String appKey, String appSecret) {        this.connectTimeout = 0;        this.readTimeout = 0;        this.serverUrl = serverUrl;        this.accessToken = accessToken;        this.appKey = appKey;        this.appSecret = appSecret;    }    public DefaultJdClient(String serverUrl, String accessToken, String appKey, String appSecret, int connectTimeout, int readTimeout) {        this(serverUrl, accessToken, appKey, appSecret);        this.connectTimeout = connectTimeout;        this.readTimeout = readTimeout;    }    ... ...}

问题来了,如果程序初始化client时不指定超时时间, SDK中默认成了0, 即无穷大,虽然不能确定是不是当前遇到的问题,但这样肯定是不合理的,改了试试再说,

JdClient client=new DefaultJdClient(Constant.JDURL,sessionkey,appkey,secret, 10000, 10000);

修改后,链接数正常了, 不再持续增加, 问题解决了,但是还有两个疑问:

1、出现链接未关闭的根本原因还不清楚;

2、这个应用已经正常运行了2年了, 为嘛现在才出现问题;

看了下应用日志,发现加上超时时间后,日志里有很多这种错误:

11:31:08,352 ERROR JingDongUpdateSkuStockCmd:62 - IO异常:com.jd.open.api.sdk.JdException: 服务器连接超时,请重试	at com.jd.open.api.sdk.DefaultJdClient.execute(DefaultJdClient.java:103)

到此,问题就很清晰了:

近期,网络问题或者是JOS平台问题(嫌疑比较大),导致我们这边应用发出的请求得不到响应,而连接没有设置超时时间,导致程序一直走等待,占用线程数,等到线程数满了, tomcat就拒绝服务了。

 

最后甩个锅, 没有设置链接超时时间,是按照JOS平台给的代码示例写的,示例代码这么搞,坑人啊!

广告 广告

评论区