Skip to main content
Innovation|Innovation

Spring Cloud తో Microservices: పెద్ద Apps ను చిన్న ముక్కలుగా విభజించడం

Spring Cloud తో microservices build చేయడానికి beginner-friendly guide — API Gateway, Eureka service discovery, Config Server, Resilience4j circuit breakers, load balancing, Feign clients, WebClient, Micrometer మరియు Zipkin తో distributed tracing, మరియు inter-service authentication.

8 ఏప్రిల్, 202613 min read

Microservices అంటే ఏమిటి మరియు మీరు ఎందుకు పట్టించుకోవాలి?

మీరు ఒక పెద్ద రెస్టారెంట్ నడుపుతున్నారని ఊహించుకోండి, అక్కడ ఒక భారీ వంటగది అన్నింటినీ చేస్తుంది: appetizers, main courses, desserts, drinks, మరియు billing. Dessert chef సెలవులో ఉంటే, మొత్తం రెస్టారెంట్ మూసివేయబడుతుంది. అది monolith — అన్నీ చేసే ఒక పెద్ద application.

ఇప్పుడు బదులుగా ఒక food court ని ఊహించుకోండి. Pizza counter, burger counter, juice bar, మరియు billing kiosk ఉన్నాయి. ప్రతి counter స్వతంత్రంగా నడుస్తుంది. Juice bar పాడైతే, మిగతావన్నీ serve చేస్తూనే ఉంటాయి. అదే microservices — ప్రతి ఒక్కటి ఒక పనిని బాగా చేసే చాలా చిన్న, స్వతంత్ర services.

Spring Cloud జావా developers కు ఈ చిన్న services ను build, connect మరియు manage చేయడానికి ఒక toolbox ఇస్తుంది. ప్రతి tool ను చూద్దాం.

Monolith vs. Microservices: పక్కపక్కన పోలిక

అంశంMonolith (పెద్ద రెస్టారెంట్)Microservices (Food Court)
Deploymentఒక పెద్ద JAR — మొత్తం deploy చేయాలిప్రతి service స్వతంత్రంగా deploy అవుతుంది
Scalingఒక భాగం busy అయినా అన్నింటినీ scale చేయాలిBusy counter (service) ను మాత్రమే scale చేయండి
Failureఒక bug మొత్తం app ను crash చేయగలదుఒక service fail అయినా, మిగతావి నడుస్తూనే ఉంటాయి
Team ownershipఅందరూ ఒకే codebase లో పని చేస్తారుప్రతి team తన own service ను own చేస్తుంది
Tech stackఒక language/framework లో lock అవుతుందిప్రతి service వేరే tech ఉపయోగించవచ్చు
Complexityమొదట simple, పెరిగినప్పుడు కష్టంమొదటి రోజు నుండే ఎక్కువ moving parts

నియమం: చిన్న project కోసం monolith తో మొదలు పెట్టండి. మీ team మరియు traffic మొనోలిత్ bottleneck అయ్యే వరకు పెరిగినప్పుడు microservices కు move అవ్వండి.

API Gateway (Spring Cloud Gateway)

API Gateway ను హోటల్ యొక్క front desk గా భావించండి. Guests (clients) నేరుగా kitchen లేదా housekeeping కు వెళ్ళరు. వారు front desk కు వెళ్తారు, అది వారిని సరైన department కు route చేస్తుంది. Gateway HTTP requests కు అదే చేస్తుంది.

Spring Cloud Gateway మీ అన్ని microservices ముందు కూర్చుంటుంది. ఇది handle చేస్తుంది:

  • Routing/api/orders/** ను order-service కు, /api/users/** ను user-service కు పంపండి
  • Load balancing — ఒక service యొక్క multiple instances లో requests ను spread చేయండి
  • Filters — Forward చేయడానికి ముందు headers add చేయండి, rate-limit, log, లేదా authenticate చేయండి
  • Single entry point — Clients కు ఒక URL మాత్రమే తెలియాలి

Gateway Configuration (application.yml)

spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1

        - id: inventory-service
          uri: lb://INVENTORY-SERVICE
          predicates:
            - Path=/api/inventory/**
          filters:
            - StripPrefix=1

        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1

        - id: notification-service
          uri: lb://NOTIFICATION-SERVICE
          predicates:
            - Path=/api/notifications/**
          filters:
            - StripPrefix=1

lb:// prefix gateway కు load balancing ఉపయోగించమని మరియు service registry (Eureka) నుండి service ను name ద్వారా చూడమని చెబుతుంది. StripPrefix=1 forward చేయడానికి ముందు /api ను తొలగిస్తుంది, కాబట్టి /api/orders/123 order-service కు చేరుకున్నప్పుడు /orders/123 అవుతుంది.

Custom Global Filter (Java)

ప్రతి request ను log చేయడం వంటి cross-cutting logic ను global filter ఉపయోగించి add చేయవచ్చు:

@Component
public class LoggingFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(LoggingFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        String method = exchange.getRequest().getMethod().name();
        log.info("Incoming request: {} {}", method, path);

        return chain.filter(exchange).then(Mono.fromRunnable(() ->
            log.info("Response status: {}", exchange.getResponse().getStatusCode())
        ));
    }

    @Override
    public int getOrder() {
        return -1; // ఇతర filters కంటే ముందు run అవుతుంది
    }
}

Service Discovery (Eureka)

Food court లో, ఈ రోజు ఏ counters open అని front desk కు ఎలా తెలుసు? ఎవరైనా live list ను maintain చేస్తారు. Eureka సరిగ్గా అదే చేస్తుంది. ప్రతి microservice start అయినప్పుడు Eureka తో register అవుతుంది, మరియు Eureka ఏ services alive గా ఉన్నాయి మరియు అవి ఎక్కడ ఉన్నాయి (IP + port) ను track చేస్తుంది.

Service discovery లేకుండా, మీరు http://192.168.1.10:8080 వంటి URLs ను hardcode చేయాల్సి ఉంటుంది. ఆ server move అయితే లేదా మీరు రెండో instance add చేస్తే, అన్నీ break అవుతాయి. Eureka తో, services "నేను ORDER-SERVICE ను" అని చెబుతాయి మరియు ఇతర services వాటిని name ద్వారా కనుగొంటాయి.

Eureka Server Setup చేయడం

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServerApplication.class, args);
    }
}
# Eureka Server application.yml
server:
  port: 8761

eureka:
  client:
    register-with-eureka: false   # Server తనతో తాను register అవ్వదు
    fetch-registry: false

Service ను Register చేయడం (Eureka Client)

ప్రతి microservice Eureka client dependency మరియు కొన్ని config lines add చేస్తుంది:

# order-service application.yml
spring:
  application:
    name: ORDER-SERVICE

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

ఇప్పుడు Eureka కు తెలుసు: "ORDER-SERVICE 192.168.1.10:8081 లో run అవుతోంది, మరియు 192.168.1.11:8081 లో కూడా." ఇతర services దాన్ని name ద్వారా కనుగొనగలవు.

Centralized Configuration (Spring Cloud Config Server)

Food court లో ప్రతి counter దగ్గర దాని own recipe book ఉందని ఊహించుకోండి. అన్ని recipes లో salt level మార్చాలంటే, మీరు ప్రతి counter కు ఒక్కొక్కటిగా వెళ్ళాలి. అది చాలా కష్టం.

Spring Cloud Config Server ఒక చోట (సాధారణంగా Git repository) store చేయబడిన shared recipe book లాంటిది. అన్ని services ఈ central location నుండి తమ configuration ను pull చేస్తాయి. ఒకసారి మార్చండి, మరియు ప్రతి service దాన్ని pick up చేస్తుంది.

Config Server Setup

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
# Config Server application.yml
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-org/config-repo
          default-label: main
          search-paths: '{application}'

Client-Side Config (order-service)

# order-service application.yml
spring:
  application:
    name: order-service
  config:
    import: optional:configserver:http://localhost:8888

Config server Git repo లో order-service.yml అనే file ను వెతికి serve చేస్తుంది. మీరు profiles కూడా ఉపయోగించవచ్చు: order-service-dev.yml, order-service-prod.yml.

Runtime లో Config Refresh చేయడం

Beans ను @RefreshScope తో mark చేసి POST /actuator/refresh hit చేయండి — bean service restart చేయకుండా config ను re-read చేస్తుంది:

@RestController
@RefreshScope
public class OrderController {

    @Value("${order.max-items:50}")
    private int maxItems;

    @GetMapping("/orders/max-items")
    public int getMaxItems() {
        return maxItems;
    }
}

Circuit Breaker (Resilience4j)

Circuit breaker మీ ఇంట్లో fuse లాంటిది. Wire ద్వారా చాలా ఎక్కువ electricity flow అయితే, మీ appliances fire catch కాకుండా fuse break అవుతుంది. Problem fix చేసిన తర్వాత, fuse ను తిరిగి flip చేస్తారు.

Microservices లో, inventory-service down అయితే, order-service requests తో దాన్ని hammer చేస్తూ ఉండకూడదు. అది resources waste చేస్తుంది మరియు విషయాలను మరింత worse చేస్తుంది. బదులుగా, circuit breaker "trips" అయి immediately fallback response return చేస్తుంది.

మూడు States

Stateఏమి జరుగుతుందిAnalogy
CLOSEDఅంతా normal. Requests service కు flow అవుతాయి.Fuse intact గా ఉంది. Electricity normally flow అవుతోంది.
OPENచాలా failures! Requests immediately fallback తో reject అవుతాయి.Fuse blow అయింది. Electricity flow అవ్వదు. Appliances safe.
HALF-OPENService recover అయిందో చూడటానికి కొన్ని test requests ను allow చేస్తుంది.Fuse తిరిగి on చేసి test చేయడానికి ఒక appliance plug in చేస్తారు.

Flow: CLOSED (normal) → failures pile up → OPEN (requests block) → wait timer expire → HALF-OPEN (కొన్ని test) → tests pass అయితే → తిరిగి CLOSED. Tests fail అయితే → తిరిగి OPEN.

Resilience4j Configuration

# application.yml
resilience4j:
  circuitbreaker:
    instances:
      inventoryService:
        sliding-window-size: 10            # చివరి 10 calls చూడండి
        failure-rate-threshold: 50         # 50% calls fail అయితే trip అవుతుంది
        wait-duration-in-open-state: 30s   # 30 seconds OPEN గా ఉంటుంది
        permitted-number-of-calls-in-half-open-state: 5  # 5 calls తో test
        automatic-transition-from-open-to-half-open-enabled: true

  retry:
    instances:
      inventoryService:
        max-attempts: 3
        wait-duration: 2s

  timelimiter:
    instances:
      inventoryService:
        timeout-duration: 5s              # 5 seconds తర్వాత give up

Java Code లో Circuit Breaker

@Service
public class OrderService {

    private final InventoryClient inventoryClient;

    public OrderService(InventoryClient inventoryClient) {
        this.inventoryClient = inventoryClient;
    }

    @CircuitBreaker(name = "inventoryService", fallbackMethod = "inventoryFallback")
    @Retry(name = "inventoryService")
    @TimeLimiter(name = "inventoryService")
    public CompletableFuture<Boolean> checkStock(String sku, int quantity) {
        return CompletableFuture.supplyAsync(() ->
            inventoryClient.isInStock(sku, quantity)
        );
    }

    // Fallback: circuit OPEN అయినప్పుడు లేదా retries తర్వాత call fail అయినప్పుడు run అవుతుంది
    public CompletableFuture<Boolean> inventoryFallback(String sku, int quantity, Throwable t) {
        log.warn("Inventory service unavailable for SKU {}. Assuming out of stock.", sku);
        return CompletableFuture.completedFuture(false);
    }
}

Circuit OPEN అయినప్పుడు, inventoryFallback method inventory-service ను call చేయడానికి try కూడా చేయకుండా instantly run అవుతుంది. ఇది మీ service ను మరియు struggling downstream service ను protect చేస్తుంది.

Client-Side Load Balancing

Food court లో pizza counter చాలా popular అయితే, మీరు రెండో pizza counter open చేస్తారు. ఇప్పుడు front desk decide చేయాలి: "ఈ customer ను counter A కు పంపాలా లేదా counter B కు?" అదే load balancing.

Spring Cloud Spring Cloud LoadBalancer (Ribbon successor) ను ఒక service యొక్క multiple instances లో requests distribute చేయడానికి ఉపయోగిస్తుంది. ఇది Eureka తో automatically పని చేస్తుంది — hardcoded URL బదులు service name ఉపయోగించండి.

@Configuration
public class WebClientConfig {

    @Bean
    @LoadBalanced   // ఈ annotation client-side load balancing enable చేస్తుంది
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

@Service
public class OrderService {

    private final WebClient.Builder webClientBuilder;

    public OrderService(WebClient.Builder webClientBuilder) {
        this.webClientBuilder = webClientBuilder;
    }

    public Mono<InventoryResponse> checkInventory(String sku) {
        // "INVENTORY-SERVICE" Eureka నుండి look up, load-balanced
        return webClientBuilder.build()
            .get()
            .uri("http://INVENTORY-SERVICE/inventory/{sku}", sku)
            .retrieve()
            .bodyToMono(InventoryResponse.class);
    }
}

@LoadBalanced annotation Spring కు request ను intercept చేయమని, Eureka నుండి INVENTORY-SERVICE యొక్క అన్ని instances ను look up చేయమని, మరియు strategy (default round-robin) ఉపయోగించి ఒకదాన్ని pick చేయమని చెబుతుంది.

Inter-Service Communication

Food court లో, counters ఒకరితో ఒకరు మాట్లాడుకోవాలి. Burger counter inventory counter ను అడగవచ్చు: "మన దగ్గర ఇంకా buns ఉన్నాయా?" Services communicate చేసే రెండు ప్రధాన మార్గాలు ఉన్నాయి:

1. Feign Clients (Declarative REST)

Feign మీరు local Java method ను call చేస్తున్నట్లు మరొక service ను call చేయడానికి అనుమతిస్తుంది. మీరు ఒక interface రాస్తారు, మరియు Feign HTTP client ను build చేస్తుంది.

// Client ను define చేయండి — ఒక regular Java interface లా కనిపిస్తుంది
@FeignClient(name = "INVENTORY-SERVICE")
public interface InventoryClient {

    @GetMapping("/inventory/{sku}")
    InventoryResponse getInventory(@PathVariable String sku);

    @PostMapping("/inventory/reserve")
    ReservationResponse reserveStock(@RequestBody ReservationRequest request);
}

// ఉపయోగించండి — ఏదైనా Spring bean లా inject చేసి call చేయండి
@Service
public class OrderService {

    private final InventoryClient inventoryClient;

    public OrderService(InventoryClient inventoryClient) {
        this.inventoryClient = inventoryClient;
    }

    public OrderResponse placeOrder(OrderRequest request) {
        // ఇది local method call లా కనిపిస్తుంది, కానీ ఇది inventory-service కు HTTP GET
        InventoryResponse stock = inventoryClient.getInventory(request.getSku());

        if (stock.getQuantity() < request.getQuantity()) {
            throw new InsufficientStockException("Not enough stock for: " + request.getSku());
        }

        // Stock ను reserve చేయండి
        inventoryClient.reserveStock(new ReservationRequest(
            request.getSku(), request.getQuantity()
        ));

        return new OrderResponse("Order placed successfully");
    }
}

మీ main class లో Feign ను enable చేయండి:

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

2. WebClient (Reactive/Non-Blocking)

WebClient modern, non-blocking alternative. Reactive streams అవసరమైనప్పుడు లేదా parallel లో multiple calls చేయాలనుకున్నప్పుడు ఉపయోగించండి:

@Service
public class OrderService {

    private final WebClient.Builder webClientBuilder;

    public OrderService(@LoadBalanced WebClient.Builder webClientBuilder) {
        this.webClientBuilder = webClientBuilder;
    }

    // Sequential call
    public Mono<InventoryResponse> checkInventory(String sku) {
        return webClientBuilder.build()
            .get()
            .uri("http://INVENTORY-SERVICE/inventory/{sku}", sku)
            .retrieve()
            .bodyToMono(InventoryResponse.class);
    }

    // Parallel calls — inventory check మరియు user info ఒకే సమయంలో get చేయండి
    public Mono<OrderSummary> getOrderSummary(String sku, String userId) {
        Mono<InventoryResponse> inventory = webClientBuilder.build()
            .get()
            .uri("http://INVENTORY-SERVICE/inventory/{sku}", sku)
            .retrieve()
            .bodyToMono(InventoryResponse.class);

        Mono<UserResponse> user = webClientBuilder.build()
            .get()
            .uri("http://USER-SERVICE/users/{id}", userId)
            .retrieve()
            .bodyToMono(UserResponse.class);

        // రెండు calls ఒకే సమయంలో జరుగుతాయి!
        return Mono.zip(inventory, user, (inv, usr) ->
            new OrderSummary(usr.getName(), inv.getQuantity(), inv.getPrice())
        );
    }
}

ఏది ఎప్పుడు ఉపయోగించాలి?

FeatureFeign ClientWebClient
StyleDeclarative (interface-based)Programmatic (builder-based)
Blocking?Yes (by default)No (non-blocking/reactive)
Parallel callsకష్టం (threads అవసరం)Mono.zip() తో easy
Best forSimple service-to-service REST callsHigh-throughput reactive systems

Distributed Tracing (Micrometer + Zipkin)

Food court లో ఒక customer bad meal గురించి complaint చేస్తే, ఏ counter దాన్ని చేసిందో ఎలా trace చేస్తారు? ప్రతి counter ను touch చేసిన order ను follow చేసే receipt number అవసరం.

Microservices లో, ఒక user request 5 services ద్వారా hop చేయవచ్చు. ఏదైనా wrong అయితే, మీకు తెలియాలి: "సరిగ్గా ఎక్కడ fail అయింది?" Distributed tracing ప్రతి request కు unique Trace ID assign చేసి ప్రతి service hop లో track చేస్తుంది.

ముఖ్య Concepts

  • Trace — ఒక request యొక్క మొత్తం journey (full receipt లాంటిది). ఒక Trace ID ఉంటుంది.
  • Span — Journey లో ఒక step (ఒక counter యొక్క work లాంటిది). ప్రతి span కు Span ID ఉంటుంది.
  • Parent-Child — Order-service inventory-service ను call చేస్తే, inventory span order span యొక్క child.

Tracing Setup చేయడం

ప్రతి service కు ఈ dependencies add చేయండి:

<!-- Micrometer Tracing + Brave bridge -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>

<!-- Zipkin కు traces పంపండి -->
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>
# application.yml (ప్రతి service కు add చేయండి)
management:
  tracing:
    sampling:
      probability: 1.0   # 100% requests sample చేయండి (production లో 10% కోసం 0.1 ఉపయోగించండి)
  zipkin:
    tracing:
      endpoint: http://localhost:9411/api/v2/spans

logging:
  pattern:
    level: "%5p [${spring.application.name},%X{traceId},%X{spanId}]"

ఈ logging pattern తో, ప్రతి log line లో service name, trace ID, మరియు span ID ఉంటాయి:

INFO [order-service,abc123def456,span789] Placing order for SKU: WIDGET-001
INFO [inventory-service,abc123def456,span012] Checking stock for SKU: WIDGET-001
INFO [notification-service,abc123def456,span345] Sending confirmation email

Trace ID abc123def456 మూడు services లో same గా ఉందని గమనించండి. Zipkin లో దాన్ని search చేసి మొత్తం request journey ను timeline గా visualize చేయవచ్చు.

Inter-Service Authentication

Food court లో, ఎవరైనా kitchen లోకి నడిచి వెళ్ళలేరు. Staff వారు ఎవరో prove చేయడానికి ID badges wear చేస్తారు. Microservices కు కూడా అదే అవసరం — order-service inventory-service ను call చేసినప్పుడు, inventory-service caller legitimate అని మరియు ఏదో random outsider కాదని verify చేయాలి.

Approach 1: JWT Token Propagation

User యొక్క JWT token service నుండి service కు pass అవుతుంది. ప్రతి service దాన్ని validate చేస్తుంది.

// Feign RequestInterceptor — JWT ను automatically forward చేస్తుంది
@Component
public class AuthFeignInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        // ప్రస్తుత request యొక్క Authorization header ను get చేయండి
        ServletRequestAttributes attributes =
            (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        if (attributes != null) {
            String authHeader = attributes.getRequest().getHeader("Authorization");
            if (authHeader != null) {
                template.header("Authorization", authHeader);
            }
        }
    }
}

Approach 2: Internal Services కోసం API Key

User నుండి originate కాని service-to-service calls కోసం (e.g., scheduled jobs), shared API key ఉపయోగించండి:

// Sending side — outgoing requests కు API key add చేయండి
@Component
public class InternalApiKeyInterceptor implements RequestInterceptor {

    @Value("${internal.api-key}")
    private String apiKey;

    @Override
    public void apply(RequestTemplate template) {
        template.header("X-Internal-API-Key", apiKey);
    }
}

// Receiving side — incoming requests పై API key validate చేయండి
@Component
public class ApiKeyFilter extends OncePerRequestFilter {

    @Value("${internal.api-key}")
    private String expectedApiKey;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String apiKey = request.getHeader("X-Internal-API-Key");

        // Valid API key లేదా JWT ద్వారా already authenticated అయితే allow చేయండి
        if (expectedApiKey.equals(apiKey) || isAlreadyAuthenticated()) {
            filterChain.doFilter(request, response);
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("{\"error\": \"Invalid or missing API key\"}");
        }
    }

    private boolean isAlreadyAuthenticated() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return auth != null && auth.isAuthenticated()
               && !(auth instanceof AnonymousAuthenticationToken);
    }
}

Internal Endpoints కోసం Spring Security Config

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/**").permitAll()
                .requestMatchers("/internal/**").hasRole("SERVICE")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
            .build();
    }
}

అన్నీ కలిపి చూద్దాం: పూర్తి Architecture

ఒక typical microservices setup లో అన్ని pieces ఎలా fit అవుతాయో ఇక్కడ ఉంది:

                          [Client / Browser]
                                |
                         [API Gateway :8080]
                          /     |     \
                         /      |      \
              [Order :8081] [User :8082] [Notification :8083]
                  |              |
           [Inventory :8084]    |
                  |              |
              [Eureka :8761]  (Service Discovery)
              [Config :8888]  (Central Config)
              [Zipkin :9411]  (Distributed Tracing)
  1. Client POST /api/orders ను API Gateway కు పంపుతుంది
  2. Gateway Eureka లో ORDER-SERVICE ను look up చేసి, ఒక instance కు route చేస్తుంది
  3. Order-service Feign ద్వారా INVENTORY-SERVICE ను call చేస్తుంది (load-balanced, circuit-breaker protected)
  4. Order-service confirmation పంపడానికి NOTIFICATION-SERVICE ను call చేస్తుంది
  5. ప్రతి hop Micrometer + Zipkin ద్వారా same Trace ID తో trace అవుతుంది
  6. అన్ని services Config Server నుండి config pull చేస్తాయి

Microservices కోసం Best Practices

  • ప్రతి service కు ఒక database — Services మధ్య database share చేయకండి. ప్రతి service దాని data ను own చేస్తుంది.
  • API-first design — Code రాయడానికి ముందు మీ REST contracts (OpenAPI/Swagger) define చేయండి.
  • Health checks — Spring Boot Actuator యొక్క /actuator/health endpoint ఉపయోగించండి. Eureka మీ service alive గా ఉందో తెలుసుకోవడానికి దాన్ని ఉపయోగిస్తుంది.
  • Graceful degradation — ఎల్లప్పుడూ fallback ఉంచండి. Downstream service down అయితే, cached data లేదా safe default return చేయండి.
  • Centralized logging — ప్రతి log line లో Trace ID ఉపయోగించండి. Logs ను central place (ELK stack, Grafana Loki) కు ship చేయండి.
  • అన్నింటినీ containerize చేయండి — ప్రతి service కు దాని own Docker image ఉంటుంది. Orchestrate చేయడానికి Kubernetes లేదా Docker Compose ఉపయోగించండి.
  • Testing automate చేయండి — Unit tests + integration tests + contract tests (Spring Cloud Contract).

Starter Dependencies (pom.xml)

Spring Cloud microservice కు అవసరమైన key dependencies ఇక్కడ ఉన్నాయి:

<properties>
    <java.version>21</java.version>
    <spring-cloud.version>2024.0.1</spring-cloud.version>
</properties>

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Eureka Client (Service Discovery) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!-- Config Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

    <!-- Feign Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!-- Resilience4j Circuit Breaker -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
    </dependency>

    <!-- Micrometer Tracing -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-tracing-bridge-brave</artifactId>
    </dependency>

    <!-- Zipkin Reporter -->
    <dependency>
        <groupId>io.zipkin.reporter2</groupId>
        <artifactId>zipkin-reporter-brave</artifactId>
    </dependency>

    <!-- Actuator (health, metrics) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Frequently Asked Questions

Monolith నుండి microservices కు ఎప్పుడు switch చేయాలి?

కొత్త project కోసం microservices తో start చేయకండి. బాగా structured monolith తో start చేయండి. నిజమైన pain points hit అయినప్పుడు switch చేయండి: codebase ఒక team కు చాలా పెద్దది, ఒక change redeploying everything అవసరం కాబట్టి deployments చాలా ఎక్కువ సమయం తీసుకుంటాయి, లేదా app యొక్క వేర్వేరు parts independently scale కావాలి. 3 developers team కొత్త product build చేస్తుంటే, monolith దాదాపు ఎల్లప్పుడూ సరైన choice.

Eureka server down అయితే ఏమి జరుగుతుంది?

Services registry ను locally cache చేస్తాయి. Eureka temporarily down అయితే, services cached copy నుండి ఒకరి గురించి ఇంకా తెలుసు. కానీ, కొత్త services register అవ్వవు మరియు health updates జరగవు. Production లో, multiple Eureka instances (cluster) run చేయండి, ఒకటి down అయితే, మిగతావి పని చేస్తూనే ఉంటాయి. eureka.client.service-url.defaultZone ను multiple Eureka URLs కు point చేసి peer awareness configure చేయవచ్చు.

Circuit breaker మరియు retry లో తేడా ఏమిటి?

Retry చెబుతుంది: "అది fail అయిందా? మళ్ళీ try చేయండి." Circuit breaker చెబుతుంది: "ఇటీవల చాలా failures జరిగాయి. కొంతసేపు try చేయడం ఆపండి." రెండూ కలిసి పని చేస్తాయి. మీరు సాధారణంగా మొదట 2-3 times retry చేస్తారు. చాలా calls లో failures continue అవుతుంటే, circuit breaker trip open అయి failing service కు అన్ని calls ఆపేస్తుంది. ఇలా think చేయండి: retry occasional hiccups (network blip) ను handle చేస్తుంది, circuit breaker sustained outages (service minutes చాలా down) ను handle చేస్తుంది.

Inter-service communication కోసం REST బదులు Kafka లేదా RabbitMQ ఉపయోగించవచ్చా?

Yes, మరియు మీరు తరచుగా ఉపయోగించాలి. REST (synchronous) "నాకు ఇప్పుడే answer కావాలి" కోసం మంచిది — order place చేయడానికి ముందు item stock లో ఉందో check చేయడం వంటివి. Message queues (asynchronous) "మీకు time ఉన్నప్పుడు ఇది చేయండి" కోసం better — confirmation email పంపడం లేదా analytics update చేయడం వంటివి. చాలా real systems రెండూ ఉపయోగిస్తాయి: immediate responses అవసరమైన queries మరియు commands కోసం REST, events మరియు notifications కోసం message queues. Spring Cloud Stream minimal code changes తో Kafka లేదా RabbitMQ ఉపయోగించడం easy చేస్తుంది.

Multiple microservices లో database transactions ఎలా handle చేయాలి?

ఇది microservices లో అత్యంత కష్టమైన problems లో ఒకటి. ప్రతి service దాని own database కలిగి ఉన్నందున services అంతటా traditional database transaction ఉపయోగించలేరు. బదులుగా, Saga pattern ఉపయోగించండి. Saga అనేది local transactions యొక్క sequence. Step 3 fail అయితే, steps 1 మరియు 2 ను undo చేయడానికి "compensating transactions" run చేస్తారు. ఉదాహరణకు: Order-service order create చేస్తుంది (step 1), inventory-service stock reserve చేస్తుంది (step 2). Payment fail అయితే (step 3), inventory-service stock release చేస్తుంది (step 2 compensate) మరియు order-service order cancel చేస్తుంది (step 1 compensate). Spring Cloud built-in saga framework అందించదు, కానీ Axon Framework లేదా Eventuate Tram వంటి libraries help చేయగలవు.

More from Innovation

Innovation

ఈ ఏడాది తెలివితేటలు చౌకయ్యాయి — విలువ మీరు దానితో నిర్మించేదానికి మారింది

ఒక మిలియన్ AI టోకెన్ల ఖర్చు ఒకే ఏడాదిలో దాదాపు నాలుగు రెట్లు తగ్గింది. ముడిసరుకు ఇంత వేగంగా చౌకైనప్పుడు, ప్రయోజనం మోడల్ ఎవరిది అనేది కాకుండా ఉపయోగకరమైనది ఎవరు నిర్మిస్తారు అనేదిగా మారుతుంది.

14, జూన్ 20263 min read
Innovation

రోబోట్లు ప్రదర్శన ఆపి పని మొదలుపెట్టిన సంవత్సరం

ఒక దశాబ్దం పాటు హ్యూమనాయిడ్ రోబోట్లు కేవలం డెమో వీడియోలే — ఎప్పుడూ ఆకట్టుకునేవి, ఎప్పుడూ ఐదేళ్ళ దూరంలో ఉండేవి. 2026లో కథ నిశ్శబ్దంగా వీడియోల నుండి ఉత్పత్తి సంఖ్యలకు మారింది.

14, జూన్ 20263 min read
Innovation

AI నెలనెలా చౌకవుతోంది. మరి అందరి AI బిల్లులు ఎందుకు పేలిపోతున్నాయి?

AI ధర ఏడాదిలో సుమారు 4 రెట్లు తగ్గింది — కానీ కంపెనీలు వార్షిక AI బడ్జెట్లను నెలల్లో ఖర్చు చేస్తున్నాయి. రెండూ నిజమే — కారణం అర్థం చేసుకోవడం ముఖ్యం.

12, జూన్ 20263 min read