【Springcloud】(04)中级搭建-Eureka的服务发现Discovery和自我保护
(1)Eureka的服务发现Discovery
(1.1)服务发现基本介绍
微服务向外提供功能,ip是多少、主机名称是什么、服务端口号是多少,对外暴露的服务的信息,
(1.2)修改流程
(1)修改8001的controller
package com.allen.springcloud.controller;
import com.allen.springcloud.entities.CommonResult;
import com.allen.springcloud.entities.Payment;
import com.allen.springcloud.service.PaymentServiceImpl;
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.List;
/**
* @ClassName: PaymenController
* @Author: AllenSun
* @Date: 2020/4/11 1:36
*/
@RestController
@Slf4j
public class PaymenController {
@Resource
private PaymentServiceImpl paymentServiceImpl;
@Value("${server.port}")
private String serverPort;
//可以提供自身的一些服务信息,例如主机名称、ip、端口号等等
@Resource
private DiscoveryClient discoveryClient;
//增添用的往往是post请求,所以这个用PostMapping,但是网页默认的是发送get请求,所以这里要用Postman工具发送post请求
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment) {
int result = paymentServiceImpl.create(payment);
log.info("****插入结果:" + result);
if (result > 0) {
return new CommonResult(200, "插入数据库成功,serverPort:" + serverPort, result);
} else {
return new CommonResult(444, "插入数据库失败", null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentServiceImpl.getPaymentById(id);
log.info("****查询结果:" + payment);
if (payment != null) {
return new CommonResult(200, "查询成功,serverPort:" + serverPort, payment);
} else {
return new CommonResult(444, "查询失败,对应id为:" + id, null);
}
}
@GetMapping(value = "/payment/discovery")
public Object discovery() {
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element:" + element);
}
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance:instances) {
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}
return this.discoveryClient;
}
}
(2)修改启动类,添加注解@EnableDiscoveryClient
(3)测试一下
测试地址:localhost:8001/payment/discovery
(2)Eureka的自我保护机制
(2.1)自我保护的基本介绍
(1)认识自我保护
进入Eureka Server网页看到这串红字,就说明进入保护模式了
(2)什么是自我保护?
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护,只要进入保护模式,Eureka Server就会尝试保护它的服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
一句话总结:某时刻某一个服务不可用了,Eureka Server不会立刻清理,而是继续对这个微服务的信息进行保存。属于CAP里面的AP分支
(3)为什么要有自我保护机制?
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server就会注销这个实例,默认是90秒。
但是有时候Eureka Client是可以正常运行的,只不过是与Eureka Server网络不通,此时不该注销这个微服务,在这种情况下Eureka Server暂时监测不到Eureka Client的心跳,如果没有这种保护机制的话,Eureka Server会立刻清除Eureka Client,这样显然是不行的。
Eureka通过自我保护模式来解决这个问题,就是说当Eureka Server节点再短时间内丢失过多客户时,可能是发生了网络分区故障,那么这个节点就会进入自我保护模式。宁可同时保留所有微服务,也不要盲目的注销任何健康的微服务。
(2.2)如何禁止自我保护(主要用7001和8001来测试)
(2.2.1)修改注册中心Eureka Server端7001
(1)把7001改回单机版,方便测试(也就是不再互相注册)
(2)修改yml出厂默认的自我保护机制是开启的,我们把它设置成关闭的false,并且设置等待时间
(3)启动7001,进入Eureka Server查看效果
访问地址:http://eureka7001.com:7001/
(2.2.2)生产者客户端Eureka Client端8001
(1)同样,先把集群版改成单机版
(2)修改pom,设置时间
(2.2.3)测试一下禁止自我保护后的效果
(1)先启动7001
(2)再启动8001
(3)测试地址:http://eureka7001.com:7001/,查看效果
(4)关闭8001,再查看效果,发现之前注册的微服务消失了!!!