Consul – service discovery i configuration

TL;DR: Consul to narzędzie od HashiCorp do service discovery, health checking i przechowywania konfiguracji w systemach rozproszonych. Pozwala aplikacjom automatycznie znajdować się nawzajem bez hardkodowania adresów IP. Idealny dla architektury mikrousług, którą coraz więcej firm zaczyna adoptować w 2017 roku.

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.

Consul powstał w HashiCorp w 2014 roku i szybko zyskuje popularność jako alternatywa dla Eureka (Netflix) czy Apache Zookeeper. W 2017 roku wiele firm zaczyna go adoptować jako standard dla service discovery.

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
Wymagania wstępne: Podstawowa znajomość Java, Spring Boot, REST API i konceptów mikrousług. Pomocna będzie znajomość Docker i JSON.

Czym jest Consul?

Consul to wielofunkcyjne narzędzie do budowy systemów rozproszonych. W jego skład wchodzą cztery główne komponenty:

Service Discovery – automatyczne rejestrowanie i znajdowanie serwisów w sieci bez hardkodowania adresów
Health Checking – monitorowanie stanu serwisów i automatyczne usuwanie nieprawidłowych instancji
Key/Value Store – rozproszona baza danych do przechowywania konfiguracji i metadanych
Multi-Datacenter – wsparcie dla deployment across multiple data centers z automatyczną replikacją

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
Pro tip: W trybie development Consul działa na single node bez persistencji danych. Idealny do nauki i testów, ale nigdy nie używaj go w produkcji.

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 ResponseEntity getUser(@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

Po uruchomieniu aplikacji automatycznie zarejestruje się w Consul pod nazwą „user-service”. Consul będzie regularnie sprawdzał endpoint /health, aby upewnić się, że serwis jest dostępny.

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 ResponseEntity getOrderUser(@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();
    }
}
Uwaga: W powyższym przykładzie używamy prostego load balancingu (first available). W produkcji powinieneś użyć Spring Cloud LoadBalancer lub Ribbon dla bardziej zaawansowanych strategii.

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

Pro tip: Consul automatycznie usuwa serwisy, które są „critical” przez określony czas. To zapobiega przekierowaniu ruchu na niedziałające instancje.

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"
PortProtokółPrzeznaczenie
8500HTTPAPI i Web UI
8600DNSDNS queries
8300TCPServer RPC
8301TCP/UDPSerf LAN
8302TCP/UDPSerf WAN
Czy Consul to jedyne rozwiązanie do service discovery?

Nie, istnieją alternatywy jak Netflix Eureka, Apache Zookeeper czy etcd. Consul wyróżnia się prostotą konfiguracji i wbudowanym health checking.

Jak Consul radzi sobie z network partitions?

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.

Czy mogę używać Consul tylko do konfiguracji bez service discovery?

Tak, Consul KV store może działać niezależnie. Wiele firm używa go jako alternatywę dla Apache Zookeeper do przechowywania konfiguracji.

Jaką wydajność oferuje Consul?

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.

Czy Consul wymaga zewnętrznych zależności?

Nie, Consul to single binary bez zewnętrznych zależności. Można go uruchomić na dowolnym systemie z jednym plikiem wykonywalnym.

Jak zabezpieczyć Consul w produkcji?

Consul oferuje ACL (Access Control Lists) i TLS encryption. W produkcji zawsze włączaj authentication i encryption między nodes.

Typowy błąd: Używanie trybu development w produkcji. Development mode nie zachowuje danych po restarcie i nie oferuje high availability.

🚀 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:

Jakie są Twoje doświadczenia z service discovery? Używasz Consul czy innych rozwiązań w swoich projektach mikrousług?

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Przewijanie do góry