Spring Cloud是一系列框架的有序集合,它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
Spring Cloud微服务工具包为开发者提供了分布式系统中的配置管理、服务发现、断路器、智能路由、微代理、控制总线等开发工具包。它的各个项目基于Spring Boot,将Netflix的多个框架进行封装,并且通过自动配置的方式将这些框架绑定到Spring的环境中,从而简化了这些框架的使用。由于Spring Boot的简便性,使得我们在使用SpringCloud时,很容易将Netflix各个框架整合进我们的项目中。Spring Cloud下的"Spring Cloud Netflix"模块主要封装了Netflix的以下项目。
除了Spring Cloud Netflix模块,SpringCloud还包括以下几个重要的模块。
Spring Cloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式,这两种方式各有优劣。虽然牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下显得更加合适。
各组件的运行流程如下:
上面只是Spring Cloud体系的一部分,Spring Cloud共集成了19个子项目,里面都包含一个或者多个第三方的组件或框架。Spring Cloud工具框架如下。
Spring Cloud Config:配置中心,利用Git集中管理程序的配置。
Spring Cloud Netflix:集成众多Netflix的开源软件。
Spring Cloud Bus:消息总线,利用分布式消息将服务和服务实例连接在一起,用于在一个集群中传播状态的变化。
Spring Cloud for Cloud Foundry:利用Pivotal Cloud foundry集成应用程序。
Spring Cloud Foundry Service Broker:为建立管理云托管服务的服务代理提供了一个起点。
Spring Cloud Cluster:基于ZooKeeper、Redis、Hazeleast、Consul实现的领导选举和平民状态模式的抽象和实现。
Spring Cloud Consul:基于Hashicorp Consul实现的服务发现和配置管理。
Spring Cloud Security:在Zuul代理中为OAuth2 REST客户端和认证头转发提供负载均衡。
Spring Cloud Sleuth:应用的分布式追踪系统和Zipkin、HTrace、ELK兼容。
Spring Cloud Data Flow:一个云本地程序和操作模型,在一个结构化的平台上组成数据微服务。
Spring Cloud Stream:基于Redis、RabbitMQ、Kafka实现的消息微服务,简单声明模型用于在Spring Cloud应用中收发消息。
Spring Cloud Stream App Starters:基于Spring Boot为外部系统提供Spring的集成。
Spring Cloud Task:短生命周期的微服务,为Spring Boot应用简单声明添加功能和非功能特性。
Spring Cloud Task App Starters:任务调度框架。
Spring Cloud ZooKeeper:服务发现和配置管理基于Apache ZooKeeper。
Spring Cloud for Amazon Web Services:快速和亚马逊网络服务集成。
Spring Cloud Connectors:便于PaaS应用在各种平台上连接到后端数据库和消息经纪服务。
Spring Cloud Starters:项目已经终止并且在Angel.SR2后的版本和其他项目合井。
Spring Cloud CLI:基于Spring Cloud CLI,可以以命令行方式快速建立云组件。
这些工具集还在不断地增加。
ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。由于ZooKeeper的开源特性,后来开发者在分布式锁的基础上,摸索出了其他的使用方法:配置维护、组服务、分布式消息队列、分布式通知/协调等。ZooKeeper性能上的特点决定了它能够用在大型的、分布式的系统当中。从可靠性方面来说,它并不会因为一个节点的错误而崩溃。除此之外,它严格的序列访问控制意味着复杂的控制原语可以应用在客户端上。
很多场景下ZooKeeper也作为Service发现服务解决方案。ZooKeeper保证的是CP,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。
Eureka是Netflix开发的服务发现框架,Spring Cloud将它集成在自己的子项目Spring-cloud-netflix中,实现Spring Cloud的服务发现功能。Eureka Sever会提供服务注册功能,各个服务节点启动后,会在Eureka Server中进行注册,这样Eureka Server中就有了所有服务节点的信息,并且Eureka有监控页面,可以在页面中直观地看到所有注册的服务的情况。同时Eureka有心跳机制,当某个节点服务在规定时间内没有发送心跳信号时,Eureka会从服务注册表中把这个服务节点移除。Eureka还提供了客户端缓存的机制,即使所有的Eureka Server都挂掉,客户端仍然可以利用缓存中的信息调用服务节点的服务。Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理地进行负载。Eureka遵守的就是AP原则。
Eureka程序构成如下。
(1)纯正的Servlet应用,需构建成war包部署。
(2)使用了Jersey框架实现自身的RESTful HTTP接口。
(3) peer之间的同步与服务的注册全部通过HTTP协议实现。
(4)定时任务(发送心跳、定时清理过期服务、节点同步等)通过JDK自带的Timer实现。
(5)内存缓存使用Google的guava包实现。
Eureka的高级架构:
可以看出在这个体系中有2个角色,即Eureka Server和Eureka Client。而Eureka Client又分为Application Service和Application Client,即服务提供者和服务消费者。每个区域有一个Eureka集群,并且每个区域至少有一个Eureka服务器可以处理区域故障,以防止服务器瘫痪。
etcd是一个高可用的键值存储系统,主要用于共享配置和服务发现。etcd是由CoreOS开发并维护的,灵感来自ZooKeeper和Doozer,它使用Go语言编写,井通过Raft一致性算法处理日志复制以保证强一致性。Raft是一个新的一致性算法,适用于分布式系统的日志复制,Raft通过选举的方式来实现一致性。Google的容器集群管理系统Kubemetes、开源PaaS平台Cloud Foundry和CoreOS的Fleet都广泛使用了etcd。在分布式系统中,如何管理节点间的状态一直是一个难题,etcd像是专门为集群环境的服务发现和注册而设计的,它提供了数据TTL失效、数据改变监视、多值、目录监听、分布式锁原子操作等功能,可以方便地跟踪并管理集群节点的状态。
Consul(http://www.consul.io/downloads.html)是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置共享。对比其他分布式服务注册与发现的方案,Consul的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现(Raft算法)、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。Consul用Golang实现,因此具有天然可移植性(支持Linux、Windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合。
在注册中心的选择方面,可以针对自身业务的特点,选择一款合适的注册中心,如果团队原有框架基于Dubbo,那么ZooKeeper会更合适一些;如果团队整体使用SpringCloud,那么Eureka的优势就会更大一些;如果团队对于容器化的要求比较高,那么etcd和Consul都是不错的选择。
1.新建工程rpc_eureka_server,并添加Eureka依赖
org.springframework.cloud
spring-cloud-starter-eureka-server
1.4.7.RELEASE
由于是微服务需要引入SpringCloud,由于我的SpringBoot的版本是2.2.5的,所以要引入兼容的SpringCloud版本
org.springframework.cloud
spring-cloud-dependencies
Hoxton.RELEASE
pom
import
2.在应用启动类上添加@EnableEurekaServer注解
3.在配置文件中添加一下配置
server:
port: 8001 #指定服务端口
eureka:
instance:
hostname: 127.0.0.1
client:
register-with-eureka: false #是否将Eureka自身作为应用注册到Eureka注册中心
fetch-registry: false #为true时,可以启动,但报异常: Cannot execute request on any known server
serviceUrl: #服务注册中心的配置内容,指定服务注册中心的位置
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4.注册服务到注册中心,新建一个服务提供方工程rpc_client_demo1,即将服务注册到上面的rpc_eureka_server服务中心里,并且添加依赖
org.springframework.cloud
spring-cloud-starter-eureka
1.4.7.RELEASE
同样需要引入兼容的SpringCloud版本
5.在启动类上添加@EnableDiscoveryClient注解,通过注解,实现服务发现、注册。也可以使用@EnableEurekaClient,这两个的区别就是一个是通用的服务发现,可以发现 Eureka、Consul、ZooKeeper中注册的服务,一个是专门为Eureka使用的。
6.添加示例,新建类ServiceInstanceRestController,然后编写代码
@RestController
public class UserInfoController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/user/{userId}")
public User getUserInfo(@PathVariable String userId){
User user = new User();
user.setId(userId);
user.setName("用户号为"+userId);
return user;
}
@GetMapping("/allUser")
public List getUserInfo(){
List userList = new ArrayList<>();
User user1 = new User("1","小明");
User user2 = new User("2","小红");
User user3 = new User("3","小小");
Collections.addAll(userList,user1,user2,user3);
return userList;
}
@RequestMapping("/service-instance/{serviceId}")
public List getserviceInstance(@PathVariable String serviceId){
return this.discoveryClient.getInstances(serviceId);
}
}
7.添加配置文件,bootstrap.yml和application.yml,bootstrap.yml先于application.yml加载,一般不变的东西配置在bootstrap.yml里,使用的方式是一样的。
bootstrap.yml
application.yml
8.启动两个项目,打开eureka的服务端,打开浏览器,输入localhost:8001
最下面的ip地址对应的是172.17.0.229,在请求中输入http://localhost:7001/allUser,以及http://172.17.0.229:7001/allUser,得到的效果一致
可以在浏览器中输入http://localhost:8001/eureka/apps查看注册中心的元数据信息
对于之前在rpc_eureka_demo1中的请求可以查看某一服务的信息,在请求栏中输入http://172.17.0.229:7001/service-instance/RPC_SERVER_DEMO1