如何从 URL 分析导致程序出现问题的方法?

Posted

技术标签:

【中文标题】如何从 URL 分析导致程序出现问题的方法?【英文标题】:How do I profile a method from URL that is causing issues in my program? 【发布时间】:2019-02-13 09:43:58 【问题描述】:

我用 Java 编写了一个软件,通过使用代理发送 HTTP 请求来检查代理是否正常工作。它并行发送请求,使用 ThreadPool 运行超过 100 个线程。

以下方法用于检查单个代理:

public boolean isWorkingProxy() 
    //Case of an invalid proxy
    if(proxyPort == -1) 
        return false;
    

    HttpURLConnection con = null;

    //Perform checks on URL
    //IF any exception occurs here, the proxy is obviously bad.
    try 
        URL url = new URL(this.getTestingUrl());
        //Create proxy
        Proxy p = new Proxy(this.testingType, new InetSocketAddress(this.proxyIp, this.proxyPort));
        //No redirect
        HttpURLConnection.setFollowRedirects(false);
        //Open connection with proxy
        con = (HttpURLConnection)url.openConnection(p);
        //Set the request method
        con.setRequestMethod("GET");
        //Set max timeout for a request.
        con.setConnectTimeout(this.timeout);
        con.setReadTimeout(this.timeout);
     catch(MalformedURLException e) 
        System.out.println("The testing URL is bad. Please fix this.");
        return false;
     catch (ProtocolException e) 
        System.out.println("Invalid request type provided (Not GET / POST / Valid type)");
        return false;
     catch(IOException e) 
        System.out.println("Failed to open connection with url using proxy.");
        return false;
    

    try(
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            ) 

        //read text response
        String inputLine = null; StringBuilder response = new StringBuilder();
        while((inputLine = in.readLine()) != null) 
            response.append(inputLine);
        


        //A valid proxy!
        return con.getResponseCode() > 0;

     catch(Exception e) 
        return false;
    

以下代码是我如何启动线程:

Deque<String> proxies = DB.getProxiesToCheck();
while(proxies.isEmpty() == false) 
    try 
        String[] split = proxies.pop().split(":");

        //Submit every check for this proxy
        //There are a total 7 checks right now.
        for(int i = 0; i < checks.length; i++) 
            executor.submit(new RunnableProxyRequest(split[0], split[1], checks[i]));
        

     catch(IndexOutOfBoundsException e) 
        continue;
    
    //Wait 50ms before each proxy
    Thread.sleep(50);

现在:CPU 使用率在某些时候变得相当高,我尝试使用 JVisualVM 对其进行分析。我有以下结果:

它声明我有“放弃的连接清理线程”,但是我的代码使用资源尝试打开HttpURLConnection 的输入流,但我找不到任何我留下打开连接的实例。除了方法中的流之外,我不打开任何其他流。此外,看起来 parseURL(Java 的 URL 对象中使用的一种方法)正在消耗我 100% 的 CPU 时间。

请注意,它会更新 SQL 数据库以报告代理是否在工作。mysql 数据库的更新是 synchronized()

为什么会发生这种情况,我该如何解决?

编辑

在将每个代理检查发送到 exectuor 服务之前,我添加了一个 Thread.sleep(50);(在上面的代码中很明显)我还在命令行中添加了参数 -XX:+UseParallelGC。它似乎持续更长时间,但几个小时后 CPU 使用率仍然很高,程序崩溃了。

【问题讨论】:

【参考方案1】:

outputStream 也应该关闭。 同时进行 100 多个连接确实会消耗 CPU 资源,尤其是在大多数代理都可用的情况下。

【讨论】:

哪个输出流?我的代码中没有 outputStreams?

以上是关于如何从 URL 分析导致程序出现问题的方法?的主要内容,如果未能解决你的问题,请参考以下文章

url 中的特殊字符 % # & = ? / + 无法被后端解析问题分析及解决方法

如何停止返回导致“void函数中出现意外的非void返回值”?

将应用程序 URL 从一个选项卡复制到另一个选项卡导致 404 错误

IIS7 向 URL 添加乱码,导致 CSS 文件出现 404

CouchDB 重写规则以更新处理程序导致 405 方法不允许

从 TFS 仪表板打开项目导致 Visual Studio Web 处理程序异常