前言:以前网上学习过Spring Cloud,对于工做上须要是足够了,总归对于一些方面只知其一;不知其二,最近可贵有些闲暇时间,有幸读了崔永超先生的《Spring Cloud 微服务实战》,一方面记录下本身的学习历程和读后感,一方面分享下本身对Spring Cloud微服务的一些看法,写下此文。
注意:本文着重于描述Spring Cloud运行的机制和原理部分,不会涉及到过多的代码,不会演示如何搭建注册发现,高性能注册中心,配置负载均衡等等,可是会对其内部运行机制及原理进行必定的详解。因此本文默认读者有必定的Spring Cloud基础。您若是打算系统学习该技术,本人仍是推荐上述说起书籍。html
固然欢迎大牛指导错误及不足!spring
介绍:Spring Cloud是基于Spring Boot实现的微服务架构工具,提供了配置管理,服务治理,断路器,智能路由,微代理,控制总线,全局锁,决策竞争,分布式会话,集权状态管理等操做。数据库
第一章 服务治理缓存
服务治理是微服务架构的核心与基础,主要实现各个服务实例的自动化注册与发现。Spring Cloud Eureka基于 Netflix Eureka 作了二次封装,主要负责完成微服务架构中的服务治理功能。主要用来实现服务注册发现,同时包含服务端,客户端组件。网络
一.服务注册 服务续约 服务发现
1.服务注册 服务续约架构
服务注册:服务治理中,构建注册中心来统一管理每一个服务,客户端向注册中心发送自身服务的服务名,端口,IP,通讯协议等等元数据信息。注册中心会将其并储存至本地服务清单(双层Map结构存储)。app
高可用注册中心:分布式环境中,咱们须要充分考虑发生故障的状况,因此在生产环境中必须对各个组件进行高可用部署,对于服务注册中心也同样。须要构建高可用的服务注册中心以加强系统的可用性。Eureka Server的设计一开始就考虑了高可用问题,在Eureka的服务治理设计中,全部节点便是服务提供方,也是服务消费方,服务注册中心也不例外。
Eureka Server的高可用实际上就是将本身做为服务向其余服务注册中心注册本身,这样就能够造成一组互相注册的服务注册中心, 以实现服务清单的互相同步, 达到高可用的效果。以集群的方式部署注册中心,容许分片故障期间,其余分片继续提供服务发现注册,故障分片恢复时其余分片会把状态同步回来。不一样的注册中心分片经过异步方式互相复制状态,提供高的实例可用性。负载均衡
如图4个客户端之间能够相互调用。异步
服务续约:客户端向注册中心注册自身的服务信息后,而且周期性的(默认30秒)发送心跳(eurekaTransport.registrationClient.sendHeartBeat方法)来更新服务租约。注册中心若是一段时间(默认90秒)内没收到客户端的心跳续约,则会剔除该客户端。分布式
注册流程详解:
客户端操做:服务启动时发送REST请求到注册中心的方式进行的,以discoveryClent.register(instanceinfo)方法进行服务注册,能够看到以com.netflix.appinfo.Instanceinfo对象为参数,该对象就是注册时客户端给服务端的服务的元数据信息(主机名、IP地址、端口号、状态页和健康检查等等)。
注册中心端操做:注册中心接收到注册请求后,先调用publishEvent函数,将该新服务注册的事件已请求转发的方式传播出去,通知其余节点的注册中心,达到服务同步,然后调用com.netflix.eureka.registry.AbstractlnstanceRegistry父类中的register注册实现,将InstanceInfo中的元数据信息存储在一个ConcurrentHashMap对象中。ConcurrentHashMap<String, Map<String,Lease<InstanceInfo>>>对象,它是一个两层Map结构,第一层的key存储服务名:InstanceInfo中的appName属性,第二层的key存储实例名:InstanceInfo中的instanceId属性。
2.服务发现
服务启动会调用com.netflix.discovery.DiscoveryClient的initScheduledTasks函数,发如今其中还有两个定时任务,分别是 服务获取 和 服务续约。
当咱们启动服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取注册中心存储的服务清单。为了性能考虑,Eureka Server会维护一份只读的服务清单来返回给客户端,同时每一个客户端都会周期的(默认30秒)向注册中心咨询,获取到全部的服务实例清单,存入本地(serverList),能够对其余具体服务实例进行访问。(若但愿修改缓存清单的 更新时间,能够经过 eureka.clent.registry-fetch-interval-seconds=30参数进行修改)。
二.服务消费
服务消费者在获取服务清单后,经过服务名能够得到具体提供服务的实例名和该实例的元数据信息。由于有这些服务实例的详细信息,因此客户端能够根据本身的须要决定具体调用哪一个实例(使用RestTemplate)。
RestTemplate:主要有GET,POST,PUT,DELETE的请求方式。
GET有getForEntity和getForObject的重载。POST有postForEntity和postForObject的重载。
通常咱们都会使用负载均衡结合Ribbon完成。当Ribbon与Eureka联合使用时,Ribbon的服务实例清单RibbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。Ribbon是一个基于HTTP和TCP的客户端负载均衡器,它能够在经过客户端中配置的ribbonServerList服务端列表去轮询访问(默认)以达到均衡负载的做用。
(具体的Ribbon及RestTemplate下章负载均衡会详解)
三.服务下线 失效剔除
3.1服务下线
在系统运行过程当中必然会面临关闭或重启服务的某个实例的状况,在服务关闭期间,咱们天然不但愿客户端会继续调用关闭了的实例。 因此在客户端程序中,当服务实例进行正常的关闭操做时,它会触发一个服务下线的REST请求给注册中心,告诉服务注册中心:我要下线了。注册中心在接收到请求以后,将该服务状态置为下线(DOWN), 并把该下线事件传播出去。
3.2失效剔除
有些时候,咱们的服务实例并不必定会正常下线,可能因为内存溢出,网络故障等缘由使得服务不能正常工做,而服务注册中心并未收到服务下线的请求。为了从服务列表中将这些没法提供服务的实例剔除,注册中心在启动的时候会建立一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除出去。
3.3自我保护
自我保护机制:服务注册到Eureka Server以后,会维护一个心跳链接,告诉Eureka Server本身还活着。EurekaServer在运行期间,会统计心跳失败的比例在15分钟以内是否低于85%, 若是出现低于的状况,EurekaServer会将当前的实例注册信息保护起来,让这些实例不会过时,尽量保护这些注册信息。可是在这段保护期间内实例若出现问题,那么客户端很容易拿到实际已经不存在的服务实例,会出现调用失败的清况,因此客户端必需要有容错机制,好比可使用请求重试、断路器等机制。
若是Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它容许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中的其余分片会把它们的状态再次同步回来。
固然也可使用eureka.server.enableself-preservation=false参数来关闭保护机制,以确保注册中心能够将不可用的实例正确剔除。
四.健康检测
Actuator监控管理:为了系统获取各个微服务相关指标好比环境变量,垃圾收集信息,内存信息,线程池信息,HTTP请求统计。Spring Cloud提供了Actuator模块来自动构建一系列用于监控的端点,而且支持扩展。模块中自带一些经常使用资源的健康指标检接口,好比磁盘空间,DataSource连接,Mongo数据库可用,Rabbit服务,Redis,Solr检测等,也能够本身实现自定义检测器。
默认状况下,Eureka中各个服务实例的健康检测并非经过spring-boot-actuator模块的/health 端点来实现的, 而是依靠客户端心跳的方式来保持服务实例的存活。在Eureka 的服务续约与剔除机制下,客户端的健康状态从注册到注册中心开始都会处于 UP状态, 除非心跳终止一段时间以后,服务注册中心将其剔除。 默认的心跳实现方式能够有效检查客户端进程是否正常运做, 但却没法保证客户端应用可以正常提供服务。因为大多数微服务应用都会有一些其余的外部资源依赖,好比数据库、 缓存、 消息代理等,若是咱们的应用与这些外部资源没法联通的时候, 实际上已经不能提供正常的对外服务了,可是由于客户端心跳依然在运行, 因此它仍是会被服务消费者调用,而这样的调用实际上并不能得到预期的结果。
在Spring Cloud Eureka中,咱们能够经过简单的配置,把Eureka客户端的健康检测交给spring-boot-actuator模块的/health端点, 以实现更加全面的健康状态维护。
本文连接:《Spring Cloud》学习(一) 服务治理!
转载声明:本博客由静影残月创做。可自由转载、引用,但需署名做者且注明文章出处。