In this tutorial, we’ll create two Spring Boot microservices, register them with an Eureka server, and demonstrate service communication using Feign. We’ll be using Spring Boot 3.2+ and Spring Cloud 2023.x.
Introduction to Eureka Server
Eureka Server is a service registry where microservices register and discover other services. This dynamic discovery mechanism helps manage communication in a distributed system. It eliminates the need for hardcoding service addresses, making the system more scalable and resilient.
How Microservices Use Eureka for Discovery
When a microservice registers with Eureka, it provides the server with details like its hostname, IP address, and port. Other microservices can then query the Eureka server to get this information and communicate dynamically.
For example:
- Service Registration: When a microservice starts, it registers itself with Eureka by sending a POST request with its metadata (such as hostname, IP address, and port) to the Eureka server.
- Service Discovery: Another microservice, instead of hardcoding the service address, queries Eureka to get the address and port of the service. This is especially useful when services are deployed across multiple instances and dynamically assigned ports.
Flow of the System
- Eureka Server: Acts as a central registry where microservices register.
- Microservices: Register with Eureka Server and discover other services.
- Service Discovery: Microservices query the Eureka Server to find the network locations (IP and port) of other microservices.
For example, the order-service
will use Eureka to dynamically get the address and port of product-service
instead of hardcoding the URL.
Prerequisites
- JDK 17 or later
- Maven or Gradle
- IDE (IntelliJ IDEA, Eclipse, etc.)
Step 1: Set Up the Eureka Server
1.1 Create the Project
Use Spring Initializr to create a new project with the following dependency:
- Eureka Server
1.2 Configure application.properties
Set up the application properties for the Eureka Server.
server.port=8761
spring.application.name=eureka-server
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Explanation:
server.port=8761
: Sets the port for the Eureka Server.spring.application.name=eureka-server
: Names the application.eureka.client.register-with-eureka=false
: The Eureka Server should not register with another Eureka Server.eureka.client.fetch-registry=false
: The Eureka Server doesn’t fetch the registry from other servers.
1.3 Enable Eureka Server
Add the @EnableEurekaServer
annotation to the main application class.
package com.example.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);
}
}
Explanation:
@EnableEurekaServer
: Enables the Eureka Server functionality.
Step 2: Set Up product-service
2.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Eureka Discovery Client
2.2 Configure application.properties
Set up the application properties for product-service
.
server.port=8081
spring.application.name=product-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
Explanation:
server.port=8081
: Sets the port forproduct-service
.spring.application.name=product-service
: Names the application.eureka.client.service-url.default-zone=http://localhost:8761/eureka/
: Specifies the Eureka Server URL for service registration.
2.3 Enable Eureka Client
Add the @EnableDiscoveryClient
annotation to the main application class.
package com.example.productservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
Explanation:
@EnableDiscoveryClient
: Registers the microservice with Eureka Server for service discovery.
2.4 Create a Product Model
Create a simple Product model to represent product data.
package com.example.productservice;
public class Product {
private String id;
private String name;
private double price;
public Product(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
// Getters
public String getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
}
2.5 Create a Controller
Create a controller to handle product-related requests.
package com.example.productservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable String id) {
return new Product(id, "Sample Product", 99.99);
}
}
Explanation:
@RestController
: Marks this class as a REST controller.@GetMapping("/products/{id}")
: Maps GET requests to/products/{id}
.
Step 3: Set Up order-service
3.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Eureka Discovery Client
- OpenFeign
3.2 Configure application.properties
Set up the application properties for order-service
.
server.port=8082
spring.application.name=order-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
3.3 Enable Feign Clients and Eureka Client
Enable Feign clients and Eureka client functionality by adding the @EnableFeignClients
and @EnableDiscoveryClient
annotations in the main application class.
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
3.4 Create a Feign Client for product-service
Create a Feign client interface to communicate with product-service
.
package com.example.orderservice;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "product-service")
public interface ProductServiceClient {
@GetMapping("/products/{id}")
Product getProductById(@PathVariable String id);
}
How Eureka Works Here:
@FeignClient(name = "product-service")
: This tellsorder-service
that it should communicate withproduct-service
. The name"product-service"
is the name that was registered in the Eureka server whenproduct-service
started.How Eureka Helps: Normally, to communicate with another service, you'd need to know where that service is located (its IP address and port). But thanks to Eureka,
order-service
doesn't need to know those details. Eureka works like a directory, so whenorder-service
wants to talk toproduct-service
, it just asks Eureka for the current address and port. Eureka then provides this information automatically, even ifproduct-service
has moved to a different location or port.
This means the communication between services becomes dynamic and flexible because Eureka handles the behind-the-scenes details of finding and connecting to product-service
.
3.5 Create a Controller
Create a controller to handle order-related requests and use the ProductServiceClient
to fetch product details.
package com.example.orderservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
private final ProductServiceClient productServiceClient;
public OrderController(ProductServiceClient productServiceClient) {
this.productServiceClient = productServiceClient;
}
@GetMapping("/orders/{productId}")
public String createOrder(@PathVariable String productId) {
Product product = productServiceClient.getProductById(productId);
return "Order created for product: " + product.getName() + " with price: $" + product.getPrice();
}
}
Explanation:
ProductServiceClient productServiceClient
: Injects the Feign client for communication withproduct-service
.
Step 4: Run the Microservices
- Start the Eureka Server: Run the
EurekaServerApplication
class. - Start
product-service
: Run theProductServiceApplication
class. - Start
order-service
: Run theOrderServiceApplication
class.
Step 5: Test the Communication
Use a browser or Postman to test the endpoints:
product-service
:http://localhost:8081/products/1
order-service
:http://localhost:8082/orders/1
The response from order-service
should include product details fetched from product-service
.
Conclusion
You have successfully set up two Spring Boot microservices and registered them with Eureka Server. The Eureka Server acts as a service registry, allowing microservices to discover and communicate with each other by querying for dynamic service addresses and ports. This setup demonstrates a scalable microservices architecture and can be extended to more services and complex interactions.
Comments
Post a Comment
Leave Comment