本文目录导读:

我将为您提供一个完整的Java服务注册与发现案例,使用Spring Cloud Netflix Eureka作为注册中心。
项目结构
service-registry-demo
├── pom.xml (父POM)
├── eureka-server (注册中心)
├── user-service (用户服务 - 服务提供者)
└── order-service (订单服务 - 服务消费者)
父POM配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>service-registry-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>eureka-server</module>
<module>user-service</module>
<module>order-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
<relativePath/>
</parent>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.8</spring-cloud.version>
</properties>
<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>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Eureka Server(注册中心)
eureka-server/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>service-registry-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
EurekaServerApplication.java
package com.example.eureka;
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);
}
}
application.yml
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
# 注册中心本身不注册自己
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# 关闭自我保护模式(开发环境)
enable-self-preservation: false
eviction-interval-timer-in-ms: 5000
User Service(服务提供者)
user-service/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>service-registry-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>user-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
UserServiceApplication.java
package com.example.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
UserController.java
package com.example.user.controller;
import com.example.user.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@RestController
@RequestMapping("/api/users")
public class UserController {
@Value("${server.port}")
private String serverPort;
@Resource
private DiscoveryClient discoveryClient;
// 模拟数据库
private static final Map<Long, User> USER_DB = new ConcurrentHashMap<>();
static {
USER_DB.put(1L, new User(1L, "张三", "zhangsan@example.com"));
USER_DB.put(2L, new User(2L, "李四", "lisi@example.com"));
USER_DB.put(3L, new User(3L, "王五", "wangwu@example.com"));
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
log.info("从端口 {} 获取用户信息, id: {}", serverPort, id);
User user = USER_DB.get(id);
if (user != null) {
user.setServicePort(serverPort);
}
return user;
}
@GetMapping("/list")
public List<User> getAllUsers() {
log.info("从端口 {} 获取所有用户", serverPort);
return USER_DB.values().stream()
.peek(user -> user.setServicePort(serverPort))
.toList();
}
@PostMapping
public User createUser(@RequestBody User user) {
log.info("从端口 {} 创建用户: {}", serverPort, user);
user.setId((long) (USER_DB.size() + 1));
user.setServicePort(serverPort);
USER_DB.put(user.getId(), user);
return user;
}
/**
* 获取服务发现信息
*/
@GetMapping("/service-info")
public Map<String, Object> getServiceInfo() {
Map<String, Object> info = new HashMap<>();
info.put("serviceName", "USER-SERVICE");
info.put("port", serverPort);
List<ServiceInstance> instances = discoveryClient.getInstances("USER-SERVICE");
info.put("instances", instances.stream()
.map(instance -> Map.of(
"serviceId", instance.getServiceId(),
"host", instance.getHost(),
"port", instance.getPort(),
"uri", instance.getUri().toString()
))
.toList());
return info;
}
}
User.java
package com.example.user.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private String email;
private String servicePort;
}
application.yml
server:
port: 8081
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
instance-id: user-service-${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
lease-renewal-interval-in-seconds: 5 # 心跳时间
lease-expiration-duration-in-seconds: 10 # 过期时间
management:
endpoints:
web:
exposure:
include: '*'
Order Service(服务消费者)
order-service/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>service-registry-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>order-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
</project>
OrderServiceApplication.java
package com.example.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
/**
* RestTemplate 负载均衡配置
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
/**
* WebClient 负载均衡配置
*/
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
OrderController.java
package com.example.order.controller;
import com.example.order.model.Order;
import com.example.order.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private static final Map<Long, Order> ORDER_DB = new ConcurrentHashMap<>();
static {
ORDER_DB.put(1L, new Order(1L, 101L, 200.50, "已支付"));
ORDER_DB.put(2L, new Order(2L, 102L, 350.00, "待发货"));
ORDER_DB.put(3L, new Order(3L, 103L, 150.75, "已完成"));
}
@Resource
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@Autowired
@Qualifier("webClientBuilder")
private WebClient.Builder webClientBuilder;
/**
* 获取订单详情(包含用户信息)
* 使用 RestTemplate 进行服务调用
*/
@GetMapping("/{id}/with-user")
public Map<String, Object> getOrderWithUser(@PathVariable Long id) {
Order order = ORDER_DB.get(id);
if (order == null) {
throw new RuntimeException("订单不存在: " + id);
}
log.info("获取订单: {},调用用户服务获取用户信息", order);
// 通过服务名调用用户服务(负载均衡)
String userServiceUrl = "http://USER-SERVICE/api/users/" + order.getUserId();
User user = restTemplate.getForObject(userServiceUrl, User.class);
Map<String, Object> result = new HashMap<>();
result.put("order", order);
result.put("user", user);
return result;
}
/**
* 使用 WebClient 进行响应式调用
*/
@GetMapping("/{id}/with-user-reactive")
public Map<String, Object> getOrderWithUserReactive(@PathVariable Long id) throws Exception {
Order order = ORDER_DB.get(id);
if (order == null) {
throw new RuntimeException("订单不存在: " + id);
}
// 使用 WebClient 异步调用
User user = webClientBuilder.build()
.get()
.uri("http://USER-SERVICE/api/users/" + order.getUserId())
.retrieve()
.bodyToMono(User.class)
.block();
Map<String, Object> result = new HashMap<>();
result.put("order", order);
result.put("user", user);
return result;
}
/**
* 发现并获取服务的所有实例
*/
@GetMapping("/discover-service")
public Map<String, Object> discoverService() {
Map<String, Object> result = new HashMap<>();
// 获取所有服务
List<String> services = discoveryClient.getServices();
result.put("services", services);
// 获取 USER-SERVICE 的所有实例
List<ServiceInstance> instances = discoveryClient.getInstances("USER-SERVICE");
result.put("userServiceInstances", instances.stream()
.map(instance -> Map.of(
"instanceId", instance.getInstanceId(),
"host", instance.getHost(),
"port", instance.getPort(),
"uri", instance.getUri().toString()
))
.toList());
return result;
}
/**
* 负载均衡测试 - 多次调用用户服务
*/
@GetMapping("/load-balance-test")
public List<Map<String, Object>> loadBalanceTest(@RequestParam(defaultValue = "5") int count) {
List<Map<String, Object>> results = new ArrayList<>();
for (int i = 0; i < count; i++) {
User user = restTemplate.getForObject("http://USER-SERVICE/api/users/" + (i % 3 + 1), User.class);
Map<String, Object> item = new HashMap<>();
item.put("requestId", i + 1);
item.put("user", user);
item.put("calledPort", user.getServicePort());
results.add(item);
}
return results;
}
}
Order.java
package com.example.order.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
private Long id;
private Long userId;
private Double amount;
private String status;
}
User.java (在order-service中定义)
package com.example.order.model;
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private String email;
private String servicePort;
}
application.yml
server:
port: 8082
spring:
application:
name: order-service
cloud:
loadbalancer:
ribbon:
enabled: false
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
instance-id: order-service-${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
测试步骤
1 启动服务
按照以下顺序启动服务:
# 1. 启动Eureka Server cd eureka-server mvn spring-boot:run # 2. 启动User Service cd user-service mvn spring-boot:run # 3. 启动Order Service cd order-service mvn spring-boot:run
2 验证服务注册
访问Eureka管理界面:http://localhost:8761
你应该能看到:
- USER-SERVICE 注册了一个实例
- ORDER-SERVICE 注册了一个实例
3 测试接口
# 1. 获取用户信息 curl http://localhost:8081/api/users/1 # 2. 获取订单及用户信息(使用RestTemplate) curl http://localhost:8082/api/orders/1/with-user # 3. 获取订单及用户信息(使用WebClient) curl http://localhost:8082/api/orders/1/with-user-reactive # 4. 查看服务发现信息 curl http://localhost:8082/api/orders/discover-service # 5. 负载均衡测试 curl "http://localhost:8082/api/orders/load-balance-test?count=5"
多实例测试
要测试负载均衡,可以启动多个User Service实例:
# 启动第一个实例(默认8081端口) mvn spring-boot:run # 启动第二个实例(指定8083端口) mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=8083
核心概念说明
- 服务注册:服务启动时向Eureka Server注册自身信息
- 服务发现:服务消费者通过服务名从Eureka Server获取服务实例列表
- 心跳机制:服务每5秒向Eureka Server发送心跳保持连接
- 负载均衡:Spring Cloud LoadBalancer实现客户端负载均衡
- 服务下线:服务优雅退出时向Eureka Server发送注销请求
这个案例完整展示了Spring Cloud服务注册与发现的核心功能,可以作为微服务架构的基础模板使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播