在前面,我们的服务端启动的时候会自动把自己的注册信息给注册到zookeeper注册中心上,所以那么我们就肯定是要求客户端在启动的时候,就能连接上注册中心,然后从注册中心去获取下所有的服务列表,在客户端需要使用的时候,直接能拿到对应的服务信息。所以这里的话,我们需要实现下服务发现。
实现服务发现的逻辑和流程比较简单,主要是:
连接上注册中心 从注册中心获取到所有的服务列表
因此这里我们首先定义一个ServiceDiscoverer的接口,代码示例如下:
package org.wz.rpc.framework.discovery; import java.util.List; import org.wz.rpc.framework.model.ZookeeperMetadataData; /** * 服务发现抽象类,定义服务发现规范 * */ public interface ServiceDiscoverer { List<ZookeeperMetadataData> getServices(String name); }
这个接口的主要实现就是获取整个服务列表信息,接着我们实现下这个接口,由于我们的注册中心是zookeeper,因此这里的话,我们就定义一个ZookeeperServiceDiscoverer类,代码示例如下:
package org.wz.rpc.framework.discovery; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import org.I0Itec.zkclient.ZkClient; import org.wz.rpc.framework.constants.RPCConstants; import org.wz.rpc.framework.model.ZookeeperMetadataData; import org.wz.rpc.framework.serializer.ZookeeperSerializer; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; /** * Zookeeper服务发现者,定义以Zookeeper为注册中心的服务发现细则 * */ @Slf4j public class ZookeeperServiceDiscoverer implements ServiceDiscoverer { private ZkClient zkClient; public ZookeeperServiceDiscoverer(String zkAddress) { zkClient = new ZkClient(zkAddress); zkClient.setZkSerializer(new ZookeeperSerializer()); } /** * 使用Zookeeper客户端,通过服务名获取服务列表 * 服务名格式:接口全路径 * * @param name 服务名 * @return 服务列表 */ @Override public List<ZookeeperMetadataData> getServices(String name) { String servicePath = RPCConstants.ZK_SERVICE_PATH + RPCConstants.PATH_DELIMITER + name + "/service"; List<String> children = zkClient.getChildren(servicePath); return Optional.ofNullable(children).orElse(new ArrayList<>()).stream().map(str -> { String deCh = null; try { deCh = URLDecoder.decode(str, RPCConstants.UTF_8); } catch (Exception e) { log.error(e.getMessage(),e); } return JSON.parseObject(deCh, ZookeeperMetadataData.class); }).collect(Collectors.toList()); } }
以上我们就实现了一个zookeeper自动发现的工具类了这里我们的项目结构如下:
最后按照惯例,附上本案例的源码,登录后即可下载。
还没有评论,来说两句吧...