BYTEBOOK
Bytebook Docs • Spring Cloud / Microservices / Gateway
← Înapoi la Bytebook
PATH: DOCS / SPRING_CLOUD_GUIDE.HTML _
[00:00:00] DOCS_READY
DEMOS Main Archive JAVA LABS Enterprise PY LABS Neural Assets NODE LABS Async Runtime INFRA Control Center
BACKEND ARCHITECTURE GUIDES • JAVA SPRING CLOUD

Ghid Arhitectură Microservicii Java Spring Cloud pe VPS

Acest ghid descrie configurarea unei arhitecturi moderne de microservicii Java pe VPS-ul Ubuntu (63.250.40.142). Ghidul utilizează stack-ul standard de la Spring Cloud: Eureka Server (Service Discovery), Spring Cloud Gateway (Routing & Edge Server) și Resilience4j (Circuit Breaker & Fault Tolerance).

# Diagrama Arhitecturală pe VPS

[ Browser / Client ] │ HTTPS ▼ [ Caddy Reverse Proxy ] (caddy.bytebook.xyz) │ HTTP :8080 ▼ [ Spring Cloud Gateway ] (Port 8080) / │ \ (Rutează cererile prin numele serviciilor) / │ \ ▼ ▼ ▼ [User-Service] [Order-Service] [Payment-Service] (Port 8081) (Port 8082) (Port 8083) │ │ │ └─────────────┴─────────────┘ │ (Înregistrare & Heartbeat) ▼ [ Eureka Discovery Server ] (Port 8761)

1. Componenta 1: Eureka Server (Registru de Servicii Centralizat)

Eureka Server acționează ca un registru dinamic în care toate microserviciile își înregistrează adresa IP și portul la pornire.

A. Fișierul pom.xml (Eureka Server)

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

B. Clasa Principală Java

package com.bytebook.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

C. Fișierul application.yml

server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
  server:
    wait-time-in-ms-when-sync-empty: 0

2. Componenta 2: Microserviciul de Business (ex: user-service)

Fiecare microserviciu își va asuma un nume unic și se va înregistra automat în Eureka.

A. Fișierul pom.xml (user-service)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

B. Fișierul application.yml (user-service)

server:
  port: 8081

spring:
  application:
    name: user-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

C. Controller REST Java

package com.bytebook.userservice.controller;

import org.springframework.web.bind.annotation.*;
import java.util.Map;

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public Map<String, Object> getUserById(@PathVariable String id) {
        return Map.of(
            "userId", id,
            "name", "Alin Popescu",
            "email", "alin@bytebook.xyz",
            "serverPort", 8081
        );
    }
}

3. Componenta 3: Spring Cloud Gateway & Resilience4j

Gateway-ul primește cererile din exterior, le rutează inteligent prin Eureka către microservicii și oferă reziliență prin Circuit Breaker.

A. Fișierul pom.xml (Gateway)

<dependencies>
    <!-- Gateway Reactive WebFlux -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- Eureka Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!-- Resilience4j Circuit Breaker -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
    </dependency>
</dependencies>

B. Fișierul application.yml (Gateway Config)

server:
  port: 8080

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        - id: user-service-route
          uri: lb://USER-SERVICE
          predicates:
            - Path=/api/v1/users/**
          filters:
            - RewritePath=/api/v1/(?<segment>.*), /${segment}
            - name: CircuitBreaker
              args:
                name: userServiceCircuitBreaker
                fallbackUri: forward:/fallback/users

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

C. Controller de Fallback (Resilience4j)

package com.bytebook.gateway.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.Map;

@RestController
@RequestMapping("/fallback")
public class FallbackController {

    @GetMapping("/users")
    public Mono<Map<String, String>> userServiceFallback() {
        return Mono.just(Map.of(
            "status", "503 Service Unavailable",
            "message", "Serviciul de Utilizatori este indisponibil temporar. Incercati mai tarziu!",
            "circuitBreaker", "OPEN"
        ));
    }
}

4. Integrarea cu Caddy Reverse Proxy pe VPS

Caddy va fi singurul punct de intrare public SSL (https://api.bytebook.xyz), redirecționând tot traficul către Spring Cloud Gateway pe portul 8080.

  1. Deschide fișierul Caddyfile:
    nano /etc/caddy/Caddyfile
  2. Adaugă configurația pentru subdomeniul de API Gateway și Eureka Dashboard:
    # Dashboard-ul grafic Eureka (Opțional)
    eureka.bytebook.xyz {
        reverse_proxy localhost:8761
    }
    
    # API Gateway Unificat
    api.bytebook.xyz {
        reverse_proxy localhost:8080
    }
  3. Reîncarcă Caddy:
    systemctl reload caddy

5. Rularea Microserviciilor ca Servicii systemd 24/7

Pentru ca serviciile să pornească automat în ordinea corectă (întâi Eureka Server, apoi Gateway-ul și Microserviciile):

A. Serviciu Systemd Eureka (/etc/systemd/system/eureka-server.service)

[Unit]
Description=Spring Cloud Eureka Server
After=network.target

[Service]
User=root
WorkingDirectory=/root/projects/microservices/eureka-server
ExecStart=/usr/bin/java -jar target/eureka-server-1.0.0.jar
Restart=always

[Install]
WantedBy=multi-user.target

B. Serviciu Systemd API Gateway (/etc/systemd/system/api-gateway.service)

[Unit]
Description=Spring Cloud API Gateway
After=eureka-server.service
Requires=eureka-server.service

[Service]
User=root
WorkingDirectory=/root/projects/microservices/api-gateway
ExecStart=/usr/bin/java -jar target/api-gateway-1.0.0.jar
Restart=always

[Install]
WantedBy=multi-user.target

C. Activează și pornește serviciile

systemctl daemon-reload
systemctl enable --now eureka-server api-gateway

6. Testarea Arhitecturii

  1. Accesează https://eureka.bytebook.xyz în browser pentru a vedea interfața grafică Eureka și lista de servicii înregistrate (USER-SERVICE, API-GATEWAY).
  2. Trimite o cerere către API Gateway:
    curl https://api.bytebook.xyz/api/v1/users/100
  3. Testare Circuit Breaker: Oprește user-service (systemctl stop user-service) și repetă cererea curl. Vei primi instant răspunsul JSON de Fallback din Resilience4j, fără ca aplicația să returneze eroarea 500!