Dlaczego Consul jest ważny?
W świecie mikrousług, gdzie aplikacja składa się z dziesiątek niezależnych serwisów, największym wyzwaniem staje się pytanie: „jak serwis A znajdzie serwis B?” Tradycyjne podejście z konfiguracją IP i portów w plikach staje się niemożliwe do utrzymania. Consul rozwiązuje ten problem automatycznie.
Co się nauczysz:
- Jak zainstalować i skonfigurować Consul cluster
- Implementacja service discovery w aplikacjach Java
- Zarządzanie konfiguracją przez Consul KV store
- Health checking i monitoring serwisów
- Integracja z Spring Boot i Docker
Czym jest Consul?
Consul to wielofunkcyjne narzędzie do budowy systemów rozproszonych. W jego skład wchodzą cztery główne komponenty:
Instalacja i pierwsze uruchomienie
Rozpocznijmy od prostej instalacji Consul w trybie development:
# Pobieranie Consul (wersja 1.0.0 - najnowsza w październiku 2017) wget https://releases.hashicorp.com/consul/1.0.0/consul_1.0.0_linux_amd64.zip unzip consul_1.0.0_linux_amd64.zip # Uruchomienie w trybie development ./consul agent -dev -node=machine # Weryfikacja instalacji ./consul members
Po uruchomieniu Consul będzie dostępny na:
- HTTP API: http://localhost:8500
- DNS interface: localhost:8600
- Web UI: http://localhost:8500/ui
Service Discovery w praktyce
Stwórzmy prostą aplikację Spring Boot, która rejestruje się w Consul:
org.springframework.cloud spring-cloud-starter-consul-discovery 1.3.0.RELEASE org.springframework.boot spring-boot-starter-web 1.5.8.RELEASE
// UserServiceApplication.java @SpringBootApplication @EnableDiscoveryClient // Włącza service discovery public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } @RestController public static class UserController { @GetMapping("/users/{id}") public ResponseEntitygetUser(@PathVariable Long id) { // Symulacja pobierania użytkownika User user = new User(id, "John Doe", "john@example.com"); return ResponseEntity.ok(user); } @GetMapping("/health") public ResponseEntity health() { return ResponseEntity.ok("User service is healthy!"); } } static class User { private Long id; private String name; private String email; // konstruktor, gettery, settery public User(Long id, String name, String email) { this.id = id; this.name = name; this.email = email; } // gettery i settery... } }
# application.yml spring: application: name: user-service cloud: consul: host: localhost port: 8500 discovery: healthCheckPath: /health healthCheckInterval: 10s hostname: localhost instanceId: ${spring.application.name}:${random.int} server: port: 8080
Używanie service discovery do komunikacji
Teraz stwórzmy drugi serwis, który będzie komunikował się z user-service przez Consul:
// OrderServiceApplication.java @SpringBootApplication @EnableDiscoveryClient public class OrderServiceApplication { @Autowired private DiscoveryClient discoveryClient; @RestController public class OrderController { @Autowired private RestTemplate restTemplate; @GetMapping("/orders/{orderId}/user") public ResponseEntitygetOrderUser(@PathVariable Long orderId) { // Znajdź instancje user-service List instances = discoveryClient.getInstances("user-service"); if (instances.isEmpty()) { return ResponseEntity.status(503) .body("User service not available"); } // Pobierz pierwszą dostępną instancję ServiceInstance instance = instances.get(0); String userServiceUrl = instance.getUri().toString() + "/users/123"; try { String userResponse = restTemplate.getForObject( userServiceUrl, String.class); return ResponseEntity.ok(userResponse); } catch (Exception e) { return ResponseEntity.status(500) .body("Error calling user service: " + e.getMessage()); } } } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
Zarządzanie konfiguracją z Consul KV
Consul oferuje rozproszoną bazę key-value do przechowywania konfiguracji. Oto jak z niej korzystać:
# Dodawanie konfiguracji przez HTTP API curl -X PUT -d 'user-service-db-url=jdbc:postgresql://localhost:5432/users' \ http://localhost:8500/v1/kv/config/user-service/database-url curl -X PUT -d '10' \ http://localhost:8500/v1/kv/config/user-service/max-connections # Pobieranie konfiguracji curl http://localhost:8500/v1/kv/config/user-service/database-url
Integracja z Spring Boot:
org.springframework.cloud spring-cloud-starter-consul-config 1.3.0.RELEASE
# bootstrap.yml (ładowany przed application.yml) spring: application: name: user-service cloud: consul: config: enabled: true prefix: config format: KEY_VALUE data-key: data
// Używanie konfiguracji w kodzie @Component @RefreshScope // Pozwala na refresh konfiguracji bez restartu public class DatabaseConfig { @Value("${database-url:jdbc:h2:mem:testdb}") private String databaseUrl; @Value("${max-connections:5}") private int maxConnections; // gettery public String getDatabaseUrl() { return databaseUrl; } public int getMaxConnections() { return maxConnections; } }
Health Checking i monitoring
Consul automatycznie monitoruje stan serwisów. Możesz definiować własne health checks:
# application.yml - zaawansowane health checking spring: cloud: consul: discovery: health-check-path: /actuator/health health-check-interval: 15s health-check-timeout: 3s health-check-critical-timeout: 30s # Włączenie Spring Boot Actuator management: endpoints: web: exposure: include: health,info endpoint: health: show-details: always
Docker i Consul
W 2017 roku Docker zyskuje ogromną popularność. Oto jak uruchomić Consul z Docker:
# docker-compose.yml dla development setup version: '3' services: consul: image: consul:1.0.0 ports: - "8500:8500" - "8600:8600/udp" command: consul agent -dev -ui -client=0.0.0.0 user-service: build: ./user-service environment: - SPRING_CLOUD_CONSUL_HOST=consul depends_on: - consul ports: - "8080:8080"
Port | Protokół | Przeznaczenie |
---|---|---|
8500 | HTTP | API i Web UI |
8600 | DNS | DNS queries |
8300 | TCP | Server RPC |
8301 | TCP/UDP | Serf LAN |
8302 | TCP/UDP | Serf WAN |
Nie, istnieją alternatywy jak Netflix Eureka, Apache Zookeeper czy etcd. Consul wyróżnia się prostotą konfiguracji i wbudowanym health checking.
Consul używa algorytmu Raft do osiągnięcia consensus. W przypadku network partition, tylko partycja z większością nodes może akceptować zmiany.
Tak, Consul KV store może działać niezależnie. Wiele firm używa go jako alternatywę dla Apache Zookeeper do przechowywania konfiguracji.
Consul może obsłużyć tysiące serwisów na pojedynczym cluster. W testach HashiCorp cluster 5 nodes obsługiwał 10,000 serwisów bez problemów.
Nie, Consul to single binary bez zewnętrznych zależności. Można go uruchomić na dowolnym systemie z jednym plikiem wykonywalnym.
Consul oferuje ACL (Access Control Lists) i TLS encryption. W produkcji zawsze włączaj authentication i encryption między nodes.
🚀 Zadanie dla Ciebie
Stwórz cluster trzech serwisów: user-service, order-service i notification-service. Każdy serwis powinien rejestrować się w Consul i komunikować z innymi przez service discovery. Dodaj custom health check, który sprawdza połączenie z bazą danych.
Przydatne zasoby:
- Oficjalna dokumentacja Consul
- Spring Cloud Consul docs
- HashiCorp Learn – Consul tutorials
- Consul na GitHub
Jakie są Twoje doświadczenia z service discovery? Używasz Consul czy innych rozwiązań w swoich projektach mikrousług?