微服务分布式架构基础与实战:基于Spring Boot + Spring Cloud
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4 【实例】通过代码获取Consul中的服务信息

2.4.1 实例背景

大部分注册中心底层实现原理都基本相同,主要分为注册中心、服务提供者、服务消费者3个角色。

注册中心会在自身创建相关的服务注册表,让多个服务提供者在表上注册,组织服务提供者形成集群,让服务消费者通过服务注册表获取具体的服务访问地址,访问地址通常以IP+端口号的HTTP形式在Consul内进行存储。在服务消费者调用相关地址后,可以获得服务提供者的功能。在Consul的Web UI控制器中Consul自身的节点为node,每个不同的service会注册到不同的node中,被注册的node将会存储一系列service的相关信息,如该service的IP、端口、调用方式、协议、序列化方式等。从此时开始,对于node来说service是被注册的node中的一个节点。无论一个node中有多少service,对于该node来说都是整合了众多不同地址、不同命名的节点。node之间会不断相互通信,发送到node中的service节点上,就完成了分布式的思想,也是最基础的注册中心能力。在此基础上,每个注册中心都会在保证自身稳定性、性能、文件大小的情况下做出不同的功能(如Consul中的K/V和ACL),提供不同的特性(如Consul中替代心跳的Gossip协议),用户可根据不同的需求场景选择不同的注册中心。

本实例将更改2.3节中的cloud_01工程,并使用Spring Boot应用程序通过Consul注册中心,获得在Consul注册中心上注册的其他微服务及相关地址等信息。

2.4.2 编写获得其他注册服务的代码

为方便测试,编写ConsulController.java类中接口,返回注册中心中相关服务的数据,代码如下。在ConsulController接口中通过Spring Cloud的LoadBalancerClient接口和DiscoveryClient接口,获得Consul注册中心中其他注册服务的相关地址。

LoadBalancerClient类:负载均衡器,继承自ServiceInstanceChooser接口。负载均衡是指分摊到多个操作单元上进行执行,如Web服务器、FTP服务器、企业关键应用服务器和其他关键任务服务器等,共同完成工作任务。LoadBalancerClient负载均衡器含有两个抽象函数execute、reconstructURI,其中execute被重载一次,用来执行(来自)负载均衡器的Service实例指定服务的请求;reconstructURI用来为Service创建一个合适的URI,入参为ServiceInstance对象。

ServiceInstance对象:Spring Cloud整理注册Service服务实例的Java Bean,包括注册Service服务实例的地址、端口号、服务ID等相关信息。

ServiceInstanceChooser接口:只含有一个待实现的choose(serviceID)抽象函数,由负载均衡器指定某个服务ID获得注册在Consul注册中心上的某个Service实例。

DiscoveryClient接口:发现服务(如Eureka注册中心或Consul注册中心上的已注册服务),通常用于读取注册服务的相关信息。DiscoveryClient接口中含有3个待实现抽象函数,分别为description()返回健康检查状态函数,getInstances(String ServiceID)根据服务ID获得Service服务实例信息函数,getServices()获得全部已注册的服务ID。

2.4.3 运行结果

如图2-13所示,通过Java代码获取Consul注册中心上其他服务的注册服务信息,接口返回json数据格式的信息。

图2-13

可使用HttpClient等相关工具,通过Consul注册中心上注册的其他服务URL等相关信息调用其他服务的接口。例如,图2-13中cloud02-application微服务的IP为localhost:50124,只要知道cloud02-application微服务提供接口的名称及入参,即可进行调用。

2.4.4 实例易错点

不可忽视服务注册Consul的初始化时间,如果在上述代码中并没有代码上的Bug,可在调用相关接口时总返回空指针异常等相关错误,就很有可能是启动服务和调用接口的操作时间过快导致的。例如,心跳配置的是15s,则初始化时间应该是在15s以上,15s以后才能根据接口返回其他服务相关信息。错误通常如下。