Как использовать MultiThread HttpURLConnection в Java - PullRequest
0 голосов
/ 05 августа 2020

Привет, ребята, у меня есть клиент, который хотел бы проверить варианты на своем веб-сайте. У них есть 5 миллионов URL для проверки. Если бы я должен был отправлять запросы / пинги синхронно, это заняло бы у меня 23 дня. Итак, я ищу многопоточное решение. Первоначально я начал эту проблему с Python, но не заметил особых улучшений / не смог хорошо масштабироваться, поэтому здесь я нахожусь в Java, и если это тоже не удастся, я попробую Go, прежде чем бросать в полотенце.

Проблема в том, что я не вижу никаких улучшений с многопоточностью. Возможно, я неправильно его реализую, может ли кто-нибудь мне помочь? этого поста, чтобы увидеть, как я справился с проблемой.

Это предложение сокета, терпит неудачу, когда я пытаюсь запустить его в потоке, тоже не уверен, что я здесь делаю неправильно.

Основной класс:

package com.company;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class Main extends Thread{
public static void main(String[] args) throws IOException {
long startTime = System.nanoTime();
Helpers.get("www.google.com", 80); // works here
String path = "test.txt";
boolean append = true;
for (int x = 0; x < 1; x++) {
ArrayList<String> urls = new ArrayList<String>();
// when x = 0, y = 0 | 10 /\ when x = 1, y = 10 | 20
for (int y= x * 10;y < ((x + 1) * 10); y++){
urls.add(String.format("www.google%d.com/", y)); // doesn't work here
}
Thread thread = new Thread(new Helpers(path, append, urls, 80));
thread.start();
thread.interrupt();
}
long endTime = System.nanoTime();
long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
System.out.println(duration + " ms");
}
}

Класс помощников:

package com.company;
import java.io.IOException;
import java.net.*;import java.io.FileWriter;
import java.io.PrintWriter;import java.util.ArrayList;
public class Helpers extends Thread{
public Helpers(String path, boolean append, ArrayList<String> urls, int port) throws IOException {
this.run(path, append, urls, port);
}
public void run(String path, boolean append, ArrayList<String> urls, int port) throws IOException {
for (String url : urls) {
String status = Helpers.get(url, port);Helpers.writeToFile(path, append, status);
System.out.println(status);
}
}
public static String get(String url, int port) throws IOException {
try {
Socket conn = new Socket(url, 80);
conn.close();
return url + " | Success";
}catch (UnknownHostException error){return url + " | Failed";
}
}

Ответы [ 2 ]

0 голосов
/ 07 августа 2020

Вы можете попробовать другой подход. Вместо того, чтобы создавать HTTPConnection для каждого вызова, вы можете попробовать создать соединение сокета с веб-сервером, а затем выполнить несколько вызовов (GET / HEAD) на разные URL-адреса.

/**
 * hostname of the webserver e.g. www.w3.org
 * @param hostname
 * @param urlList
 * @throws IOException
 */
public static void makingHTTPCall( String hostname , List<String> urlList) throws IOException {

    SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    SSLSocket socket =
            (SSLSocket)factory.createSocket(hostname, 443);


    BufferedReader in
            = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
    PrintWriter out
            = new PrintWriter(socket.getOutputStream(), true);

    /**
     *  if required create different url List and pass those list to separate thread for better performance
     */

    urlList.forEach(
            url -> {
                System.out.println("Making call to url /" + url);
                out.println("HEAD "  + url + " HTTP/1.1\r\n");
                out.flush();

                String line = "";

                try {
                    while ((line = in.readLine()) != null) {
                        System.out.println("Response" + line);
                        break;
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    );

    try {
            in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    out.close();

}

Я пробовал использовать сокет SSL, который вы можете измените это в соответствии с вашей конфигурацией.

0 голосов
/ 06 августа 2020

Вы неправильно это реализуете. Вы должны сделать так, чтобы класс Helpers расширял поток или реализовывал запускаемый. Передайте этому классу все, что вам нужно, например URL-адрес, указатель файла и т. Д. c.

В основном классе создайте объект Helper, а затем запустите его как поток.

...