【问题标题】:Check servers for active Webserver fast (multithreaded)快速检查服务器的活动 Web 服务器(多线程)
【发布时间】:2011-06-04 13:17:40
【问题描述】:

我想检查大量(数千个)网站,如果它们仍在运行。因为我想删除我的 HostFile Wikipage about Hostfiles 中的 unececarry 条目。 我想分两阶段进行。

  1. 检查端口 80 是否正在运行
  2. 检查 HTTP 响应代码(如果不是 200 我必须检查站点)

我想多线程,因为如果我想检查数千个地址,我不能等待超时。 这个问题只是关于第一步。

我有一个问题,我的连接尝试中有大约 1/4 不起作用。如果我重试大约 3/4 工作的不工作?我没有正确关闭套接字吗?我是否遇到了打开套接字的限制? 默认我运行 16 个线程,但我有 8 个或 4 个相同的问题。 有什么我想念的吗

我已经稍微简化了代码。 这是线程的代码

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;
        }
      }
    }
  }
}

关于线程,我创建了一个线程的 ArrayList,创建它们并 .start() 它们,然后我 .join() 它们,获取“上帝”和“坏”将它们保存到文件中。

感谢您的帮助。

PS:我先重命名了 Hosts 文件,以免影响进程,所以这不是问题。


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

不过,我(到目前为止)仍然无法达到我想要的速度(10+ 个条目/秒),即使每秒 6 个条目似乎也不起作用。 以下是我测试过的几个场景(到目前为止都没有任何 sleep())。

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 和 sleep 的最佳位置(或者如果我遇到很多错误,可能只是暂停一分钟)。 问题是,有 100 万个条目的主机文件,每秒一个条目需要 11 天,我想大家都明白,这是不可预期的。 有没有办法即时切换 DNS 服务器? 还有其他建议吗? 我应该将新问题作为单独的问题发布吗?

感谢您到目前为止的帮助。 我将在大约一周后发布新结果。

【问题讨论】:

    标签: java multithreading performance sockets httpurlconnection


    【解决方案1】:

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

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

    【讨论】:

    • 1.我在第二阶段使用它,它也有一些问题 2. CPU 和带宽不是瓶颈,问题是超时很长,所以大多数线程无论如何都在等待。 3. 听起来是个好主意,但我只是不想打扰同步。
    • 编辑:与套接字类似的问题,过了一会儿我得到了错误
    【解决方案2】:

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

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

    socket.setSoLinger(false, 0);
    

    【讨论】:

    • 这似乎在一段时间内工作得非常好(而且非常快),但经过大约 100 次检查后,其余的根本无法访问。
    • 您的路由器或您路由上的任何其他网络设备可能有类似的措施来处理连接,DNS 服务器也倾向于限制您在一定时间内可以执行的查询数量。因此,很可能您根本无法以如此高的速度进行这些检查,并且您可能必须根据您在过去几秒钟内打开的套接字数量添加暂停。
    • 如何缩小问题范围?打印IP?使用更少的线程?
    • 最简单的方法可能是在连接尝试成功后添加睡眠,以便每个连接占用线程一定的最短时间。即,如果连接是在 200 毫秒后建立的,请再等待 800 毫秒,以使每次连接至少需要 1000 毫秒。然后,您可以调整线程数和最短连接时间,以了解您大约可以走多快,然后我将这个数字减半,让野兽运行它需要多长时间。由于您遇到无法访问的错误,我怀疑这次是 DNS 服务器拒绝了您的请求泛滥。
    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 2013-11-15
    • 2020-09-20
    • 1970-01-01
    • 2020-01-29
    • 2016-11-02
    • 1970-01-01
    相关资源
    最近更新 更多