SpringCloud 1
1. RestTemplate
spring cloud是基于rest 的框架, 所以在调用其他服务的时候, 可以支持用restTemplate来调用.
可以在spring中首先用@Bean的方式把ResTemplate放入spring容器
@Configuration
public class MyConfig {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
使用:
private final RestTemplate restTemplate;
restTemplate.getForOject(url, request,Response.class);
有很多其他的方法, 可以查看文档
2. Eureka 服务注册与发现
-
springcloud封装lNetFlix的Eureka模块来实现注册与发现
-
Eureka采用C/S架构, 需要自己写一个项目Eureka-Server来作为注册服务器, 是服务注册中心, 其他服务就可以使用Eureka客户端来进行连接;
-
其他模块和Eureka-Server的连接是心跳连接, 默认30s, 各个微服务启动后, 会向EurekaServer发送心跳,使Server可以监测到各个服务存活。
-
如果没有发现心跳,按理来说 Server会从服务注册表中移除这个没有心跳的服务节点,但是,因为有自我保护机制, 所以当一个服务宕机, 在Eureka的注册表中并不会立刻注销这个服务节点, 而是保留注册表中该服务的信息, 并等待该服务发送心跳;当收到的心跳数大于恢复的阈值时, 将推出自我保护模式。(好死不如濑活)
2.1 自己写一个Eureka-Server来作为注册中心服务器
创建一个springboot项目
build.gradle中
#导入Eureka-server到包:
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
yml配置
server:
port: 8761
eureka:
instance:
hostname: eureka-server #Eureka-Server项目的实例名, 类似每一个微服务名字
client:
register-with-eureka: false # 是否向注册中心注册自己(server不需要注册自己
fetch-registry: false # false, 是否从Eureka中获取注册信息
service-url: #eureka的项目地址
defalutZone: http://${eureka.instance.hostname}:${server.port}/enureka/
在主启动类上添加
@EnableEurekaServer
启动后访问该项目的端口号就可以访问admin页面(localhost: 8761)
2.2 添加微服务到Eureka注册中心
build.grale 导入依赖
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
yml添加:
spring:
application:
name: first-server-provider #用于此服务的名称
eureka:
client:
service-url:
defalutZone: http://eureka-server:8761/enreka/
主启动类添加:
@EnableDiscoveryCliennt
另外, 想获得更多的Eureka信息, 可以通过DiscoveryClient(Spring的)来获取;
eg:
@Autowired
private DiscoveryClient client;
List<String> services = client.getServices();
2.3 Eureka集群配置
比如, 现在有一个provider-server, 有三个eureka项目, 分别是eureka01,eureka02, eureka03;现在要把这个项目注册到三个eureka中, 并且, 三个eureka项目需要互相关联
因此, 在配置时,
eureka01项目的defaultZone: http://eureka02:8761/eureka/,http://eureka02:8761/eureka/
;既每一个项目的eureka defaultZone需要有其他两个eureka项目的注册中心地址;
provider-server项目的defaultZone中需要写三个eureka项目的地址;
这样, 就可以在一个有三个eureka项目的集群中, 配置一个微服务项目, 这样可以防止一个eureka服务宕机的问题, 保证一个宕机, 其他注册中心仍然可用的状态。
2.4 Zookeeper和Eureka的对比
关系型数据库RDBMS(Msql。。。) 满足 ACID原则
NoSQL(redis, mongdb) 满足CAP原则
2.4.1 CAP原则:
Consistency 强一致性(数据一致性)
Availability 可用性(通用性)
Partition tolerance 分区容错性(扩展性)
CAP的三进二: 一个分布式系统最多能满足两个条件:CA, AP, CP
CA:满足 consistent, availability, 单点集群, 满足一致性和可用性, 扩展性差
CP: 一致, 分区容错性的系统(可扩展), 通用性差
AP:满足可用性和分区容错性, 一致性差
实际上, 如果不满足P, c和a是无法实现的, 所以只有ap和cp(分布式系统必须满足p)
一下对比中说的都是基于“注册服务”来说, 并不是注册中心提供的其他服务
-
Zookeeper保证的是CP
zk会出现: 当master节点因为网络故障失去联系, 剩余节点会重写选举leader, 在选举期间, 整个zk集群都是不可用的, 这就导致在选举中注册服务瘫痪, 因此会出现不可用的情况
-
Eureka保证的是AP
Eureka的各个节点都是平等的, 所以几个节点挂掉不影响使用;当服务注册时, 发现一个节点失败, 会切换到其他节点, 只要有一台节点可用, 就保证注册服务的可用性, 只是查到的信息可能不是最新的;
-
此外, Eureka还有自我保护机制, 如果15分钟以内, 85%以上的节点没有正常的心跳, Eureka就认为客户端和注册中心出现了网络故障, 此时:
-
Eureka不再从注册列表移除长时间没有心跳的服务
-
Eureka仍然接受新服务的注册和查询要求, 但不会同步到其他节点上(只保证当前节点依然可用)
-
网络稳定后, 当前Eureka实例中新的注册信息会被同步到其他节点
-
因此, Eureka可以很好的应对因网络故障二导致节点失去联系的情况, 而不会像zookeeper使整个服务瘫痪。
3. 负载均衡 Ribbon
Ribbon是一套客户端(在微服务里, 客户端就是使用其他微服务的consumer-server)负载均衡工具
Load Balance, 简单来说就是将用户的请求平摊到多个服务上,达到系统的高可用(HA)
负载均衡的分类:
-
集中式LB: 既服务的消费者和提供者之间使用独立的LB, 如nginx,负责把请求通过某种策略发送给服务的提供方;
-
进程式LB: 把LB策略集成到消费方, 消费方从服务注册中心获知有哪些地址可用, 然后自己在这些地址中选择合适的服务器
Ribbon就是进程式LB, 只是一个类库, 集成到消费方进程(即需要从注册中心获取其他微服务提供者的地址的服务方称为消费方)
3.1 Ribbon使用
目前, ribbon已经集成到eureka库里了, 不需要额外依赖
思想:
有三个eureka注册中心组成的集群(eureka01-03,eureka集群在这里不是重点), 已经注册了三个provider-server, 这个微服务的spring.application.name
名称是: PROVIDER-SERVER。
三个提供者的instance-id不一样(在eureka中可以看到是同一个AppName, 但是是不同的instance)
有个一消费的微服务consumer-server, 其中使用restTemplate来访问provider-server
这时, 需要消费者进行负载均衡的访问提供者,
-
在yml配置中配置eureka的defaultZone为三个eureka的地址;
-
在把RestTemplate当作@Bean注入的地方加上注解@LoadBalanced
-
使用restTemplate的时候, url里面要写
http://PROVIDER_SERVER...
, 这是一个变量, 是注册在微服务中的provider-server的appID。 -
这样, consumer从eureka集群中拿到PROVIDER-SERVER服务, 可以通过在服务端的负载均衡, 来决定查询三个提供者中的哪一个。
3.2 负载均衡算法
IRule是负载均衡的主要接口, 可以选择算法和自定义算法等
自定义后, 在主启动类上写
@RibbonClient(name = "要去调用的微服务名称", configuration = xxxRule.class
4. Feign
feign是声明式的web service客户端, 让微服务之间的调用变得更简单了, 类似于controller调用service。同时spring cloud集成了Ribbon和Eureka, 可以使用feign式提供负载均的http客户端。
调用微服务有两种方式: 1. 微服务名称(ribbon) 2. 接口和注解(feign)
使用:
写一个接口, 把provider中的需要用到的接口都写一遍(和controller中的一样)
加上 @FeignClient(value = "provider的名称")
注解, 主启动类加@EnableFeignClients