Advanced Reading time: ~9 min

Common Components

Eureka, OpenFeign, Gateway, Spring Cloud Stream

Common Components

The most useful Spring Cloud components are the ones you apply deliberately, with clear boundaries between discovery, HTTP communication, edge routing, and event-driven integration.

1. Definíció / Definition

Mi ez? / What is it?

This topic covers the most common Spring Cloud components used in service-oriented systems: Eureka for registration and discovery, OpenFeign for declarative HTTP clients, Spring Cloud Gateway for edge routing and policy enforcement, and Spring Cloud Stream for broker-backed event integration.

Miért létezik? / Why does it exist?

Because distributed systems need more than controllers and repositories. Services must locate each other, call each other safely, expose a controlled public entry point, and exchange events asynchronously when synchronous coupling would be too fragile or too expensive.

Hol helyezkedik el? / Where does it fit?

These components sit around business services rather than inside domain logic. Eureka handles the registry layer, Feign shapes synchronous service-to-service communication, Gateway owns the edge tier, and Stream abstracts producer/consumer interactions over brokers such as Kafka or RabbitMQ.

2. Alapfogalmak / Core Concepts

2.1 Eureka Server and Client

Eureka Server is a registry that tracks available service instances. Clients register themselves, renew their lease via heartbeats, and are removed after explicit deregistration or lease expiration.

Concept Meaning Why it matters
Registration Instance is added to the registry Makes the service discoverable
Heartbeat Regular renewal signal Keeps the instance alive in the registry
Deregistration Clean removal during shutdown Reduces stale routing
Self-preservation Protection against mass eviction Prevents cascading damage during network turbulence

Self-preservation is often misunderstood. It intentionally avoids aggressive eviction when the registry suspects systemic network issues. That may leave stale instances visible for a while, but it is safer than deleting a large part of the fleet because of a temporary partition.

2.2 OpenFeign

OpenFeign is a declarative HTTP client. Instead of manually building requests in every service, you define an interface and let Spring generate a client proxy.

Typical OpenFeign call path:

  1. You define a Java interface annotated with @FeignClient.
  2. Spring generates a Feign proxy implementation.
  3. The proxy performs the outgoing HTTP call to the downstream service.

Important pieces:

  • @FeignClient(name = "inventory-service")
  • Spring MVC annotations on interface methods
  • request interceptors for authentication, tracing, or tenant propagation
  • optional fallback integration when combined with circuit breaker support

2.3 Spring Cloud Gateway

Spring Cloud Gateway is the modern Spring edge service, usually implemented on the reactive stack. It mediates traffic from clients to downstream services.

Typical gateway path:

  1. An external client sends the request.
  2. Gateway applies predicates, filters, and cross-cutting policies.
  3. The request is forwarded to the selected internal service.

Core concepts:

  • predicates decide whether a route matches;
  • filters transform requests or responses;
  • rate limiting protects downstream capacity;
  • circuit breaker integration prevents repeated calls into unhealthy services;
  • request rewriting, auth, and logging centralize cross-cutting behavior.

2.4 Gateway vs Zuul

Zuul belongs to the older Netflix generation. Spring Cloud Gateway is the preferred modern choice for new systems because it is better aligned with current Spring architecture and reactive processing. You may still encounter Zuul in older codebases, but it is typically a migration target, not a greenfield recommendation.

2.5 Spring Cloud Stream

Spring Cloud Stream provides an abstraction over messaging infrastructure. Rather than writing all broker interactions directly against Kafka or RabbitMQ APIs, applications work with binders, bindings, and often the functional programming model.

Term Meaning
Binder Adapter from application model to broker implementation
Binding Logical connection between app channel and broker destination
Functional model Supplier, Function, Consumer beans
Producer/consumer pattern Loosely coupled message publication and handling

2.6 Feign vs WebClient vs RestTemplate

Tool Best fit Main trade-off
OpenFeign Clear service-to-service REST clients Very convenient, but can hide network cost
WebClient Reactive flows and fine-grained HTTP control More flexible, more explicit, more code
RestTemplate Existing synchronous codebases Familiar, but legacy-oriented

Feign is strongest when the downstream API is stable and the team values readability. WebClient is better when backpressure, streaming, or advanced HTTP orchestration matters. RestTemplate remains common in older systems, but it is rarely the first choice for new work.

3. Gyakorlati használat / Practical Usage

Consider a commerce platform. Public mobile and web traffic enters through Spring Cloud Gateway. The gateway validates JWT tokens, adds correlation IDs, applies rate limits, and routes requests to domain services. This keeps edge policy centralized and prevents copy-pasted security or routing logic across internal services.

Inside the platform, checkout-service may use OpenFeign to call inventory-service and pricing-service. The resulting client code is compact and intention-revealing, which is valuable when dozens of service calls exist across the codebase.

Eureka is useful where service instances are dynamic: auto-scaling groups, multiple hosts, rolling deploys, or non-Kubernetes environments. Instead of manually maintaining endpoint lists, services discover each other by logical name and rely on client-side load balancing.

Spring Cloud Stream becomes attractive when workflows should be event-driven rather than tightly coupled by synchronous APIs. OrderCreated might trigger invoicing, analytics, notifications, and fraud detection independently. The functional programming model also tends to produce cleaner, more focused producer/consumer code than broker-specific listener scaffolding everywhere.

4. Kód példák / Code Examples

4.1 Eureka client configuration

@SpringBootApplication
@EnableDiscoveryClient
public class CheckoutApplication {

    public static void main(String[] args) {
        SpringApplication.run(CheckoutApplication.class, args);
    }
}
spring:
  application:
    name: checkout-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

4.2 OpenFeign client with interceptor

@FeignClient(name = "inventory-service", path = "/api/inventory")
public interface InventoryClient {

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

@Configuration
class FeignClientConfig {

    @Bean
    RequestInterceptor tracingInterceptor() {
        return template -> template.header("X-Correlation-Id", UUID.randomUUID().toString());
    }
}

record InventoryResponse(String sku, int available) {}

4.3 Gateway route definition

@Configuration
class GatewayRoutes {

    @Bean
    RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("catalog-route", r -> r
                        .path("/api/catalog/**")
                        .filters(f -> f
                                .stripPrefix(1)
                                .circuitBreaker(c -> c.setName("catalogCb")))
                        .uri("lb://catalog-service"))
                .build();
    }
}

4.4 Spring Cloud Stream functional pipeline

@Configuration
class PaymentEventsConfig {

    @Bean
    Consumer<PaymentAuthorizedEvent> updateLedger() {
        return event -> System.out.println("Ledger updated for payment " + event.paymentId());
    }

    @Bean
    Function<PaymentAuthorizedEvent, ReceiptRequestedEvent> requestReceipt() {
        return event -> new ReceiptRequestedEvent(event.paymentId(), event.customerId());
    }
}

record PaymentAuthorizedEvent(String paymentId, String customerId) {}
record ReceiptRequestedEvent(String paymentId, String customerId) {}
spring:
  cloud:
    function:
      definition: updateLedger;requestReceipt
    stream:
      bindings:
        updateLedger-in-0:
          destination: payments.authorized
        requestReceipt-in-0:
          destination: payments.authorized
        requestReceipt-out-0:
          destination: receipts.requested

5. Trade-offok / Trade-offs

Benefits

  • Eureka reduces hard-coded endpoint coupling;
  • Feign improves readability for standard REST integrations;
  • Gateway centralizes edge concerns such as routing, auth, and throttling;
  • Stream supports event-driven designs with less broker-specific boilerplate.

Costs

  • every abstraction adds learning and debugging overhead;
  • Feign can encourage an RPC mindset if teams forget the network boundary;
  • Gateway can become a bottleneck or a “God proxy” if overloaded with logic;
  • Stream can obscure broker-specific behavior that still matters operationally.

Use them when they create consistency across many services and remove repeated infrastructure code.

Avoid them when the problem is still simple, the team lacks operational maturity, or the abstraction hides constraints you actually need to control directly.

6. Gyakori hibák / Common Mistakes

6.1 Misusing Feign fallbacks

Fallbacks should not silently invent business-success responses for critical failures. Returning “stock available” or “payment accepted” because the downstream call failed is dangerous unless the domain explicitly supports that degraded behavior.

6.2 Putting business logic into Gateway

Gateway should own routing and cross-cutting policy, not domain decisions. Once business rules live in the edge service, ownership becomes blurred and maintainability degrades quickly.

6.3 Ignoring binder realities in Spring Cloud Stream

Stream provides abstraction, but Kafka partitions, consumer groups, ordering, and Rabbit routing semantics still exist. Teams that forget this often design message flows that work in tests but fail under real load.

6.4 Misreading Eureka self-preservation during incidents

Operators sometimes assume the registry is malfunctioning because it retains unhealthy instances longer than expected. In many cases, self-preservation is working exactly as designed to prevent wider harm.

6.5 Choosing the wrong client model

Using blocking Feign inside a deeply reactive flow, or overengineering simple service calls with low-level WebClient code, both create unnecessary complexity. Align the client technology with the execution model and operational needs.

7. Senior szintű meglátások / Senior-level Insights

Senior engineers should think of these components as a communication strategy rather than a dependency list. A system needs clear rules: which calls go through Gateway, which direct service calls are acceptable, which failures allow fallback, and which interactions must become asynchronous events instead of synchronous RPC.

Feign delivers excellent developer ergonomics, but that convenience is precisely why it must be governed. An annotated Java interface can look deceptively local even though it performs remote I/O with latency, partial failure, authentication, retries, and observability implications.

Gateway design also requires restraint. It is the right home for edge concerns such as authentication, route management, rate limiting, and protocol normalization. It is the wrong home for domain ownership, pricing rules, cart computation, or workflow orchestration.

For Spring Cloud Stream, decide whether abstraction or broker-specific power matters more. If portability and clean producer/consumer composition are the goal, Stream is excellent. If the system depends heavily on Kafka-native partition strategy, stream processing semantics, or deep broker tuning, direct APIs may be more honest and maintainable.

8. Szószedet / Glossary

  • Eureka Server: registry that stores available service instances.
  • Eureka Client: application that registers itself and performs discovery.
  • OpenFeign: declarative HTTP client integrated with Spring.
  • Gateway predicate: route-matching condition.
  • Gateway filter: request/response transformation step.
  • Binder: Spring Cloud Stream adapter to a concrete broker.
  • Binding: connection between an application input/output and a broker destination.
  • Fallback: alternative behavior used when a remote call fails.

9. Gyorsreferencia / Cheatsheet

Component Primary role Strong fit Main risk
Eureka Discovery registry Dynamic service fleets Misunderstood registry state
OpenFeign Declarative HTTP client Standard REST integrations Hidden RPC mindset
Gateway Edge routing and policy Auth, throttling, request shaping Proxy turning into a monolith
Stream Event abstraction Producer/consumer workflows Forgetting broker semantics
WebClient Flexible HTTP client Reactive or advanced flows More explicit complexity
RestTemplate Legacy synchronous client Existing codebases Not ideal for most new designs

🎮 Games

8 questions