服务治理
-
Spring Cloud 封装了Netflix 公司开发的 Eureka 模块来实现服务治理
-
因为每个服务之间依赖关系比较复杂,管理比较麻烦,所有需要用到服务治理,管理服务之间的依赖关系。可以实现服务调用。负载均衡、容错等,实现服务发现与注册。
-
Eureka 系统架构
服务注册
-
Eureka Server 是服务注册中心,,使用
Eurake
的客户端连接东安Eurake Server
并维持心跳连接。这样,维护人员便可以通过Eureka Server 来检测系统中各个微服务是否正常运行。
Eureka 包含的两个组件
Eureka Server: 提供服务注册服务
-
各个微服务节点通过配置启动后,会在Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中将会存储所有可用节点的信息,服务节点的信息可用在界面中直观看到。
Eureka Client: 通过注册中心进行访问
-
是一个Java 客户端,用于简化Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在启动后,会将Eureka Server 发送心跳(默认周期为30秒)。 如果Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中将服务节点移除 (默认90秒)
Eureka 构建单机
一) 创建Eureka Server
-
创建 Module
-
编写
POM
文件<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.2.RELEASE</version> </dependency>
-
创建
application.yml
文件server: port: 7001 spring: application: name: Eureka7001 eureka: client: fetch-registry: false #是否从Eureka注册中心拉取服务列表 默认为true register-with-eureka: false #是否注册进eureka注册中心 默认为true service-url: defaultZone: http://localhost:7001/eureka/
-
设置主启动类
@SpringBootApplication @EnableEurekaServer // 开启 Eureka Server 功能 public class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class,args); } }
-
启动项目: 在浏览器中访问
http://localhost:7000/
二) 创建 Eureka Client
-
创建
Moudle
-
编写
pom
文件<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
编写
application.yml
server: port: 8081 spring: application: name: cloud-payment-provider # 入住的名称 eureka: client: service-url: defaultZone: http://localhost:7001/eureka/ # 入住地址 instance: hostname: localhost
-
编写主启动类:
@SpringBootApplication @EnableEurekaClient // 开启 EurekaClient 功能 public class PaymentMain8081 { public static void main(String[] args) { SpringApplication.run(PaymentMain8081.class,args); } }
-
启动类 ,访问
http://localhost:7000/
要先启动 Eureka Server -
显示的名称就是
yml
文件中配置的名字 两个一至
Eureka 构建集群
Eureka 集群原理说明
-
互相注册,互相守望
步骤
-
创建 工程 ------ 7001 和 7002
-
编写
pom
-
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.2.RELEASE</version> </dependency>
-
更改系统hosts文件
地址: 地址: C:\Windows\System32\drivers\etc
// 添加以下内容, 127.0.0.1 server1 127.0.0.1 server2
-
编写
YML
-
7001:
server: port: 7001 spring: application: name: Eureka7001 eureka: client: fetch-registry: false #是否从Eureka注册中心拉取服务列表 register-with-eureka: false #是否注册进eureka注册中心 service-url: defaultZone: http://server2:7002/eureka/ instance: hostname: server1
-
7002:
server: port: 7002 spring: application: name: Eureka7002 eureka: client: fetch-registry: false #是否从Eureka注册中心拉取服务列表 register-with-eureka: false #是否注册进eureka注册中心 service-url: defaultZone: http://server1:7001/eureka/ instance: hostname: server2
-
-
访问:
-
访问 7001:
-
访问 7002:
-
-
将 支付 8081 微服务发布到 两台Eureka 集群配置中
service-url: # 集群版 defaultZone: http://localhost:7001/eureka/, http://localhost:7002/eureka/
-
将 订单服务:81 发布到两台Eureka 集群配置中
service-url: # 集群版 defaultZone: http://localhost:7001/eureka/, http://localhost:7002/eureka/
-
测试 : 先启动Eureka Server 7001 和7002 服务,在启动服务提供者 8081 最后启动消费者81
-
Eureka Server 7001
-
Eureka Server 7002
-
订单模块
-
actuator 微服务信息完善
-
主机名称:服务名称修改:
yml 文件中 instance: instance-id: payment8081 # 服务器名称 prefer-ip-address: true # 访问路径可以显示IP 地址
-
效果
-
-
访问信息有 IP 信息提示:
instance: instance-id: payment8081 # 服务器名称 prefer-ip-address: true # 访问路径可以显示IP 地址
服务发现Discovery
-
对于注册进 eureka 里面的微服务,可以通过服务发现来获得该服务的信息
-
定义一个
discoverClient
// 通过服务发现,获取到自己的信息 @Resource private DiscoveryClient discoveryClient;
-
使用 discoverClient 获取信息
@RequestMapping(value ="/payment/discovery") public Object discover(){ List<String> services = discoveryClient.getServices(); // 获取注册的微服务 for (String service : services) { System.out.println("------element:"+service); } // 根据服务名称,获得服务的相关信息 List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-PROVIDER"); for (ServiceInstance instance : instances) { System.out.println("id:"+instance.getServiceId()); System.out.println("host:"+instance.getHost()); System.out.println("port:"+instance.getPort()); System.out.println("url:"+instance.getUri()); } return discoveryClient; }
-
返回结果
-
页面:
-
控制台:
-
Eureka 自我保护机制
-
现象:
-
保护模式主要用于一组客户端和Eureka Server 之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不在删除服务注册表中的数据,也就是不会注销任何微服务
-
如果在Eureka Server 的首页看到,一下提示,表示Eureka 进入了保护模式
-
-
报错的原因:
-
某时刻某一个微服务不可用,Eureka 不会立即清理,依旧会对该服务的信息进行保存,属于CAP里面的AP分支
-
默认情况下,如果Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销掉该实例(默认90秒)。但当网络分区故障发生时,微服务与Eureka Server 之间无法正常通信,如果注销后,就会很危险---------因为微服务本身其实是健康的,此时本不该注销这个微服务。Eureka 通过 自我保护模式 来解决在这个问题 ------------- 当Eureka 短时间内丢失过多客户端时,那么这个节点就会进入自我保护模式
-
-
如何判断是否开启自我保护:
Eureka Server通过判断是否存在大量续约失败的服务,从而确定是否开启自我保护。默认情况下,Eureka Server配置的自我保护阀值是0.85,如果Eureka Server运行期间根据心跳比例接收到的服务续约低于阀值,则Eureka Server开启自我保护,不再剔除注册列表的信息。
-
关闭自我保护:
-
注册中心 Eureka Server 端 7001
yml server: # 关闭自我保护机制,保证不可用服务被及时剔除 enable-self-preservation:false eviction-interval-timer-in-ms:2000 # 如果两秒没有发送续约请求,Eureka Server 会将其剔除
-
生产者客户端 Eureka Client 端 8081
instance: # Eureka 客户端向服务端发送心跳的事件间隔,默认30秒 lease-renewal-interval-in-seconds:1 # 或者 leaseRenewalIntervalInSeconds: 5 # Eureka 服务端子在收到最后一次心跳后等待时间上线,单位为秒,默认90秒,超时将剔除服务 lease-expiration-duration-in-seconds:2 # 或者: leaseExpirationDurationInSeconds
-