文章目录
友情提醒
- 文末获取【真会玩】- SpringCloud Netflix 实战系列
Postman在线脚本、Github仓库实战源码- 【真会玩】- SpringCloud Netflix 实战系列有概念有实战,考验动手能力,如果实战中有操作没有达到与本文同等效果的请先仔细检查个人操作与文中相关内容是否一致,如检查无误请私信或评论区留言~

前置环境搭建
创建一个空的Maven工程


把
src文件夹删除掉作为一个空的总项目工程文件夹使用

空的工程到此就搭建好了,后续会不断往里面集成模块
Eureka
服务注册与发现,用于服务管理,在传统应用中,组件之间的调用,通过有规范的约束的接口来实现,从而实现不同模块间良好的协作。但是被拆分成微服务后,每个微服务实例的网络地址都可能动态变化,数量也会变化,使得原来硬编码的地址失去了作用。需要一个中心化的组件来进行服务的登记和管理所有的服务信息和状态
概念初识
服务注册
当客户端向Eureka注册时,它会提供有关自身的元数据 : 例如主机、端口、健康指示器URL、主页和其他详细信息。Eureka从
属于服务的每个实例接收心跳消息。如果心跳在可配置的时间表上失败,通常会从注册表中删除实例。
- 想要参与
服务注册发现的实例首先需要向Eureka服务器注册信息并且注册在第一次心跳时提交
服务发现
服务发现是基于微服务架构的关键原则之一。很难做到
每次都手动配置每个客户端或某种形式的约定。Eureka是Netflix用来发现服务器和客户端的。我们可以将服务器配置部署为高可用,然后每个服务器都将注册服务的状态复制给其他服务器。
续租
【Renew】
Eureka客户需要每30秒发送一次心跳来续租
00:00:00 第一次
间隔30s
00:00:30 第二次
间隔30s
00:01:00 第三次
间隔30s
00:01:30 第四次
最后
更新通知Eureka服务器实例仍然是活跃的。如果服务器在90秒内没有看到更新,它将从其注册表中删除该实例
拉取注册表
【Fetch Registry]
- Eureka
客户端从服务器获取注册表信息并将其缓存在本地客户端使用这些信息来查找其他服务- 通过获取
上一个获取周期和当前获取周期之间的增量更新,可以定期(每30秒)更新此信息节点信息在服务器中保存的时间更长(大约3分钟),因此获取节点信息时可能会再次返回相同的实例。Eureka客户端自动处理重复的信息- 在获得
增量之后,Eureka客户端通过比较服务器返回的实例计数来与服务器协调信息,如果由于某种原因信息不匹配,则再次获取整个注册表信息
Cancel
Eureka
客户端在关闭时向Eureka服务端发送取消请求。从服务端的实例注册表中删除实例,从而有效地将实例从通信量中取出。
同步时间延时
【TimeLag】
来自
Eureka客户端的所有操作可能需要一段时间才能反映到Eureka服务器上,然后反映到其他Eureka客户端上这是因为
eureka服务器上的有效负载缓存,它会定期刷新以反映新信息。Eureka客户端还定期地获取增量
通讯机制
Communication mechanism【kəˌmjuːnɪˈkeɪʃn ˈmekənɪzəm】
- Http协议下的Rest请求
- 默认情况下Eureka使用Jersey和Jackson以及JSON完成节点间的通讯
Eureka服务端搭建
创建Eureka模块,引入
Eureka Server依赖

📢注意:
我们本次用的SpringCloud版本为 Hoxton.SR12
所以SpringBoot版本要选2.3.12.RELEASE
如果选用其他版本请至Spring官网查看对应的版本支持
预选依赖Release Train Version: Hoxton.SR12
Supported Boot Version: 2.3.12.RELEASE
勾选依赖
- 这边的SpringBoot版本因为不是我们想用的版本,随便选一个,等下再去手动修改版本


- 修改
pom文件中spring-boot-starter-parent - version为2.3.12.RELEASE- 修改
spring-cloud.version为Hoxton.SR12- 至此
Eureka-Server模块就创建完成了
下面开始配置YAML文件
server:
port: 7900
eureka:
client:
#是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息
register-with-eureka: false
#是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false
fetch-registry: false
#设置服务注册中心的URL,用于client和server端交流
service-url:
defaultZone: http://localhost:7900/eureka/
启动程序
注意要添加
@EnableEurekaServer注解标识该服务为配置中心
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
启动并在浏览器输入
http://localhost:7900/即可显示Eureka可视化页面

Eureka客户端
Provider搭建
新建一个项目/模块 引入依赖

搭建好客户端后修改客户端的
application.yml配置文件
server:
port: 8080
spring:
application:
name: EurekaProvider
eureka:
client:
service-url:
#注册到eureka1节点
defaultZone: http://eureka1.com:7901/eureka/
再将服务端的
application.yml配置文件修改一下,只启动一个节点就可以了
spring:
# profiles:
# active: eureka2
application:
name: EurekaServer
server:
port: 7901
eureka:
client:
service-url:
#自我注册
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#是否将自己注册到其他Eureka Server,默认为true
# register-with-eureka: true
#是否从eureka server获取注册信息
# fetch-registry: true
instance:
#查找主机
hostname: eureka1.com
新建
ProviderController类并写好pingProvider接口供后续Eureka-Consumer模块测试调用
@RestController
public class ProviderController {
@GetMapping("/pingProvider")
public String ping() {
return "Ping Provider Success";
}
}
配置完成先启动服务端再启动客户端
- 启动完成后如下状态便是客户端注册成功了

📢特殊说明:
有兄弟可能会问,前面提到Eureka-Server不是需要在启动类里面添加@EnableEurekaServer注解标识为服务端吗,那Eureka-Provider不需要在@EnableEurekaClient来标识为客户端吗?
- 不需要了 我们这里用的是
Hoxton.SR12版本- 只有老版本需要加这个注解标识
Consumer搭建
按照
Provider搭建的相同操作再创建一个Eureka-Consumer模块

配置
Eureka-Consumer的application.yml配置文件
server:
port: 8081
spring:
application:
name: EurekaConsumer
eureka:
client:
service-url:
#向eureka发起注册请求
defaultZone: http://eureka1.com:7901/eureka/
新建
ConsumerController类
- 主要提供
getClient服务,查询所有注册节点的信息
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
/**
* org.springframework.cloud.client.discovery.DiscoveryClient (Spring官方指定的标准)
*/
@Resource
private DiscoveryClient discoveryClient;
@Resource
private EurekaClient eurekaClient;
/**
* 心跳接口
*
* @return java.lang.String
* @author Rhys.Ni
* @date 2022/9/15
*/
@GetMapping("/ping")
public String ping() {
return "ping success";
}
/**
* 获取服务列表
*
* @return java.lang.String
* @author Rhys.Ni
* @date 2022/9/15
*/
@GetMapping("/services")
public String getServices() {
List<String> services = discoveryClient.getServices();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("[ ");
for (String service : services) {
stringBuffer.append(service + " ");
}
stringBuffer.append("]");
return stringBuffer.toString();
}
/**
* 获取应用实例信息
*
* @return java.lang.Object
* @author Rhys.Ni
* @date 2022/9/15
*/
@GetMapping("/instances")
public Object getInstances() {
return discoveryClient.getInstances("EurekaProvider");
}
/**
* 获取应用实例信息
*
* @return java.lang.Object
* @author Rhys.Ni
* @date 2022/9/15
*/
@GetMapping("/testProvider")
public Object pingProvider() {
//根据服务名找注册列表
List<InstanceInfo> instances = eurekaClient.getInstancesByVipAddress("EurekaProvider", false);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("[ ");
for (InstanceInfo instanceInfo : instances) {
stringBuffer.append(instanceInfo + " ");
}
stringBuffer.append("]");
System.out.println(stringBuffer);
if (instances.size() > 0) {
InstanceInfo instanceInfo = instances.get(0);
//如果服务处于活跃状态下则取URL
if (instanceInfo.getStatus().equals(InstanceInfo.InstanceStatus.UP)) {
String url = "http://" + instanceInfo.getHostName() + ":" + instanceInfo.getPort() + "/pingProvider";
ResponseEntity<String> responseEntity = new RestTemplate().getForEntity(url, String.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
String s = responseEntity.getBody();
return s;
} else {
return "Bad Request";
}
}
}
return "Bad Request";
}
}
启动
Eureka-Consumer客户端并关注http://eureka1.com:7901/页面中Eureka-Consumer是否如下样例成功注册

Postman`调用接口进行验证
调用
services服务
http://localhost:8081/consumer/services
如下图:结果显示这三个服务(包括Eureka自己)都成功注册并获取到了服务列表

调用
instances服务
http://localhost:8081/consumer/instances
成功获取到了实例信息

调用
testProvider接口验证远程调用Eureka-Provider客户端的pingProvider接口
http://localhost:8081/consumer/testProvider

Eureka服务端高可用搭建
可以通过运行多个Eureka server实例并相互注册的方式实现。Server节点之间会彼此增量地同步信息,从而确保节点中数据一致。
本地IDE启动修改hosts
首先修改
hosts文件对127.0.0.1映射主机名区分两台机器
Mac修改方式
先修改
/etc/hosts文件权限,默认只读,无法修改
sudo chmod -R 777 /etc/hosts
#输入开机密码
然后再对文件进行修改
vim /etc/hosts
将以下配置贴入文件中保存即可
#Eureka
127.0.0.1 eureka1.com
127.0.0.1 eureka2.com

Windows修改方式
C:\Windows\System32\drivers\etc\hosts因为没有权限直接修改,我们需要先复制一份文件到桌面然后用
文本文档打开修改保存后再替换调C:\Windows\System32\drivers\etc下的hosts文件
- 修改内容同上
- 最后分别
ping一下两个域名,如果能ping通说明生效了- 如果
ping不通则关闭杀毒软件等重新修改保存再试

创建多个节点配置文件
新建
application-eureka1.yml
server:
port: 7901
eureka:
client:
service-url:
#向eureka节点发起请求
defaultZone: http://eureka2.com:7902/eureka/
#是否将自己注册到其他Eureka Server,默认为true
register-with-eureka: true
#是否从eureka server获取注册信息
fetch-registry: true
instance:
#查找主机
hostname: eureka1.com
新建
application-eureka2.yml
server:
port: 7902
eureka:
client:
service-url:
#向eureka1节点发起请求
defaultZone: http://eureka1.com:7901/eureka/
#是否将自己注册到其他Eureka Server,默认为true
register-with-eureka: true
#是否从eureka server获取注册信息
fetch-registry: true
instance:
hostname: eureka2.com
最后将
application.yml文件内容修改成一下内容
spring:
profiles:
#因为我们有多个配置文件 这个能决定使用哪个配置文件
active: eureka1
application:
#应用名称
name: EurekaServer
准备启动,启动前需要知道


当然,可能有部分兄弟
IDEA版本跟我的不同,界面布局可能跟我的不太一样,可能会是这样的

没关系,不用慌,该有的功能还是有的,只是放到了不同的地方而已,点击
Modify Options

在弹出的下拉框中选择
Allow multiple instances

点击保存设置,此时便可以继续往下操作了

启动两个Eureka服务

启动成功后进入浏览器查看
http://localhost:7901/、http://localhost:7902/如下便是配置成功了


自我保护机制
Eureka在CAP理论当中是属于AP , 也就说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性
默认开启,服务器端容错的一种方式,即短时间心跳不到达仍不剔除服务列表里的节点
默认情况下,Eureka Server在一定时间内(90S),没有接收到某个微服务心跳,会将这个微服务注销。但是当网络故障时,微服务与Server之间无法正常通信,上述行为就非常危险,因为微服务正常,不应该注销。
Eureka Server通过
自我保护模式来解决整个问题,当Server在短时间内丢失过多客户端时,那么Server会进入自我保护模式,会保护注册表中的微服务不被注销掉。当网络故障恢复后,退出自我保护模式。
触发自我保护
客户端每分钟续约数量小于客户端总数的85%时会触发保护机制
-
当每分钟心跳次数
renewsLastMin小于numberOfRenewsPerMinThreshold时,并且开启自动保护模式开关( eureka.server.enable-self-preservation = true ) 时,触发自我保护机制,不再自动进行过期时续租。 -
numberOfRenewsPerMinThreshold=expectedNumberOfRenewsPerMin*续租百分比( eureka.server.renewalPercentThreshold, 默认0.85 ) -
expectedNumberOfRenewsPerMin= 当前注册的应用实例数x 2(默认情况下,注册的应用实例每半分钟续租一次,那么一分钟心跳两次,因此 x 2 ) -
假设有
10个服务实例数,期望每分钟续约数10*2=20,期望阈值20*0.85=17,自我保护少于17时 触发。
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
- 意思是Eureka可能会错误地声称实例已启动,而实际上它们并没有。更新时间小于阈值,因此为了安全起见,实例不会过期。

关闭自我保护,这个配置默认是true 也就是自我保护机制默认是开启的
eureka:
server:
#关闭自我保护机制
enable-self-preservation: false
关闭后就会出现以下提示
THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.
- 意思是自保模式已关闭。可能不会在出现网络/其他问题时保护实例过期。

Eureka 健康检查
如果我们现在这个自我保护机制没有关闭,就让他是开启的状态,现在我们已经有服务处于不可用状态了,我想手动把他
Dowm掉,从服务列表中移除掉应该怎么做?
- 当服务抛了某些异常,我能够Catch住异常给这个服务进行手动下线,从服务列表中移除
- 由于server和client通过心跳保持 服务状态,而只有状态为UP的服务才能被访问。看eureka界面中的status。
- 有一种场景比如:心跳一直正常,服务一直UP,但是此服务DB连不上了,无法正常提供服务。
- 这个时候我们就要将微服务的健康状态也同步到server
- 使用
Actuator监控应用,启动eureka的健康检查,这样微服务就会将自己的健康状态同步到eureka
开启手动控制
在
Eureka-Provider和Eureka-Consumer端配置,将客户端的健康状态传播到服务端
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在
Eureka-Provider和Eureka-Consumer端的application.yml中添加以下配置
eureka:
client:
healthcheck:
enabled: true

启动
Eureka-Provider和Eureka-Consumer启动成功后可在控制台看到
/actuator路径打印在了日志中

访问
/actuator
localhost:8080/actuator

这个接口也会带一些其他接口URL可供访问
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
}
}
}
Api端点功能
开启所有端点,在
Eureka-Provider和Eureka-Consumer服务中的application.yml中添加以下配置
management:
endpoints:
web:
exposure:
include: "*"

重启
Eureka-Provider和Eureka-Consumer服务并重新调用/actuator接口可以看到返回来了所有端点信息
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"beans": {
"href": "http://localhost:8080/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8080/actuator/caches/{cache}",
"templated": true
},
"caches": {
"href": "http://localhost:8080/actuator/caches",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
},
"conditions": {
"href": "http://localhost:8080/actuator/conditions",
"templated": false
},
"configprops": {
"href": "http://localhost:8080/actuator/configprops",
"templated": false
},
"configprops-prefix": {
"href": "http://localhost:8080/actuator/configprops/{prefix}",
"templated": true
},
"env": {
"href": "http://localhost:8080/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8080/actuator/env/{toMatch}",
"templated": true
},
"loggers-name": {
"href": "http://localhost:8080/actuator/loggers/{name}",
"templated": true
},
"loggers": {
"href": "http://localhost:8080/actuator/loggers",
"templated": false
},
"heapdump": {
"href": "http://localhost:8080/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8080/actuator/threaddump",
"templated": false
},
"metrics": {
"href": "http://localhost:8080/actuator/metrics",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8080/actuator/metrics/{requiredMetricName}",
"templated": true
},
"scheduledtasks": {
"href": "http://localhost:8080/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://localhost:8080/actuator/mappings",
"templated": false
},
"refresh": {
"href": "http://localhost:8080/actuator/refresh",
"templated": false
},
"features": {
"href": "http://localhost:8080/actuator/features",
"templated": false
},
"serviceregistry": {
"href": "http://localhost:8080/actuator/serviceregistry",
"templated": false
}
}
}
| 部分接口 | 描述 |
|---|---|
| http://localhost:8080/actuator/health | 会显示系统状态 {“status”:“UP”} |
| http://localhost:8080/actuator/configprops | 获取应用中配置的属性信息报告 |
| http://localhost:8080/actuator/beans | 获取应用上下文中创建的所有Bean |
| http://localhost:8080/actuator/env | 获取应用所有可用的环境属性报告 |
| http://localhost:8080/actuator/mappings | 获取应用所有Spring Web的控制器映射关系报告 |
| http://localhost:8080/actuator/info | 获取应用自定义的信息 |
| http://localhost:8080/actuator/metrics | 返回应用的各类重要度量指标信息 |
| http://localhost:8080/actuator/metrics/jvm.memory.max | Metrics节点并没有返回全量信息,我们可以通过不同的key去加载我们想要的值 |
| http://localhost:8080/actuator/threaddump | 返回程序运行中的线程信息 |
ShutDown Api
用来关闭节点,需要在
Eureka-Provider和Eureka-Consumer服务中的application.yml中添加以下配置
management:
endpoint:
shutdown:
enabled: true

修改完成重启
Eureka-Provider和Eureka-Consumer服务,使用Post方式请求


关闭成功后再去查看
eureka1.com:7901服务列表中就没有Eureka-Provider服务了

上面了解了这么多健康检查相关的内容,那我现在想修改健康状态的服务该怎么操作呢?
- 在
Eureka-Provider和Eureka-Consumer服务中新建健康状态服务类实现HealthIndicator接口
@Service
public class HealthStatusService implements HealthIndicator {
private Boolean status = true;
public void setStatus(Boolean status) {
this.status = status;
}
@Override
public Health health() {
if (status) {
return new Health.Builder().up().build();
}
return new Health.Builder().down().build();
}
public String getStatus() {
return this.status.toString();
}
}
在controller中添加
/health接口
@GetMapping("/health")
public String health(@RequestParam("status") Boolean status) {
healthStatusService.setStatus(status);
return healthStatusService.getStatus();
}
重启两个服务,我们这边调用
Eureka-Provider服务的health接口,这是我们服务都是启动的,即 “status”: "UP"状态
localhost:8080/health?status=false
在调用
/actuator/health接口查看服务状态
http://localhost:8080/actuator/health

SpringSecurity安全配置
开启Eureka安全连接
在
Eureka-Server服务中添加Spring-Security依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
也可以安装一个
EditStarters插件,在开发过程中也能方便添加修改spring boot starter.

Mac系统在
pom文件中按Command+N弹窗选择这个插件即可Window系统在
pom文件中按Alt+Insert弹窗选择这个插件即可




这样就会自动将依赖添加到
pom文件中

添加完成依赖再到
Eureka-Provider服务中的application.yml中添加以下配置
spring:
security:
user:
name: xxx
password: 123456

如果只是修改注册中心的配置是没有用的,其他服务是没法注册进来的,我们还需要去修改所有
application.yml文件中defaultZone配置项都要改成
xxxRhysNi:123456@xxx这种带用户名密码的链接
eureka:
client:
service-url:
#向eureka发起注册请求
defaultZone: http://RhysNi:123456@eureka1.com:7901/eureka/
在
Eureka-Server服务中添加配置类关闭由Security提供的跨域攻击保护
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
http.headers().frameOptions().disable();
http.csrf().disable().authorizeRequests().antMatchers("/actuator/**").permitAll().anyRequest().authenticated().and().httpBasic();
}
}
重启所有服务并打开浏览器进入
http://localhost:7091/login、http://localhost:7092/login输入用户名密码登录


Eureka-Rest服务调用
本地服务调用Url (官方文档可点击上方链接跳转阅读)
| Operation | HTTP action | Description |
|---|---|---|
| Register new application instance | POST http://eureka1.com:7901/eureka/apps/appID | Input: JSON/XMLpayload HTTPCode: 204 on success |
| De-register application instance | DELETE http://eureka1.com:7901/eureka/apps/appID/instanceID | HTTP Code: 200 on success |
| Send application instance heartbeat | PUT http://eureka1.com:7901/eureka/apps/appID/instanceID | HTTP Code: * 200 on success * 404 if instanceIDdoesn’t exist |
| Query for all instances | GET http://eureka1.com:7901/eureka/apps | HTTP Code: 200 on success Output: JSON/XML |
| Query for all appID instances | GET http://eureka1.com:7901/eureka/apps/appID | HTTP Code: 200 on success Output: JSON/XML |
| Query for a specific appID/instanceID | GET http://eureka1.com:7901/eureka/apps/appID/instanceID | HTTP Code: 200 on success Output: JSON/XML |
| Query for a specific instanceID | GET http://eureka1.com:7901/eureka/instances/instanceID | HTTP Code: 200 on success Output: JSON/XML |
| Take instance out of service | PUT http://eureka1.com:7901/eureka/apps/appID/instanceID/status?value=OUT_OF_SERVICE | HTTP Code: * 200 on success * 500 on failure |
| Move instance back into service (remove override) | DELETE http://eureka1.com:7901/eureka/apps/appID/instanceID/status?value=UP (The value=UP is optional, it is used as a suggestion for the fallback status due to removal of the override) | HTTP Code: * 200 on success * 500 on failure |
| Update metadata | PUT http://eureka1.com:7901/eureka/apps/appID/instanceID/metadata?key=value | HTTP Code: * 200 on success * 500 on failure |
| Query for all instances under a particular vip address | GET http://eureka1.com:7901/eureka/vips/vipAddress | * HTTP Code: 200 on success Output: JSON/XML * 404 if the vipAddressdoes not exist. |
| Query for all instances under a particular secure vip address | GET http://eureka1.com:7901/eureka/svips/svipAddress | * HTTP Code: 200 on success Output: JSON/XML * 404 if the svipAddressdoes not exist. |
获取所有节点信息
http://eureka1.com:7901/eureka/apps
这里面就是我们上面注册的两个实例的节点信息了

XML格式看起来属实让人头疼是吧,我们可以用Postman调用
- 在请求头中添加
Accept:application/json参数即可返回JSON格式

{
"applications": {
"versions__delta": "1",
"apps__hashcode": "UP_2_",
"application": [
{
"name": "EUREKASERVER",
"instance": [
{
"instanceId": "rhysni.lan:EurekaServer:7901",
"hostName": "eureka1.com",
"app": "EUREKASERVER",
"ipAddr": "192.168.2.237",
"status": "UP",
"overriddenStatus": "UNKNOWN",
"port": {
"$": 7901,
"@enabled": "true"
},
"securePort": {
"$": 443,
"@enabled": "false"
},
"countryId": 1,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
},
"leaseInfo": {
"renewalIntervalInSecs": 30,
"durationInSecs": 90,
"registrationTimestamp": 1663174216001,
"lastRenewalTimestamp": 1663175866438,
"evictionTimestamp": 0,
"serviceUpTimestamp": 1663174185946
},
"metadata": {
"management.port": "7901"
},
"homePageUrl": "http://eureka1.com:7901/",
"statusPageUrl": "http://eureka1.com:7901/actuator/info",
"healthCheckUrl": "http://eureka1.com:7901/actuator/health",
"vipAddress": "EurekaServer",
"secureVipAddress": "EurekaServer",
"isCoordinatingDiscoveryServer": "true",
"lastUpdatedTimestamp": "1663174216001",
"lastDirtyTimestamp": "1663174185937",
"actionType": "ADDED"
}
]
},
{
"name": "EUREKAPROVIDER",
"instance": [
{
"instanceId": "rhysni.lan:EurekaProvider:8080",
"hostName": "rhysni.lan",
"app": "EUREKAPROVIDER",
"ipAddr": "192.168.2.237",
"status": "UP",
"overriddenStatus": "UNKNOWN",
"port": {
"$": 8080,
"@enabled": "true"
},
"securePort": {
"$": 443,
"@enabled": "false"
},
"countryId": 1,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
},
"leaseInfo": {
"renewalIntervalInSecs": 30,
"durationInSecs": 90,
"registrationTimestamp": 1663174502470,
"lastRenewalTimestamp": 1663175852885,
"evictionTimestamp": 0,
"serviceUpTimestamp": 1663174178276
},
"metadata": {
"management.port": "8080"
},
"homePageUrl": "http://rhysni.lan:8080/",
"statusPageUrl": "http://rhysni.lan:8080/actuator/info",
"healthCheckUrl": "http://rhysni.lan:8080/actuator/health",
"vipAddress": "EurekaProvider",
"secureVipAddress": "EurekaProvider",
"isCoordinatingDiscoveryServer": "false",
"lastUpdatedTimestamp": "1663174502470",
"lastDirtyTimestamp": "1663174502438",
"actionType": "ADDED"
}
]
}
]
}
}
服务状态
http://eureka1.com:7901/eureka/status
{
"generalStats": {
"num-of-cpus": "8",
//总的可使用内存数
"total-avail-memory": "693mb",
//当前占用多少内存
"current-memory-usage": "398mb (57%)",
"server-uptime": "00:35"
},
"applicationStats": {
"registered-replicas": "",
"available-replicas": "",
"unavailable-replicas": ""
},
"instanceInfo": {
"instanceId": "rhysni.lan:EurekaServer:7901",
"hostName": "eureka1.com",
"app": "EUREKASERVER",
"ipAddr": "192.168.2.237",
"status": "UP",
"overriddenStatus": "UNKNOWN",
"port": {
"$": 7901,
"@enabled": "true"
},
"securePort": {
"$": 443,
"@enabled": "false"
},
"countryId": 1,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
},
"leaseInfo": {
"renewalIntervalInSecs": 30,
"durationInSecs": 90,
"registrationTimestamp": 0,
"lastRenewalTimestamp": 0,
"evictionTimestamp": 0,
"serviceUpTimestamp": 0
},
"metadata": {
"management.port": "7901"
},
"homePageUrl": "http://eureka1.com:7901/",
"statusPageUrl": "http://eureka1.com:7901/actuator/info",
"healthCheckUrl": "http://eureka1.com:7901/actuator/health",
"vipAddress": "EurekaServer",
"secureVipAddress": "EurekaServer",
"isCoordinatingDiscoveryServer": "false",
"lastUpdatedTimestamp": "1663174155691",
"lastDirtyTimestamp": "1663174185937"
}
注册到eureka的服务信息查看
Get
{ip:port}/eureka/apps
注册到eureka的具体的服务查看
Get
{ip:port}/eureka/apps/{appname}/{id}
服务续约
Put
{ip:port}/eureka/apps/{appname}/{id}?lastDirtyTimestamp={}&status=up
更改服务状态
- 对应eureka源码的:InstanceResource.statusUpdate
Put
{ip:port}/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
删除状态更新
Delete
{ip:port}/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
删除服务
Delete
{ip:port}/eureka/apps/{appname}/{id}

源码&脚本获取地址
- Postman脚本:
https://www.getpostman.com/collections/8a0954746646f0dee9a6
- 脚本可直接复制到Postman使用
Link方式导入- 实战源码仓库:
https://github.com/RhysNi/SpringCloudFamilyMeals.git




335

被折叠的 条评论
为什么被折叠?



