Spring Cloud是一套分布式微服务的技术解决方案,它提供了快速构建分布式系统的常用组件,比如说配置管理、服务注册与发现、服务调用的负载均衡、资源隔离、熔断降级等等。不过Spring Cloud只是Spring官方提供的一套标准化的微服务定义。而真正的实现目前有两套比较主流的方案:一个是Spring Cloud Netflix,另外一个是Spring Cloud Alibaba
Spring Cloud Netflix是基于spring boot在Netflix 开源组件基础之上进行封装产生的一整套实现微服务的框架。Spring Cloud Netflix提供了一下几种方案:
服务治理:Spring Cloud Netflix提供了Eureka组件作为服务注册和发现中心,Eureka提供了Eureka Server和Eureka Client用于服务注册和服务发现。
断路器:Spring Cloud Netflix提供了组件Hystrix作为断路器。它的功能是,当对某个服务的调用在一定的时间内,有超过一定次数并且失败率超过一定值,该服务的断路器会打开。
通讯协议:Spring Cloud Netflix 提供了Feign组件作为服务之间的通讯,Feign使用了JAX-RS或spring mvc注解装饰的接口的动态代理实现。
负载均衡:Spring Cloud Netflix 使用Ribbon组件作为负载均衡组件。
路由和过滤:Spring Cloud Netflix 使用Zuul组件作为路由和过滤组件。
Spring Cloud Alibaba是基于阿里巴巴开源组件集成的一套微服务解决方案,目前算比较主流。
Spring Cloud AliBaba提供了更完善的分布式解决方案。在Spring Cloud Alibaba中,Dubbo为我们提供了负载均衡,容错,通讯等组件。除此之外,还提供了一些其他的分布式组件:
分布式事务:Spring Cloud AliBaba提供的Seata组件支持分布式事务的解决方案。
分布式消息通讯:毫无疑问消息通讯肯定使用的是alibaba提供的RocketMQ组件。
服务注册和发现:除了zooKeeper等,Spring Cloud Alibaba还为我们提供了Nacos作为配置服务和服务注册和发现中心组件。
流量控制和服务降级:Alibaba的Sentinel组件提供了的流量控制、断路和系统自适应保护等功能。
其他常用组件 Spring Cloud 除了集成其他分布式框架之外,还开发了一些自己的组件:比如Spring Cloud Config作为配置中心,Spring Cloud Gateway作为统一网关,Spring Cloud Stream用于简化消息组件(比如:rabbitmq,kafka,RocketMQ等)的开发等,更多组件可以参考Spring官方网站。
有了Spring Cloud 这样的技术生态,可以让我们快速地落地微服务的解决方案,有了Spring Cloud 这样的技术生态,可以使我们在开发微服务的时候,快速地去解决一些技术的问题,不需要去考虑第三方技术集成带来额外成本。只要通过一些简单的配置组件,可以完成我们在微服务架构下落地的一些技术问题,从而可以让我们更加关注在代码层面,关注在业务的实现层面,以上这些就是我对Spring Cloud 的个人理解。
服务注册与发现
什么是服务注册?
服务注册是指服务提供者将自己的服务信息(如服务名、IP 地址等)告 知服务注册中心。
什么是服务发现?
注册中心客户端组件从注册中心查询所有服务提供者信息,当其他服务 下线后,注册中心能够告知注册中心客户端组件这种变化。
远程客户端组件与服务提供者之间一般使用某种RPC通信机制来进行服务消费,常见的 RPC 通信方式为 REST API,底层为 HTTP 传输协议。服务提供者通常以 Web 服务的方式提供 REST API 接口;远程客户端组件则通常以模块组件的方式完成 REST API 的远程调用。
注册中心的主要功能: 1)服务注册表维护; 2)服务健康检查;
服务提供者的功能:
- 服务注册
- 心跳续约
- 健康状况查询
远程客户端组件功能:
- 服务发现
- 实例缓存
注册中心框架实现: Zookeeper,Eureka,Nacos、consul
Eureka,Nacos注册中心实现原理
在Nacos 中,服务注册时在服务端本地会通过轮询注册中心集群节点地址进行服务的注册,在注册中心上,即Nacos Server上采用了Map保存实例信息,当然配置了持久化的服务会被保存到数据库中,在服务的调用方,为了保证本地服务实例列表的动态感知,Nacos与其他注册中心不同的是,采用了 Pull/Push同时运作的方式。
Pull拉: 1.服务消费者启动时候从nacosServer中读取指定服务名称的实例列表,缓存到本地;2.开启一个定时任务,每隔10s轮询一次服务列表
Push推: 通过检测心跳,心跳超时则推送服务实例消息。通过UDP协议,无需保证连接的安全性,因为还有pull机制。
Nacos server:
nacos服务端,对外提供的服务接口请求地址为nacos/v1/ns/instance,实现代码在nacos-naming模块下的InstanceController类中
Nacos服务端收到请求后,做以下三件事:
- 构建一个Service对象保存到ConcurrentHashMap集合中(通过putService()方法将服务缓存到内存)
- 使用定时任务对当前服务下的所有实例建立心跳检测机制【 它主要通过定时任务不断检测当前服务下所有实例最后发送心跳包的时间。如果超时,则设置healthy为false表示服务不健康,并且发送服务变更事件。 】 (service.init()建立心跳机制)
- 基于数据一致性协议(Raft) 进行服务数据同步 (consistencyService.listen实现数据一致性监听)
心跳检测机制:主要通过定时任务不断检测当前服务下所有实例最后发送心跳包的时间。如果超时,则设置healthy为false表示服务不健康,并且发送服务变更事件。
服务注册:ServiceRegistry是Spring Cloud提供的服务注册的标准
Nacos提供了SDK和Open API两种形式来实现服务注册。这两种形式本质都一样,底层都是基于HTTP协议完成请求的。所以注册服务就是发送一个HTTP请求。
心跳机制就是客户端通过schedule定时向服务端发送一个数据包 ,然后启动-个线程不断检测服务端的回应,如果在设定时间内没有收到服务端的回应,则认为服务器出现了故障。Nacos服务端会根据客户端的心跳包不断更新服务的状态。【通过beatReactor.addBeatInfo()创建心跳信息实现健康检测】
Nacos服务地址动态感知原理
通过NacosNamingService#subscribe(String serviceName, EventListener listener)方法来实现监听,其中serviceName表示服务名、EventListener表示监听到的事件或者调用selectInstance方法,如果将subscribe属性设置为true,会自动注册监听。 Nacos客户端中有一个HostReactor类,它的功能是实现服务的动态更新,基本原理是:
- 客户端发起时间订阅后,在HostReactor中有一个UpdateTask线程,每10s发送一次Pull请求,获得服务端最新的地址列表
- 对于服务端,它和服务提供者的实例之间维持了心跳检测,一旦服务提供者出现异常,则会发送一个Push消息给Nacos客户端,也就是服务端消费者
- 服务消费者收到请求之后,使用HostReactor中提供的processServiceJSON解析消息,并更新本地服务地址列表
Zookeeper用作注册中心
zookeeper可以充当一个服务注册表(Service Registry),让多个服务提供者形成一个集群,让服务消费者通过服务注册表获取具体的服务访问地址(IP+端口)去访问具体的服务提供者。
具体来说,zookeeper就是个分布式文件系统,每当一个服务提供者部署后都要将自己的服务注册到zookeeper的某一路径上: /{service}/{version}/{ip:port},比如我们的HelloWorldService部署到两台机器,那么zookeeper上就会创建两条目录:分别为
/HelloWorldService/1.0.0/100.100.0.237:16888
/HelloWorldService/1.0.0/100.100.0.238:16888。
在zookeeper中,进行服务注册,实际上就是在zookeeper中创建了一个znode节点,该节点存储了该服务的IP、端口、调用方式(协议、序列化方式)等。该节点承担着最重要的职责,它由服务提供者(发布服务时)创建,以供服务消费者获取节点中的信息,从而定位到服务提供者真正网络拓扑位置以及得知如何调用。RPC服务注册、发现过程简述如下:
1.服务提供者启动时,会将其服务名称,ip地址注册到配置中心。
2.服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地,以供后续使用。当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务。
3.当服务提供者的某台服务器宕机或下线时,相应的ip会从服务提供者IP列表中移除。同时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
4.当某个服务的所有服务器都下线了,那么这个服务也就下线了。
5.同样,当服务提供者的某台服务器上线时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
6.服务提供方可以根据服务消费者的数量来作为服务下线的依据。
感知服务的下线&上线
zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除。比如100.100.0.237这台机器如果宕机了,那么zookeeper上的路径就会只剩 /HelloWorldService/1.0.0/100.100.0.238:16888。
服务消费者会去监听相应路径(/HelloWorldService/1.0.0),一旦路径上的数据有任务变化(增加或减少),zookeeper都会通知服务消费方、服务提供者地址列表已经发生改变,从而进行更新。
Zookeeper,Eureka,Nacos主要区别:Zookeeper注重CP,Eureka、Nacos注重AP 优缺点: