Tools
Tools: Part 1 : Peer Aware Eureka Service Registry
2026-01-25
0 views
admin
About the Order System Used in This Series ## What This Part Covers ## What Is a Service Registry? ## Why Start with Eureka? ## Letβs Begin π ## Why Service Discovery Is Mandatory in Production ## High-Level Architecture ## Existing Order System ## Step 1: Peer-Aware Eureka Service Registry (3 Nodes) ## Why Peer-Aware Eureka? ## Eureka Server Configuration ## Step 1: Peer-Aware Eureka Service Registry (3 Nodes) ## Why Peer-Aware Eureka? ## Eureka Server Configuration ## Eureka Server Application ## Step 2: Register Order System with Eureka ## Order System Configuration ## Step 3: Create Order Consumer Microservice ## Step 4: Service-to-Service Call ## Summary New Series: Spring Cloud Microservice Architecture (Service Discovery Β· Gateway Β· Nginx Β· Production Patterns) This blog marks the beginning of a new series focused entirely on Spring Cloudβbased microservice architecture and production-grade system design. In this series, we will design and evolve a complete microservices ecosystem using: To avoid reinventing the wheel, this series reuses an existing microservice from my earlier work: π Production-Grade Spring Boot API Design https://dev.to/pratik280/series/35113 The order-system from that series is used only as a sample business service so we can focus purely on: π This Spring Cloud series is completely independent and does not require reading the previous series, although familiarity with the order-system API helps. This Part 1 focuses on: A Service Registry is a centralized system that keeps track of all running microservice instances in a distributed system. Instead of services communicating using fixed IP addresses and ports, they: π In Spring Cloud, Eureka acts as the Service Registry. Before gateways, security, or scaling: Services must be able to find each other reliably. That is exactly what Eureka Service Registry solves β and itβs the foundation of every production-grade Spring Cloud system. In the next sections, weβll set up a 3-node peer-aware Eureka cluster and use it as the backbone for all service communication in the system. In real production systems: Hardcoding endpoints like: http://localhost:8080/orders β breaks scaling β breaks failover β tightly couples services From the earlier series, the order-system already exposes: Now we make this production-grade using service discovery. π Minimum recommended: 3 nodes π Minimum recommended: 3 nodes Note: This configuration represents one Eureka server instance. For a peer-aware Eureka cluster, create multiple Eureka applications (for example, 3 instances) and modify: so that each Eureka node points to all other Eureka nodes using their respective IPs and ports. What does @EnableEurekaServer do? This service consumes order-system data without knowing: What Is RestTemplate? RestTemplate is Springβs synchronous HTTP client used for REST calls. @LoadBalanced enables: Load-Balanced RestTemplate Configuration Order Consumer Controller Key Point http://order-system/orders β Logical service name β Resolved dynamically via Eureka Order Consumer Configuration What Happens Internally? Why This Architecture Is Production-Grade Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. as well , this person and/or CODE_BLOCK: Client β Nginx (Reverse Proxy & LB) β Spring Cloud Gateway (multiple instances) β Eureka Cluster (3 peer-aware nodes) β Order System (multiple instances) CODE_BLOCK: Client β Nginx (Reverse Proxy & LB) β Spring Cloud Gateway (multiple instances) β Eureka Cluster (3 peer-aware nodes) β Order System (multiple instances) CODE_BLOCK: Client β Nginx (Reverse Proxy & LB) β Spring Cloud Gateway (multiple instances) β Eureka Cluster (3 peer-aware nodes) β Order System (multiple instances) CODE_BLOCK: GET http://localhost:8085/orders { "status": 200, "message": "All orders fetch successfully", "data": [ { "id": 1, "productName": "Mobile" }, { "id": 2, "productName": "Mobile" }, { "id": 3, "productName": "Mobile" }, { "id": 4, "productName": "Smartwatch" } ], "errors": null } CODE_BLOCK: GET http://localhost:8085/orders { "status": 200, "message": "All orders fetch successfully", "data": [ { "id": 1, "productName": "Mobile" }, { "id": 2, "productName": "Mobile" }, { "id": 3, "productName": "Mobile" }, { "id": 4, "productName": "Smartwatch" } ], "errors": null } CODE_BLOCK: GET http://localhost:8085/orders { "status": 200, "message": "All orders fetch successfully", "data": [ { "id": 1, "productName": "Mobile" }, { "id": 2, "productName": "Mobile" }, { "id": 3, "productName": "Mobile" }, { "id": 4, "productName": "Smartwatch" } ], "errors": null } CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: spring.application.name=eureka-server server.port=8760 eureka.client.service-url.defaultZone=\ http://EurekaInstance1IP:8760/eureka,\ http://EurekaInstance2IP:8761/eureka,\ http://EurekaInstance3IP:8762/eureka eureka.client.register-with-eureka=true eureka.client.fetch-registry=true CODE_BLOCK: @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } CODE_BLOCK: @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } CODE_BLOCK: @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } CODE_BLOCK: spring.application.name=order-system eureka.client.service-url.defaultZone=\ http://localhost:8760/eureka,\ http://localhost:8761/eureka,\ http://localhost:8762/eureka eureka.instance.prefer-ip-address=true CODE_BLOCK: spring.application.name=order-system eureka.client.service-url.defaultZone=\ http://localhost:8760/eureka,\ http://localhost:8761/eureka,\ http://localhost:8762/eureka eureka.instance.prefer-ip-address=true CODE_BLOCK: spring.application.name=order-system eureka.client.service-url.defaultZone=\ http://localhost:8760/eureka,\ http://localhost:8761/eureka,\ http://localhost:8762/eureka eureka.instance.prefer-ip-address=true CODE_BLOCK: ORDER-SYSTEM β [instance-1, instance-2, instance-3] CODE_BLOCK: ORDER-SYSTEM β [instance-1, instance-2, instance-3] CODE_BLOCK: ORDER-SYSTEM β [instance-1, instance-2, instance-3] CODE_BLOCK: @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } } CODE_BLOCK: @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } } CODE_BLOCK: @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } } CODE_BLOCK: @RestController @RequestMapping("/consume") public class OrderConsumerController { private final RestTemplate restTemplate; public OrderConsumerController(RestTemplate restTemplate){ this.restTemplate = restTemplate; } @GetMapping("/orders") public String fetchOrders() { return restTemplate.getForObject( "http://order-system/orders", String.class ); } } CODE_BLOCK: @RestController @RequestMapping("/consume") public class OrderConsumerController { private final RestTemplate restTemplate; public OrderConsumerController(RestTemplate restTemplate){ this.restTemplate = restTemplate; } @GetMapping("/orders") public String fetchOrders() { return restTemplate.getForObject( "http://order-system/orders", String.class ); } } CODE_BLOCK: @RestController @RequestMapping("/consume") public class OrderConsumerController { private final RestTemplate restTemplate; public OrderConsumerController(RestTemplate restTemplate){ this.restTemplate = restTemplate; } @GetMapping("/orders") public String fetchOrders() { return restTemplate.getForObject( "http://order-system/orders", String.class ); } } CODE_BLOCK: spring: application: name: order-consumer server: port: 8090 eureka: client: service-url: defaultZone: http://localhost:8760/eureka, http://localhost:8761/eureka, http://localhost:8762/eureka instance: prefer-ip-address: true CODE_BLOCK: spring: application: name: order-consumer server: port: 8090 eureka: client: service-url: defaultZone: http://localhost:8760/eureka, http://localhost:8761/eureka, http://localhost:8762/eureka instance: prefer-ip-address: true CODE_BLOCK: spring: application: name: order-consumer server: port: 8090 eureka: client: service-url: defaultZone: http://localhost:8760/eureka, http://localhost:8761/eureka, http://localhost:8762/eureka instance: prefer-ip-address: true CODE_BLOCK: GET http://localhost:8090/consume/orders CODE_BLOCK: GET http://localhost:8090/consume/orders CODE_BLOCK: GET http://localhost:8090/consume/orders - Spring Cloud Netflix Eureka (Service Discovery) - Spring Cloud Gateway (API Gateway) - Nginx (Edge reverse proxy & load balancer) - Production-ready scaling and fault-tolerance patterns - Service discovery - Inter-service communication - Load balancing - Infrastructure concerns - order-system : https://github.com/Pratik280/order-system - order-consumer : https://github.com/Pratik280/order-consumer - eureka-server : https://github.com/Pratik280/eureka-server - Why service discovery is mandatory in production - Why a single Eureka server is not enough - How to design a peer-aware Eureka cluster - How microservices register themselves using logical names - How this eliminates hardcoded IPs and ports - Register themselves with the registry - Discover other services dynamically using logical names - Services scale dynamically - Instances come and go - IPs and ports must never be hardcoded - Load balancing must be automatic - Failure of one node must not break the system - A single Eureka server is a single point of failure - In production, Eureka must be highly available - Each Eureka node replicates registry data with its peers - A single Eureka server is a single point of failure - In production, Eureka must be highly available - Each Eureka node replicates registry data with its peers - server.port - eureka.client.service-url.defaultZone - Turns a Spring Boot application into a Service Registry - Accepts service registrations from microservices - Tracks heartbeats to detect unhealthy instances - Replicates registry information to peer Eureka nodes - Run multiple instances of order-system - All instances register under one logical name: - Number of running instances - It only supports fixed URLs - It does not understand Eureka - Service name resolution - Instance lookup from Eureka - Client-side load balancing - Consumer calls http://order-system/orders - @LoadBalanced RestTemplate intercepts the call - Eureka returns all registered order-system instances - One instance is selected - Request is forwarded - Response is returned - No hardcoded IPs or ports - Automatic scaling - High availability - Fault tolerance - Clean separation of concerns - Gateway + Nginx hide internal topology - Eureka provides service discovery - Peer-aware Eureka removes SPOF - @EnableEurekaServer creates the registry - @LoadBalanced RestTemplate enables dynamic routing - Services communicate using logical names - Scaling requires no code changes
toolsutilitiessecurity toolsawareeurekaserviceregistrysystem