学习是一件需要长期投入的事情,尤其是在当下大环境恶劣的背景下,我们程序员必须要多多的投资自己,去加强自己的技术硬实力和软实力。
你好我是胡弦,一名工作10年的IT老兵,具备非常丰富的微服务架构落地的经验。
笔者曾经做过一次关于注册中心的技术调研,发现一个非常奇怪的现象,那就是“注册中心”的轮子实在是太多了。光是主流的注册中心就有很多,比如Nacos、ZooKeeper、Consul、Sofa、Etcd、Eureka和Kubernetes等。当然还有很多公司会依葫芦画瓢的自研一些重复的轮子,比如笔者曾经在的杭州某独角兽泛娱乐直播公司,就造了很多RPC相关的重复轮子,并且还没人维护。
面对这样的问题,我想大部分的技术负责人都会把技术方向锁定在成熟的开源技术解决方案上,但是面对眼花缭乱的“注册中心”,我们该如何选择?又或者是选定了一个注册中心作为临时过渡的技术方案,后面业务起来之后,还会投入资源去自研一个新的注册中心,那么这个新的注册中心又如何和老的服务做兼容处理等等,总之,我们需要解决的问题太多了。
还有更加痛苦的,当你选型完成之后,发现公司的微服务治理框架并不支持主流的“注册中心”,然后我们又得做架构和技术调整。笔者曾经作为某直播平台的技术负责人参与中台建设时,在技术选型阶段就果断地选择了Spring Cloud Alibaba。目前Spring Cloud Alibaba支持Spring Cloud和Dubbo原生注册中心,完美的解决了“如何选择注册中心”的问题。
下面我会从如下几个方面来分析Spring Cloud Alibaba是如何解决这些问题的。
(1)什么是Spring Cloud原生注册中心;
(2)Spring Cloud Alibaba 是如何整合Spring Cloud原生注册中心的;
(3)整合Spring Cloud原生注册中心(实战)
所谓Spring Cloud原生注册中心是指Spring Cloud官方支持的注册中心, 目前官方支持Eureka、ZooKeeper、Consul和Kubernetes,开发人员只需要引入对应的组件、配置注册中心集群信息和添加注解@EnableDiscoveryClient,就可以快速的使用原生注册中心。
在Spring Cloud Alibaba应用中使用原生注册中心,需要依赖如下组件:
Spring Cloud不支持多注册中心,也就是说在同一个应用服务中,当且仅能使用Spring Cloud原生注册中心中的一种。
回到本篇文章的主题,这里先来描述下Spring Cloud Alibaba 整合Spring Cloud原生注册中心的边界,为了方便理解这里放了一张边界设计图1。
图1
从图中可以得到如下信息:
那么Spring Cloud Alibaba又是如何适配Spring Cloud,并将Nacos整合到Spring Cloud原生注册中心的呢?熟悉Spring Cloud框架的开发人员应该比较清楚,Spring Cloud提供了一个公共的组件包spring-cloud-commons,并将注册中心的公共模块下层到这个组件中。如果开发人员需要将开源的注册中心,比如Nacos等添加到Spring Cloud原生注册中心中,只需要依赖这个组件,并按照标准的规范去封装一个Starter组件即可。
为了方便大家理解原理,我这里将封装的过程拆分为两个部分,一个是服务注册,另外一个是服务发现。
1.服务注册
Spring Cloud有一套标准的服务注册的规范和标准的API,为了方便大家理解,这里将它们提炼成一张图2。
图2
完成服务注册的主要过程如下所示:
(1)首先,如果应用服务启动成功,则会发布一个事件WebServerInitializedEvent(它是Spring Boot框架的一个Web事件,主要是用来表示Spring Boot服务容器启动成功,比如Tomcat等),Spring Cloud 用观察者模式监听这个事件,部分代码如下:
//代码来源于AbstractAutoServiceRegistration类
public void onApplicationEvent(WebServerInitializedEvent event) {
//监听事件WebServerInitializedEvent
bind(event);
}
(2)其次,Spring Cloud监听到Web事件之后,就代表应用服务启动成功,并触发Spring Cloud的服务注册,去注册启动成功的应用服务,部分代码如下:
//代码来源于NacosAutoServiceRegistration类
@Override
protected void register() {
//服务注册的开关
if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
log.debug("Registration disabled.");
return;
}
if (this.registration.getPort() < 0) {
this.registration.setPort(getPort().get());
}
//触发Spring Cloud的服务注册
super.register();
}
(3)最后,调用Nacos的Open API,将启动成功的服务注册到Nacos注册中心,部分代码如下:
//代码来源于NacosServiceRegistry类
@Override
public void register(Registration registration) {
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
//用Nacos的API NamingService将服务注册到Nacos注册中心
namingService.registerInstance(serviceId, group, instance);
}
2.服务发现
Spring Cloud有一套标准的服务发现的规范和标准的API,为了方便大家理解,这里将它们提炼成一张图4。
图4
当消费者服务,利用客户端(比如RestTemplate或者OpenFeign)调用服务提供者暴露的API的URL路径时(比如http://use-restul-api-provider/test/testRestfulApi/,其中use-restul-api-provider为服务提供者的服务名称),触发基于Ribbon的客户端负载均衡机制,最终从Nacos注册中心查询指定服务名称的服务API和服务实例信息。
为了方便大家理解,本文提供了两个简单的例子来配套讲解(具体代码可以参考本文提供的源码),一个是Restful API服务的提供者use-restul-api-provider,另外一个是Restful API服务的消费者use-restul-api-consumer,这两个服务之间的通信协议为REST。读者可以直接运行这两个服务,体验一下使用Spring Cloud支持的不同原生注册中心去完成服务的注册与发现的功能。
我们先来体验一下使用Nacos作为注册中心的过程。
1.搭建注册中心环境
Nacos集群搭建的相关步骤,读者可以参考官方相关文档,本专栏统一采用版本2.0.4。
2.初始化服务
第一步,添加依赖关系和配置信息
快速初始化两个基于Spring Boot的服务,咱们只需要在服务中添加Nacos相关组件的依赖关系,就可以整合Nacos注册中心。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
熟悉Spring Boot框架的开发人员应该都了解,添加了组件的依赖关系之后,就需要添加对应的配置信息,这样组件的功能才会生效。
###对应application-nacos.yaml文件中的Nacos注册中心的配置信息
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 0cbda5a5-2796-47b3-ae16-d45fc9294263
group: spring-cloud-alibaba-advance
关于Spring Cloud Alibaba的版本号,本专栏统一采用版本2.2.7.RELEASE。
第二步,在服务提供者中添加一个Restful API接口,并在启动类中添加一个注解@EnableDiscoveryClient,这样服务启动时,接口会注册到Nacos注册中心。
第三步,在服务消费者中添加一个具备Spring Cloud服务负载均衡功能的RestTemplate客户端。
//使用基于Ribbon的客户端负载均衡
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
第四步,定义一个使用RestTemplate客户端发起HTTP调用请求的接口。
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/testConsumer/{test}")
public String consumer(@PathVariable String test){
return restTemplate.getForObject("http://use-restul-api-nacos-provider/test/
testRestfulApi/"+test, String.class);
}
第五步,启动服务提供者和服务消费者,调用URL地址“127.0.0.1:8830/consumer/testConsumer/2344”,返回响应结果200。
其它注册中心的详细过程,这里就不一一描述了,读者可以先搭建对应注册中心的环境,并在本篇专栏配套的实例源码的配置文件中,添加对应注册中心的配置信息,就可以运行了。
目前Spring Cloud Alibaba可以使用同一个注解@EnableDiscoveryClient,去开启Nacos、ZooKeeper、Consul和Eureka注册中心,开发人员可以几乎零成本的在Spring Cloud Alibaba支持的Spring Cloud原生注册中心之间快速的切换。
总结
今天我给你介绍了Spring Cloud Alibaba是如何整合Spring Cloud原生注册中心的,并且还介绍了Spring Cloud Alibaba是将Nacos添加到Spring Cloud原生注册中心的核心原理,为了方便大家理解原理还提供了相关原理的实战案例。
用过Spring Cloud的开发人员应该比较清楚,一般情况下我们是用Spring Cloud来开发Restful API,那么就意味着我们只能用Spring Cloud原生注册中心(比如Eureka、Consul)来管理这些Restful API,是否可以管理其他协议的API,比如我们大名鼎鼎的Dubbo 接口。