spring cloud服务发现有多种实现方式,官方文档中有详细的介绍,这里以zookeeper实现为例。使用zookeeper不仅可以做服务发现,还可以做配置管理,不需要另外的配置服务器,一举两得。
首先必须安装好zookeeper服务并且启动,详细请看
首先是pom依赖,官方文档依赖如下所示。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zookeeper-allartifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.4.12version>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
然后是zookeeper连接地址配置,使用zookeeper配置服务发现,必须配置zookeeper连接地址。在bootstrap配置文件添加。
#zookeeper連接地址
spring.cloud.zookeeper.connect-string=192.168.0.15:2181
SpringApplication代码如下。
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class DiscoverClient {
@Autowired
private DiscoveryClient discoveryClient;
public static void main(String[] args) {
SpringApplication.run(DiscoverClient.class, args);
}
@RequestMapping("/services")
public Object getServices(){
return discoveryClient.getServices();
}
@RequestMapping("/instance")
public Object getInstance(@RequestParam("name") String name){
return discoveryClient.getInstances(name);
}
}
访问localhost:8080/services可以看到所有注册的服务,访问“/instance”可以获取服务实例的信息。查看zookeeper中的节点信息。可以看到多了一个 /services
节点,继续往下跟踪,可以看到这么一个节点
/services/discovery-service/f9f7d237-86cb-4168-a602-137d3cf4aa18
对应的信息
/services/服务名称/服务实例随机id
使用get /services/discovery-service/f9f7d237-86cb-4168-a602-137d3cf4aa18命令,得到以下信息。
{"name":"discovery-service","id":"f9f7d237-86cb-4168-a602-137d3cf4aa18","address":"garinechou","port":8080,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"discovery-service","metadata":{}},"registrationTimeUTC":1536312068939,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
cZxid = 0x100000439
ctime = Fri Sep 07 17:21:09 CST 2018
mZxid = 0x100000439
mtime = Fri Sep 07 17:21:09 CST 2018
pZxid = 0x100000439
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x165b33a0b640004
dataLength = 521
numChildren = 0
可以看出,这里的服务发布方式是基于整个应用程序来发布的,可以跟dubbo对比,dubbo发布服务时是基于接口级别的。dubbo的节点信息类似下面,基于接口注册服务信息。相比spring cloud不一样。
/dubbo/com.garine.dubbo.api.HelloService/providers/dubbo%3A%2F%2F192.168.56.1%3A20880%2Fcom.garine.dubbo.api.HelloService%3Fanyhost%3Dtrue%26application%3Ddubbo-server%26dubbo%3D2.6.1%26generic%3Dfalse%26interface%3Dcom.garine.dubbo.api.HelloService%26methods%3Dsayhi%26owner%3Dgarine%26pid%3D11336%26side%3Dprovider%26timestamp%3D1536312836682
问题1:如果是使用Eureka注册中心进行服务发现,通常为了提供一个高可以的注册中心,都会搭建Eureka集群。Eureka服务器之间会配置相互同步服务注册信息,当有新的服务假如时,同步服务注册信息耗时长,客户端读取的服务注册信息也许会存在较大延迟。
解决1:如果存在这样的问题,可以考虑服务注册于服务信息读取分离,另外部署一个服务信息获取网关,网关定时从注册中心服务器拉取注册信息进行持久化存储,客户端获取注册信息时只从网关获取,同时Eureka服务器只进行注册信息写操作,并且不需要配置Eureka服务器之间进行注册信息同步,省去同步过程。类似读写分离概念,将查询压力分布到网关,注册中心只负责注册职责。
问题2:当一个服务进行注册时,立马断开,然后立马重新连接注册中心注册,这时注册中心可能保存了两个一样的服务注册信息。
解决2:如果是zookeeper的注册中心,这种情况只会短时间存在,因为zookeeper作为注册中心,存储的服务注册信息都是临时节点,只要客户端断开连接,会话失效,过一阵子临时节点信息就会删除掉;如果是Eureka作为注册中心,这种情况可能是会永久存在,Eureka判断是否删除服务注册信息的依据是心跳尝试连接服务看服务是否可用,可用就不删除,在一直可用的情况下,就会一直存在两个一样服务注册信息。