目录
什么是服务治理
在传统的rpc远程调用框架中,管理每个服务与服务之间的依赖关系比较复杂,所以需要服务治理,管理服务与服务之间的依赖关系,可以实现服务调用,负载均衡,容错等,实现服务发现和注册。
springcloud使用Eureka实现服务治理。
服务注册和发现
Eureka两组件
Eureka Server服务端构建
创建一个子模块装门安装部署Eureka Server服务端
依赖:
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--下面的依赖可以不要-->
<dependency>
<groupId>com.lzh.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件:
server:
port: 7001
eureka:
instance:
#eureka服务端的实例名字
hostname: localhost
client:
#标识不向注册中心注册自己
register-with-eureka: false
#表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动类:
启动,访问http://localhost:7001/
,安装成功!
Eureka Client 客户端构建
依赖:
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件:
## eureka客户端配置
eureka:
client:
#标识是否向注册中心注册自己
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true.
#单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
启动类:
测试:启动eureka服务端,在启动客户端。
消费者客户端注册是一样的。
集群
Eureka工作流程
微服务RPC远程服务调用的最核心是高可用!
所以搭建Eureka集群,实现负载均衡+故障容错。
看图,EurekaServer必须集群多节点,服务提供者也必须集群多个!
集群注册原理
互相注册,相互守望
如果有3个节点7001,7002,7003。
那么7002,7003会往7001上注册
7001,7003会往7002上注册
7001,7002会往7003上注册
Eureka集群搭建
再见建一个Eureka服务端子模块
依赖:同上面的服务端
启动类:同上
hosts:
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
配置:
7002节点的配置:使得7002往7001上去注册
server:
port: 7002
eureka:
instance:
#eureka服务端的实例名字
hostname: eureka7002.com
client:
#标识不向注册中心注册自己
register-with-eureka: false
#表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
#多个逗号隔开
defaultZone: http://eureka7001.com:7001/eureka/
7001节点配置修改:使得7001往7002上去注册
server:
port: 7001
eureka:
instance:
#eureka服务端的实例名字
hostname: eureka7001.com
client:
#标识不向注册中心注册自己
register-with-eureka: false
#表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7002.com:7002/eureka/
启动两个服务端节点。
访问http://localhost:7001/
,发现节点7002注册上来了
访问http://localhost:7002/
,发现节点7001注册上来了
客户端注册到Eureka集群
将服务提供者和消费者都注册到集群
配置修改:
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
启动消费者和提供者。
7001
7002
服务提供者集群搭建并实现负载均衡功能
启动Eureka集群
服务提供者集群搭建
再创建一个服务提供者子模块:
和8001的提供者完全一样。要修改的地方:
改个端口就完事,主要和8001区别开来
server:
port: 8002
修改8001和8002的controller主要为了演示负载均衡
服务消费者修改
地址就是应用名,如下图
开启负载均衡功能
加上注解 @LoadBalanced
@Configuration
public class ApplicationContextConfig {
// 不加@LoadBalanced会出现:nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
测试
启动服务提供者集群,可以看到服务提供者的两个节点注册上了
启动消费者。
多次访问接口:http://localhost/consumer/payment/get/1
发现消费者,使用轮询的方式调用提供者的服务。
actuator微服务信息完善
得先导入这些依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
主机名称:服务名称修改
## eureka客户端配置
eureka:
instance:
instance-id: payment8001
访问信息有ip信息提示
instance:
instance-id: payment8001
prefer-ip-address: true
服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
示例
随便修改一个服务提供者
controller:
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery(){
//获取微服务列表
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("***** element:"+element);
}
//获取 微服务CLOUD-PAYMENT-SERVICE的具体信息
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;
}
启动类:加注解
@EnableDiscoveryClient
启动,测试
http://localhost:8001/payment/discovery
看日志:
自我保护机制
保护模式主要用于一组客户端和EurekaServer之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不在删除服务注册表中的数据,也就是不会注销任何微服务。
出现这段提示表示进入保护模式:
一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。属于CAP里面的AP分支。高可用,分区容错性
为什么会产生Eureka自我保护机制?
为了防止EurekaClient可以正常运行,但是与Eureka Server网络不通情况下,Eureka Server不会立刻将Eureka Client服务剔除。
什么是自我保护模式?
默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer
将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
禁用自我保护
出厂默认,自我保护机制是开启的。
使用eureka.server.enable-self-preservation = false
可以禁用自我保护模式:
服务端配置:
server:
enable-self-preservation: false
##默认是90秒没有接受到某个微服务实例的心跳注销该实例
eviction-interval-timer-in-ms: 2000
客户端配置:
#Eureka客户端向服务端发送心跳的时间间隔,默认30秒
eureka.instance.lease-renewal-interval-in-seconds=1
#Eureka服务端在收到最后一次心跳后等待时间上限,默认90秒,超时剔除服务
eureka.instance.lease-expiration-duration-in-seconds=2
Eureka停更说明
https://github.com/Netflix/eureka/wiki