# demo-springcloud-netflix-eureka
**Repository Path**: xiaojianhx/demo-springcloud-netflix-eureka
## Basic Information
- **Project Name**: demo-springcloud-netflix-eureka
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-11-16
- **Last Updated**: 2023-11-16
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
@[TOC]
# 前言
略
## 角色(三个)
- **服务注册中心(Register Service)**: Eureka Server,提供注册和发现功能;
- **服务提供者(Provider Service)**:Eureka Client,将自己提供的服务注册到服务注册中心,以供服务消费者发现和调用;
- **服务消费者(Consumer Service)**:Eureka Client,从服务注册中心获取服务列表;
# 工程说明
## 基础运行环境
```base
JDK: jdk-20.0.2
spring cloud: 2022.0.4
spring boot: 3.1.5
```
## 工程目录说明
```shell
demo-springcloud-netflix-eureka (父工程)
├── demo-springcloud-netflix-eureka-consumer (服务消费者,端口:8000)
├── demo-springcloud-netflix-eureka-provider-impl1 (服务提供者,端口:9001)
├── demo-springcloud-netflix-eureka-provider-impl2(服务提供者,端口:9002)
├── demo-springcloud-netflix-eureka-provider-sdk(服务端,SDK)
├── demo-springcloud-netflix-eureka-register1(服务注册中心,端口:7001)
└── demo-springcloud-netflix-eureka-register2(服务注册中心,端口:7002)
```
***注意:*** 示例中,为了方便看效果,**服务注册中心**和**服务提供者**分别提供两个工程,内部代码都一样,只是端口不同。
## 启动顺序(建议):
```base
demo-springcloud-netflix-eureka-register1
demo-springcloud-netflix-eureka-register2
demo-springcloud-netflix-eureka-provider-impl1
demo-springcloud-netflix-eureka-provider-impl2
demo-springcloud-netflix-eureka-consumer
```
## 运行效果
### 注册与发现中心
[http://localhost:7001](http://localhost:7001) 或 [http://localhost:7002](http://localhost:7002)

### 服务消费者:
访问这个地址,将随机返回结果:[http://localhost:8000/main2?name=abc123](http://localhost:8000/main2?name=abc123)
```base
hello: abc123, I'm 9001
```
```base
hello: abc123, I'm 9002
```
# 代码说明
## 服务注册中心(Register Service)
**demo-springcloud-netflix-eureka-register1**,端口:**7001**
关键依赖(pom.xml)
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
```
关键配置(application.properties)
```yaml
spring.application.name=demo-springcloud-netflix-eureka-register
server.port=7001
eureka.instance.hostname=${spring.application.name}
eureka.instance.instance-id=${spring.application.name}:${server.port}
eureka.instance.prefer-ip-address=true
# 是否将自己注册到Eureka-Register中,默认的为true,单机设置为false,集群设置为true
eureka.client.register-with-eureka=true
# 是否从Eureka-Register中获取服务注册信息,默认为true
eureka.client.fetch-registry=false
# 这里是配置
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/,http://localhost:7002/eureka/
# 测试时关闭自我保护机制,保证不可用服务及时踢出
eureka.server.enable-self-preservation=false
```
启动类:
```java
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudNetflixEurekaRegister1 {
public static void main(String[] args) {
SpringApplication.run(SpringCloudNetflixEurekaRegister1.class, args);
}
}
```
**demo-springcloud-netflix-eureka-register2**,端口:**7002**
与*demo-springcloud-netflix-eureka-register1*代码完全一样,只是application.properties中的server.port=7002
```yaml
spring.application.name=demo-springcloud-netflix-eureka-register
server.port=7002
....
```
## 服务提供者(Provider Service)
**demo-springcloud-netflix-eureka-provider-impl1**,端口:**9001**
关键依赖(pom.xml)
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
```
关键配置(application.properties)
```yaml
spring.application.name=demo-springcloud-netflix-eureka-provider
server.port=9001
eureka.instance.instance-id=${spring.application.name}:${server.port}
eureka.instance.prefer-ip-address=true
# 每间隔2s,向服务端发送一次心跳,证明自己依然”存活“
eureka.instance.lease-renewal-interval-in-seconds=2
# 告诉服务端,如果我10s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
eureka.instance.lease-expiration-duration-in-seconds=10
# 是否将自己注册到Eureka-Register中,默认的为true
eureka.client.register-with-eureka=true
# 是否从Eureka-Server中获取服务注册信息,默认为true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/,http://localhost:7002/eureka/
```
启动类:
```java
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudNetflixEurekaProvider1 {
public static void main(String[] args) {
SpringApplication.run(SpringcloudNetflixEurekaProvider1.class, args);
}
}
```
**demo-springcloud-netflix-eureka-provider2**,端口:**9002**
与*demo-springcloud-netflix-eureka-provider1*代码完全一样,只是application.properties中的server.port=9002
```yaml
spring.application.name=demo-springcloud-netflix-eureka-provider
server.port=9002
....
```
## 服务消费者(Consumer Service)
**demo-springcloud-netflix-eureka-consumer**,端口:**8000**
关键依赖(pom.xml)
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
```
关键配置(application.properties)
```yaml
spring.application.name=demo-springcloud-netflix-eureka-consumer
server.port=8000
eureka.instance.instance-id=${spring.application.name}:${server.port}
eureka.instance.prefer-ip-address=true
eureka.instance.app-group-name=demo-springcloud-eureka-client-a
eureka.instance.lease-renewal-interval-in-seconds=2
# 是否将自己注册到Eureka-Server中,默认的为true,这里设置为false,表示不注册,不希望被别的服务发现
eureka.client.register-with-eureka=false
eureka.client.registry-fetch-interval-seconds=2
# 是否从Eureka-Server中获取服务注册信息,默认为true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/,http://localhost:7002/eureka/
```
启动类:
```java
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudNetflixEurekaConsumer {
public static void main(String[] args) {
SpringApplication.run(SpringCloudNetflixEurekaConsumer.class, args);
}
}
```
## 服务提供者SDK(Provider Service sdk)
实际工作中,该工程应该由**服务提供者**开发团队开发,供**服务消费者**依赖调用,来实现远程调用。本实例使用openfeign。
关键依赖(pom.xml)
```xml
org.springframework.cloud
spring-cloud-starter-openfeign
```
关键代码(demo-springcloud-netflix-eureka-provider-sdk工程ProviderService类):
```java
// 接口,无需手写实现类
@Component
@FeignClient(name = ProviderConstants.SERVICE_ID)
public interface ProviderService {
// 服务提供者需提供“/sub”接口服务
@RequestMapping(value = "/sub")
String test(@RequestParam("name") String name);
// 其他服务....
}
```
服务提供者依赖后使用(demo-springcloud-netflix-eureka-provider-impl1工程)
```java
@Service
public class DemoService implements ProviderService {
@Autowired
private Environment env;
public String test(String name) {
return "hello: " + name + ", I'm " + env.getProperty("server.port");
}
}
@Controller
public class DemoController {
@Autowired
private DemoService service;
@ResponseBody
@RequestMapping("/sub")
public String test(String name) {
return service.test(name);
}
}
```
服务消费者依赖后使用(demo-springcloud-netflix-eureka-consumer工程)
```java
@Autowired
private ProviderService providerService;
@ResponseBody
@RequestMapping("/main2")
public String main2(String name) {
return providerService.test(name);
}
```
# 负载均衡
客户端负载:(demo-springcloud-netflix-eureka-consumer工程)
```java
@Configuration(proxyBeanMethods = false)
public class CustomLoadBalancerConfig {
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer reactorServiceInstanceLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
var name = ProviderConstants.SERVICE_ID;
return new CustomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
```
```java
// CustomLoadBalancer.java
private Response getInstanceResponse(List instances) {
if (instances.isEmpty()) {
if (log.isWarnEnabled()) {
log.warn("No servers available for service: " + serviceId);
}
return new EmptyResponse();
}
// 随机
var index = ThreadLocalRandom.current().nextInt(instances.size());
var instance = instances.get(index);
return new DefaultResponse(instance);
}
```
# 源码地址
[https://gitee.com/xiaojianhx/demo-springcloud-netflix-eureka](https://gitee.com/xiaojianhx/demo-springcloud-netflix-eureka)