上一篇文章《手把手教你写rpc框架系列(五)定义zookeeper数据交互的序列化和反序列化》我们介绍了zookeeper元数据的序列化和反序列化,这篇文章我们就来实现整个微服务的自动注册。
首先我们定义一个register的注册接口,里面主要做两件事情,第一件事向zookeeper注册服务,第二件事是从zookeeper获取注册的服务,定义的接口类是:ServiceRegister,完整代码如下:
package org.wz.rpc.framework.register; import org.wz.rpc.framework.model.ServiceObject; public interface ServiceRegister { //需要把服务注册到注册中心去 void register(ServiceObject serviceObject) throws Exception; //需要把服务从注册中心给查出来 ServiceObject getServiceObject(String serviceName) throws Exception; }
既然有了注册的业务接口,那么我们肯定是需要编写一个实现类的,这里我们先编写一个本地缓存的简单实现类,主要是把注册的信息存放在map里面,然后获取服务的时候,直接从这个map里面获取即可,实现类是:DefaultServiceRegister,完整代码如下:
package org.wz.rpc.framework.register; import java.util.HashMap; import java.util.Map; import org.wz.rpc.framework.model.ServiceObject; /** * 默认服务注册器 */ public class DefaultServiceRegister implements ServiceRegister { /** * 把service缓存在内存中,这样子方便直接进行读写 */ private Map<String, ServiceObject> serviceMap = new HashMap<String, ServiceObject>(); @Override public void register(ServiceObject serviceObject) throws Exception { if (serviceObject == null) { throw new RuntimeException("注册的服务信息为空,请检查"); } this.serviceMap.put(serviceObject.getName(), serviceObject); } @Override public ServiceObject getServiceObject(String serviceName) { return this.serviceMap.get(serviceName); } }
上面这个类其实相当于是一个本地缓存的服务,在真实的情况下,一般我们向zookeeper注册的时候,会在本地存储一份,上面我们编写了本地存储的那份,但是还没有编写向zookeeper注册的逻辑,所以这里我们编写一个ZookeeperServiceRegister类,实现向zookeeper注册。ZookeeperServiceRegister类的完整代码如下:
package org.wz.rpc.framework.register; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URLEncoder; import org.I0Itec.zkclient.ZkClient; import org.wz.rpc.framework.model.ServiceObject; import org.wz.rpc.framework.model.ZookeeperMetadataData; import org.wz.rpc.framework.serializer.ZookeeperSerializer; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @Slf4j public class ZookeeperServiceRegister extends DefaultServiceRegister implements ServiceRegister { // 定义ZkClient private ZkClient client; // 定义元数据的协议 private String protocol; // 定义服务暴露的端口 private Integer port; /** * 初始化的时候,把zookeeper的信息初始化进去 * * @param zkAddress * @param port * @param protocol */ public ZookeeperServiceRegister(String zkAddress, Integer port, String protocol) { log.info("初始化zookeeper连接"); client = new ZkClient(zkAddress); client.setZkSerializer(new ZookeeperSerializer()); this.port = port; this.protocol = protocol; } @Override public void register(ServiceObject serviceObject) throws Exception { log.info("准备向zookeeper注册自身服务信息:{}", JSON.toJSONString(serviceObject)); super.register(serviceObject); // 首先拼接存储到zookeeper上的元数据信息 ZookeeperMetadataData metaData = this.getNewZookeeperMetaData(serviceObject); this.writeMetaData2Zookeeper(metaData); } private void writeMetaData2Zookeeper(ZookeeperMetadataData meta) { // servicename,例如:org.shop.api.UserService String serviceName = meta.getName(); String uri = JSON.toJSONString(meta); try { // 例如: // {"address":"192.168.31.147:18000","name":"org.shop.api.UserService","protocol":"wz-rpc"} uri = URLEncoder.encode(uri, RPCConstants.UTF_8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // zookeeper写数据的路径,例如:/wz-rpc/org.shop.api.UserService/service String servicePath = RPCConstants.ZK_SERVICE_PATH + RPCConstants.PATH_DELIMITER + serviceName + "/service"; if (!client.exists(servicePath)) { client.createPersistent(servicePath, true); } // 这里是把数据写入到路径里面去 String uriPath = servicePath + RPCConstants.PATH_DELIMITER + uri; if (client.exists(uriPath)) { client.delete(uriPath); } client.createEphemeral(uriPath); } /** * 构建新的实例的元数据信息 * * @param serviceObject * @return * @throws Exception */ private ZookeeperMetadataData getNewZookeeperMetaData(ServiceObject serviceObject) throws Exception { ZookeeperMetadataData meta = new ZookeeperMetadataData(); String host = InetAddress.getLocalHost().getHostAddress(); String address = host + ":" + port; meta.setAddress(address); meta.setName(serviceObject.getClazz().getName()); meta.setProtocol(protocol); return meta; } }
这里的逻辑就是调用zookeeper的api,实现向zookeeper进行注册,同时这里的
super.register(serviceObject);
实现了把注册信息填写到本地的内存中。
以上我们编写的zookeeper注册客户端的工具类就实现了,按照惯例,附上本案例的源码,登录后即可下载。
还没有评论,来说两句吧...