SpringCloud
SpringCloud
套路:
1.导入依赖
2.编写配置文件
3.开启这个功能
4.配置类
前言:如何学习SpringCloud?
1、Api : 网关及路由
2、通信 : http、RPC
3、注册和发现 : 注册中心及高可用
4、熔断机制 : 服务降级(容错)

一、基础知识
1、SpringBoot 和 SpringCloud关系
1.1 SpringBoot专注于快速方便的开发单个个体微服务。
1.2 SpringCloud是关注全局的微服务协调治理框架,它将SpringBoot开发的一个个体微服务整合并管理起来,为各个微服务之间提供: 配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等集成服务。
1.3 SpringBoot可以离开SpringCloud独立使用,开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系
SpringBoot专注于快捷、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架
2、技术选型:Dubbo和SpringCloud对比

3.推荐自学网址
一站式重点自学网站:C语言中文网:C语言程序设计门户网站(入门教程、编程软件) (biancheng.net)
Spring Cloud Netflix : https://springcloud.cc/spring-cloud-netflix.html
中文API文档:https://springcloud.cc/spring-cloud-dalston.html
SpringCloud中国社区:http://springcloud.cn/
SpringCloud中文网:https://springcloud.cc
SpringCloud自学网站重点:Eureka:Spring Cloud服务注册与发现组件(非常详细) (biancheng.net)
二、Rest学习
@RestController
@RequestMapping("/consumer")
public class DeptConsumerController {
//注意:消费者不应该有service层
//RestTemplate,注册到Spring中
//String url, Class<T> responseType
@Autowired//提供多种便捷访问远程http服务的方法,简单的restful模板
private RestTemplate restTemplate;
private static final String REST_URL_PREFIX = "http://localhost:8001";
@RequestMapping("/dept/{id}")
public Dept get(@PathVariable Integer id){
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/"+id,Dept.class);
}
@RequestMapping("/dept/add")
public boolean addDept(Dept dept){//不能加@requestBody此注解
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept,boolean.class);
}
@RequestMapping("/list")
public List<Dept> getAllDept(){
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list",List.class);
}
}
Template
RestTemplate是Spring提供的用于访问Rest服务的客端,RestTemplate提供多种便捷访问远程http服务的方法,简单的restful模板
三、Eureka
1. 实现服务注册与发现的原理

Eureka三大角色:
- 服务注册中心(Register Service):它是一个 Eureka Server,用于提供服务注册和发现功能。
- 服务提供者(Provider Service):它是一个 Eureka Client,用于提供服务。它将自己提供的服务注册到服务注册中心,以供服务消费者发现。
- 服务消费者(Consumer Service):它是一个 Eureka Client,用于消费服务。它可以从服务注册中心获取服务列表,调用所需的服务。
2.Eureka 实现服务注册与发现的流程如下:
- 搭建一个 Eureka Server 作为服务注册中心;
- 服务提供者 Eureka Client 启动时,会把当前服务器的信息以服务名(spring.application.name)的方式注册到服务注册中心;
- 服务消费者 Eureka Client 启动时,也会向服务注册中心注册;
- 服务消费者还会获取一份可用服务列表,该列表中包含了所有注册到服务注册中心的服务信息(包括服务提供者和自身的信息);
- 在获得了可用服务列表后,服务消费者通过 HTTP 或消息中间件远程调用服务提供者提供的服务。
- 服务注册中心(Eureka Server)所扮演的角色十分重要,它是服务提供者和服务消费者之间的桥梁。服务提供者只有将自己的服务注册到服务注册中心才可能被服务消费者调用,而服务消费者也只有通过服务注册中心获取可用服务列表后,才能调用所需的服务。
3.Eureka使用
说明:Eureka是作为服务端Server,所以都是eureka-server。
而Provider和Consumer则是作为客户端Client,所以都是eureka-client
(一)作为注册中心的配置
3.1 导入服务端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
3.2 Eureka配置文件
server.port=7001
#Eureka配置
eureka.instance.hostname=localhost
#表示是否向Eureka注册中心注册自己
eureka.client.register-with-eureka=false
#fetch-register如果为false,则表示自己为注册中心
eureka.client.fetch-registry=false
#监控页面
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
3.3 配置启动类并开启@EnableEurekaServer
@SpringBootApplication //启动后,可以访问http://localhost:7001
@EnableEurekaServer //服务端的启动类,可以接受别人注册进来
public class SpringApplicationEureka {
public static void main(String[] args) {
SpringApplication.run(SpringApplicationEureka.class,args);
}
}
(二)作为服务提供者的配置
3.1 导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
3.2 Provider配置文件
#配置Euerka地址
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/
3.3 配置启动类并开启@EnableEurekaClient
@SpringBootApplication//启动类
@EnableEurekaClient //在服务启动后自动注册到Eureka注册中心!
public class DeptProvider_8001_application {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001_application.class,args);
}
}
4. Eureka自我保护机制
当我们在本地调试基于 Eureka 的程序时,Eureka 服务注册中心很有可能会出现如下图所示的红色警告。

实际上,这个警告是触发了 Eureka 的自我保护机制而出现的。默认情况下,如果 Eureka Server 在一段时间内(默认为 90 秒)没有接收到某个服务提供者(Eureka Client)的心跳,就会将这个服务提供者提供的服务从服务注册表中移除。 这样服务消费者就再也无法从服务注册中心中获取到这个服务了,更无法调用该服务。
但在实际的分布式微服务系统中,健康的服务(Eureka Client)也有可能会由于网络故障(例如网络延迟、卡顿、拥挤等原因)而无法与 Eureka Server 正常通讯。若此时 Eureka Server 因为没有接收心跳而误将健康的服务从服务列表中移除,这显然是不合理的。而 Eureka 的自我保护机制就是来解决此问题的。
所谓 “Eureka 的自我保护机制”,其中心思想就是“好死不如赖活着”。如果 Eureka Server 在一段时间内没有接收到 Eureka Client 的心跳,那么 Eureka Server 就会开启自我保护模式,将所有的 Eureka Client 的注册信息保护起来,而不是直接从服务注册表中移除。一旦网络恢复,这些 Eureka Client 提供的服务还可以继续被服务消费者消费。
综上,Eureka 的自我保护机制是一种应对网络异常的安全保护措施。它的架构哲学是:宁可同时保留所有微服务(健康的服务和不健康的服务都会保留)也不盲目移除任何健康的服务。通过 Eureka 的自我保护机制,可以让 Eureka Server 集群更加的健壮、稳定。
Eureka 的自我保护机制也存在弊端。如果在 Eureka 自我保护机制触发期间,服务提供者提供的服务出现问题,那么服务消费者就很容易获取到已经不存在的服务进而出现调用失败的情况,此时,我们可以通过客户端的容错机制来解决此问题,详情请参考 Spring Cloud Netflix Ribbon 和 Spring Cloud Netflix Hystrix。
默认情况下,Eureka 的自我保护机制是开启的,如果想要关闭,则需要在配置文件中添加以下配置。
eureka.server.enable-self-preservation=false # false 关闭 Eureka 的自我保护机制,默认是开启,一般不建议大家修改
5.CAP原则及对比Zookeeper
5.1 简介
CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A):保证每个请求不管成功或者失败都有响应。
分区容忍性(P):系统中任意信息的丢失或失败不会影响系统的继续运作。
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足
5.2 作为服务注册中心,eureka和zookeeper的对比
前面说到,一个分布式系统不能同时满足CAP原则,相对的分错容错性是分布式系统必不可少的一个部分,所以对于分布式系统只有两种原则实现:AP\CP
ZOOKEEPER:保证的是CP原则,即当我们向服务中心请求资源时,我们可以容忍服务中心返回的是几分钟前的信息,但不接受服务器直接挂掉不可用,也就是说,一致性相对高于可用性,BUG:zk存在一个问题,集群中当master节点挂掉,集群会进行一次内部选举,选一个新的节点作为master,这个时间是很长的(30~120s),在此期间集群处于不可用状态,导致服务瘫痪,这是不可容忍的。
EUREKA:保证的是AP原则,相对zookeeper来说eureka的各个节点都是平等的,几个节点挂掉并不会影响服务的使用,客户端再向服务中心注册服务时,只要有一个节点可用,就不影响服务的注册,另外eureka提供自我保护机制,当一段时间(15min)内超过85%的服务没有心跳时,eureka会认为客户端与服务中心出现网络故障,eureka会采用以下方式处理:
eureka不再移除服务列表中因为长时间没有心跳而应该过期的服务eureka仍可以接受新服务的注册即查询请求,但不会同步到其他节点,保证当前节点可用, 一旦其他节点恢复,再同步
总结
因此,Eureka可以很好的应对因网络故障导致不部分节点失去联系的情况,而不会像zookeeper那样使整个注册中心服务瘫痪。