Gymterview
middle

Как организовать синхронное взаимодействие микросервисов через REST?

В Spring Boot для синхронного взаимодействия между микросервисами используются HTTP-клиенты: RestTemplate (устаревший), WebClient (рекомендуемый), Declarative HTTP Client (Spring 6+) и OpenFeign.

1. RestTemplate (устаревший, но ещё встречается)
@Service
public class PaymentService {
    private final RestTemplate restTemplate;

    public PaymentService(RestTemplateBuilder builder) {
        this.restTemplate = builder
            .rootUri("http://customer-service")
            .setConnectTimeout(Duration.ofSeconds(3))
            .setReadTimeout(Duration.ofSeconds(5))
            .build();
    }

    public CustomerDto getCustomer(Long customerId) {
        return restTemplate.getForObject(
            "/api/customers/{id}", CustomerDto.class, customerId
        );
    }
}
2. WebClient (реактивный, рекомендуется)
@Service
public class PaymentService {
    private final WebClient webClient;

    public PaymentService(WebClient.Builder builder) {
        this.webClient = builder
            .baseUrl("http://customer-service")
            .build();
    }

    public Mono<CustomerDto> getCustomer(Long customerId) {
        return webClient.get()
            .uri("/api/customers/{id}", customerId)
            .retrieve()
            .bodyToMono(CustomerDto.class);
    }
}
3. Declarative HTTP Client (Spring 6+ / Spring Boot 3+)
// Декларативный клиент — аналог Feign, но нативный Spring
@HttpExchange("/api/customers")
public interface CustomerClient {

    @GetExchange("/{id}")
    CustomerDto getCustomer(@PathVariable Long id);

    @PostExchange
    CustomerDto createCustomer(@RequestBody CreateCustomerRequest request);
}

@Configuration
public class ClientConfig {
    @Bean
    public CustomerClient customerClient(WebClient.Builder builder) {
        WebClient webClient = builder.baseUrl("http://customer-service").build();
        HttpServiceProxyFactory factory = HttpServiceProxyFactory
            .builderFor(WebClientAdapter.create(webClient))
            .build();
        return factory.createClient(CustomerClient.class);
    }
}
4. OpenFeign (Spring Cloud)
@FeignClient(name = "customer-service", url = "${customer-service.url}")
public interface CustomerClient {

    @GetMapping("/api/customers/{id}")
    CustomerDto getCustomer(@PathVariable("id") Long id);
}

Важные моменты

  • Всегда устанавливайте таймауты (connect timeout, read timeout).
  • Используйте Circuit Breaker для защиты от каскадных сбоев.
  • Применяйте retry с exponential backoff для transient errors.
  • При использовании Service Discovery имена сервисов резолвятся автоматически.

На собеседовании: знайте эволюцию: RestTemplate -> WebClient -> Declarative HTTP Client. В Spring Boot 3+ рекомендуется Declarative HTTP Client или WebClient. Feign остаётся в Spring Cloud-экосистеме.