快速检查服务器以查找活动Web服务器(多线程)

时间:2011-06-04 13:17:40

标签: java multithreading performance sockets httpurlconnection

我想查看大量(数千)网站,如果他们仍然在运行。因为我想在我的HostFile Wikipage about Hostfiles中删除不可用的条目。 我想在2阶段的过程中做到这一点。

  1. 检查端口80上是否有正在运行的内容
  2. 检查HTTP响应代码(如果不是200我必须检查网站)
  3. 我想多线程,因为如果我想检查数千个地址,我就等不及超时了。 这个问题与第一步有关。

    我遇到了问题,即1/4的连接尝试无法正常工作。如果我重试那些不工作的约~3 / 4工作?我没有正确关闭套接字吗?我是否遇到开放套接字的限制? 默认我运行16个线程,但我遇到了与8或4相同的问题。 有什么我想念的吗

    我已经简化了一些代码。 这是Thread的代码

    public class SocketThread extends Thread{
    
      int tn;
      int n;
      String[] s;
      private ArrayList<String> good;
      private ArrayList<String> bad;
    
      public SocketThread(int tn, int n, String[] s) {
        this.tn = tn;
        this.n = n;
        this.s = s;
        good = new ArrayList<String>();
        bad = new ArrayList<String>();
      }
    
      @Override
      public void run() {
        int answer;
        for (int i = tn * (s.length / n); i < ((tn + 1) * (s.length / n)) - 1; i++) {
          answer = checkPort80(s[i]);
          if (answer == 1) {
            good.add(s[i]);
          } else {
            bad.add(s[i]);
          }
          System.out.println(s[i] + " | " + answer);
        }
      }
    }
    

    这是checkPort80方法

    public static int checkPort80(String host) 
      Socket socket = null;
      int reachable = -1;
      try {
        //One way of doing it
        //socket = new Socket(host, 80);
        //socket.close();
    
        //Another way I've tried
        socket = new Socket();
        InetSocketAddress ina = new InetSocketAddress(host, 80);
        socket.connect(ina, 30000);
        socket.close();
        return reachable = 1;
      } catch (Exception e) {
      } finally {
        if (socket != null) {
          if (socket.isBound()) {
            try {
              socket.close();
              return reachable;
            } catch (Exception e) {
              e.getMessage();
              return reachable;
            }
          }
        }
      }
    }
    

    关于Threads,我创建一个ThreadList的ArrayList,创建它们和.start()它们,然后我们.join()它们,得到“上帝”和“坏”将它们保存到文件中。

    非常感谢帮助。

    PS:我首先重命名Hosts文件,这样它不会影响进程,所以这不是问题。


    修改
    感谢MarceloHernándezRishr,我发现,HttpURLConnection似乎是更好的解决方案。它工作得更快,我也可以得到HttpResponseCode,我也感兴趣(只是认为它会慢得多,然后只检查端口80)。我还有一段时间突然得到错误,我想这与DNS服务器认为这是一个DOS攻击^^(但我应该检查更进一步,如果错误位于其他地方)也fyi我使用OpenDNS,所以也许他们只是不喜欢我^^。 x4u建议在线程中添加一个sleep(),这似乎可以让事情变得更好,但是它会帮助我提高/秒我不知道的条目。

    尽管如此,我不能(到目前为止)达到我想要的速度(10次以上/秒),即使每秒6次也似乎不起作用。 以下是我测试的一些场景(直到现在都没有任何睡眠())。

    number of  time i get first round  how many entries where  entries/second
    threads    of errors               processed until then
    10         1 minute 17 seconds     ~770 entries            10
    8          3 minute 55 seconds     ~2000 entries           8,51
    6          6 minute 30 seconds     ~2270 entries           5,82
    

    我会尝试使用Threads找到一个最佳位置并睡觉(或者如果我遇到很多错误,可能只需暂停一分钟)。 问题是,有一百万个条目的Hostfiles,每秒一个条目需要11天,我想所有人都明白,这是不可预料的。 有没有办法动态切换DNS服务器? 还有其他建议吗? 我应该将这些新问题作为单独的问题发布吗?

    感谢您的帮助,直到现在。 我将在大约一周内发布新的结果。

2 个答案:

答案 0 :(得分:0)

套接字通常会尝试正常关闭并等待目标端口的响应。当他们正在等待时,他们仍然会阻止资源,如果在打开套接字太多的情况下执行连接尝试失败,则会导致连续尝试失败。

为避免这种情况,您可以在连接套接字之前关闭延迟:

socket.setSoLinger(false, 0);

答案 1 :(得分:0)

我有3条建议可以帮助您完成任务。

  1. 也许您可以使用课程HttpURLConnection
  2. 最多使用10个线程,因为您仍然受到cpu,带宽等的限制。
  3. 列表goodbad不应该是您的线程类的一部分,也许它们可以是类的静态成员,如果您有主方法并执行静态同步方法以添加成员两个列表来自任何线程。