Как я могу правильно обрабатывать асинхронные запросы, чтобы избежать регулирования?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как я могу правильно обрабатывать асинхронные запросы, чтобы избежать регулирования?

Сообщение Anonymous »

У меня есть приложение, которое будет сканировать страницу и получать ссылки на этой странице, если страница содержит заданное ключевое слово.
Сейчас я использую для этого Java CompletableFuture, но по мере роста количества ссылок медленнее становятся запросы.
Вот HttpClient:

Код: Выделить всё

import java.net.http.HttpClient;

private final HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(2))
.build();

@Override
public CompletableFuture getPageContentAsync(String url) {
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.GET()
.build();

return this.client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(resp -> resp.statusCode() == 200 ? resp.body() : "");
}
И класс, отвечающий за выполнение:

Код: Выделить всё

public class SearchTask implements Runnable {

private final String id;
private final String keyword;

// Repository is just a ConcurrentHashMap.
private final SearchRepository repository;
private final ExecutorService crawlPool;

private final Set urlsVisited = ConcurrentHashMap.newKeySet();

public SearchTask(String id, String keyword,
SearchRepository repository, ExecutorService crawlPool) {
this.id = id;
this.keyword = keyword;
this.repository = repository;
this.crawlPool = crawlPool;
}

@Override
public void run() {
try {
this.crawlAsync("https://www.kernel.org/pub/linux/docs/man-pages/").join();
// sysout("task with id %s finished")
} finally {
this.crawlPool.shutdown();
}
}

private CompletableFuture crawlAsync(String url) {
if (this.urlsVisited.add(url))
return this.httpService.getPageContentAsync(url, this.id)
.thenComposeAsync(html -> {
if (HtmlUtils.containsKeyword(html, this.keyword)) this.repository.addUrl(this.id, url);

// The utils will get all the href tags and extract the text.
Set links = HtmlUtils.extractLinksFromHtml(html)
.stream()
.filter(link -> !this.urlsVisited.contains(link))
.collect(Collectors.toSet());

CompletableFuture[] futures = links.stream().limit(2)
.map(this::crawlAsync)
.toArray(CompletableFuture[]::new);

return CompletableFuture.allOf(futures);
}, this.crawlPool);
return CompletableFuture.completedFuture(null);
}
}
А вот как создается исполнитель:

Код: Выделить всё

int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
Я пробовал увеличить размер пула, но не думаю, что это правильный путь.
Я также пытался вставить семафор, но он не работал должным образом, казалось, что запросы останавливались до того, как все страницы были просканированы.
У меня есть скриншот профилирования, который может помочь понять, что происходит.
Изображение

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

Подробнее здесь: https://stackoverflow.com/questions/797 ... throttling
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»