← Назад к вопросам

Что такое асинхронный клиент?

2.3 Middle🔥 121 комментариев
#REST API и микросервисы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Асинхронный клиент в Java

Определение

Асинхронный клиент — это компонент, который отправляет запросы на сервер без блокирования текущего потока выполнения. Вместо ожидания ответа, приложение продолжает работать и обрабатывает ответ позже, когда он будет получен.

Синхронный vs Асинхронный

Синхронный клиент (блокирующий)

String response = httpClient.get("https://api.example.com/users");
System.out.println("Ответ: " + response);
String nextTask = performNextAction();

Проблемы:

  • Поток заблокирован во время ожидания
  • Если много запросов — нужно много потоков
  • Плохо масштабируется

Асинхронный клиент (неблокирующий)

httpClient.getAsync("https://api.example.com/users")
    .thenAccept(response -> {
        System.out.println("Ответ: " + response);
    });

String nextTask = performNextAction();
System.out.println("Запрос отправлен, продолжаем работу");

Преимущества:

  • Поток не блокируется
  • Один поток может обрабатывать множество запросов
  • Лучше масштабируется
  • Выше пропускная способность

Java технологии для асинхронных клиентов

1. Apache HttpAsyncClient

CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
httpClient.start();

HttpGet request = new HttpGet("https://api.example.com/users");

Future<HttpResponse> future = httpClient.execute(request, 
    new FutureCallback<HttpResponse>() {
        public void completed(HttpResponse response) {
            System.out.println("Успех: " + response.getStatusLine());
        }
        
        public void failed(Exception ex) {
            System.out.println("Ошибка: " + ex.getMessage());
        }
        
        public void cancelled() {
            System.out.println("Отменено");
        }
    }
);

System.out.println("Запрос отправлен, продолжаем");
HttpResponse response = future.get();
httpClient.close();

2. Spring WebClient (современный подход)

@Service
public class UserClient {
    private final WebClient webClient;
    
    public UserClient(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("https://api.example.com").build();
    }
    
    public Mono<UserDto> getUser(Long id) {
        return webClient
            .get()
            .uri("/users/{id}", id)
            .retrieve()
            .bodyToMono(UserDto.class);
    }
    
    public Flux<UserDto> getAllUsers() {
        return webClient
            .get()
            .uri("/users")
            .retrieve()
            .bodyToFlux(UserDto.class);
    }
}

@RestController
public class UserController {
    private final UserClient userClient;
    
    public UserController(UserClient userClient) {
        this.userClient = userClient;
    }
    
    @GetMapping("/users/{id}")
    public Mono<UserDto> getUser(@PathVariable Long id) {
        return userClient.getUser(id);
    }
}

3. RestTemplate (синхронный, устарел)

@Service
public class UserService {
    private final RestTemplate restTemplate;
    
    public UserDto getUser(Long id) {
        return restTemplate.getForObject(
            "https://api.example.com/users/{id}",
            UserDto.class,
            id
        );
    }
}

4. Retrofit (асинхронный для REST API)

public interface UserApi {
    @GET("/users/{id}")
    Call<UserDto> getUser(@Path("id") Long id);
}

UserApi api = retrofit.create(UserApi.class);
Call<UserDto> call = api.getUser(1);

call.enqueue(new Callback<UserDto>() {
    public void onResponse(Call<UserDto> call, Response<UserDto> response) {
        System.out.println("Пользователь: " + response.body());
    }
    
    public void onFailure(Call<UserDto> call, Throwable t) {
        System.out.println("Ошибка: " + t.getMessage());
    }
});

CompletableFuture

CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> {
        return httpClient.get("https://api.example.com/data");
    })
    .thenApply(response -> response.toUpperCase())
    .thenAccept(result -> {
        System.out.println("Результат: " + result);
    })
    .exceptionally(ex -> {
        System.out.println("Ошибка: " + ex.getMessage());
        return null;
    });

System.out.println("Асинхронная операция запущена");

Project Reactor

@Service
public class ReactiveUserService {
    private final WebClient webClient;
    
    public Mono<List<UserDto>> getAllUsers() {
        return webClient
            .get()
            .uri("/users")
            .retrieve()
            .bodyToFlux(UserDto.class)
            .collectList();
    }
    
    public Flux<UserDto> streamUsers() {
        return webClient
            .get()
            .uri("/users")
            .retrieve()
            .bodyToFlux(UserDto.class);
    }
}

Java 11+ встроенный HttpClient

HttpClient httpClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .build();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .build();

httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println)
    .join();

Преимущества асинхронных клиентов

  1. Масштабируемость — один поток обрабатывает много запросов
  2. Производительность — нет блокирования потоков
  3. Ресурсы — меньше памяти
  4. Отзывчивость — UI не замерзает
  5. Пропускная способность — больше запросов в единицу времени

Когда использовать

  • Асинхронные: веб-приложения, микросервисы, высоконагруженные системы
  • Синхронные: простые скрипты, batch обработка

Современный подход (2024+)

Рекомендуется использовать:

  • Spring WebClient — для Spring приложений
  • Project Reactor — для реактивного стека
  • Java HttpClient — встроенный клиент (Java 11+)
Что такое асинхронный клиент? | PrepBro