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-экосистеме.