基于Zookeeper集群环境下的服务注册

转载请标明出处:https://blog.csdn.net/LiaoHongHB/article/details/84950486

代码下载地址:https://download.csdn.net/download/liaohonghb/10843684

架构图:

zookeeper服务注册:上面这张图左边是zookeeper集群,右边work server三台是工作服务器 。工作服务器启动时,如果该工作服务器表示master机器,则在zookeeper集群环境中创建master节点,并将工作服务器的相关信息写入master节点数据(比如IP地址等);如果该工作服务器表示slave集群,则在zookeeper集群环境中创建slave(servers)根节点,然后通过zookeeper的命名服务创建server-0000000001子节点,并将工作服务器的相关信息写入该子节点。上图中,server1和server3都是slave机器,server2是master机器。

1、集群环境的搭建:

         可参考博客:https://blog.csdn.net/LiaoHongHB/article/details/84849397

          三台机器地址分别是:192.168.202.128:2181;192.168.202.129:2181;192.168.202.130:2181

 2、新建项目zookeeper-register,在该项目下新建子模块(module):

          register-client1;register-client2;register-client3;register-core;

   3、register-core:

        

        ServiceRegistry:

           

public interface ServiceRegistry {

    /**
     * 注册服务信息
     *
     * @param serviceName    服务名称
     * @param serviceAddress 服务地址
     */
    void register(String serviceName, String serviceAddress);
}

         ServiceRegistryImpl:

@Service
public class ServiceRegistryImpl implements ServiceRegistry, Watcher {

    private static Logger logger = LoggerFactory.getLogger(ServiceRegistryImpl.class);
    private static CountDownLatch latch = new CountDownLatch(1);
    private ZooKeeper zk;
    private static final int SESSION_TIMEOUT = 15000;

    public ServiceRegistryImpl() {
    }

    public ServiceRegistryImpl(String zkServers) {
        try {
            zk = new ZooKeeper(zkServers, SESSION_TIMEOUT, this);
            latch.await();
            logger.debug("connected to zookeeper");
        } catch (Exception ex) {
            logger.error("create zookeeper client failure", ex);
        }
    }

    private static final String REGISTRY_PATH = "/registry";

    @Override
    public void register(String serviceName, String serviceAddress) {
        try {
            if (serviceName.equals("master")) {
                logger.info("创建master节点");
                if (zk.exists("/master", false) == null) {
                    zk.create("/master", serviceAddress.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                }
            } else {
                logger.info("创建slave节点");
                String registryPath = REGISTRY_PATH;
                if (zk.exists(registryPath, false) == null) {
                    zk.create(registryPath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                    logger.debug("create registry node:{}", registryPath);
                }
                //创建服务节点(临时性节点)
                String servicePath = registryPath + "/" + serviceName;
                if (zk.exists(servicePath, false) == null) {
                    zk.create(servicePath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                    logger.debug("create service node:{}", servicePath);
                }

                //创建地址节点
                String addressPath = servicePath + "/address-";
                String addressNode = zk.create(addressPath, serviceAddress.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
                logger.debug("create address node:{} => {}", addressNode, serviceAddress);
            }
        } catch (Exception e) {
            logger.error("create node failure", e);
        }
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected)
            latch.countDown();
    }
}

4、register-client1:

   

application.yml:

server:
  port: 5001
  address: 127.0.0.1

registry:
  servers: 192.168.202.128:2181,192.168.202.129:2181,192.168.202.130:2181

RegistryConfig:通过自定义的servers地址映射到RegistryServiceImpl中的zookeeper集群机器地址

@Configuration
@ConfigurationProperties(prefix = "registry")
public class RegistryConfig {

    private String servers;

    @Bean
    public ServiceRegistry serviceRegistry() {
        return new ServiceRegistryImpl(servers);
    }

    public void setServers(String servers) {
        this.servers = servers;
    }
}

WebListener:通过implement ServletContextListener 中的方法,使得程序一启动就去调用ServiceRegistry.registry方法

@Component
public class WebListener implements ServletContextListener {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${server.address}")
    private String serverAddress;

    @Value("${server.port}")
    private int serverPort;

    @Autowired
    public ServiceRegistry serviceRegistry;


    @Override
    public void contextInitialized(ServletContextEvent sce) {

        logger.info("注册服务:{},{}", serverAddress, serverPort);
        serviceRegistry.register("slave",String.format("%s:%d",serverAddress,serverPort));
//        ServletContext servletContext=sce.getServletContext();
//        ApplicationContext applicationContext= WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
//        RequestMappingHandlerMapping mapping=applicationContext.getBean(RequestMappingHandlerMapping.class);
//        Map<RequestMappingInfo,HandlerMethod> infoMap=mapping.getHandlerMethods();
//        for (RequestMappingInfo info : infoMap.keySet()) {
//            String serviceName=info.getName();
//            logger.info("-----------------" + serviceName);
//            if(serviceName!=null){
//                //注册服务
//                logger.info("注册服务:{},{}", serverAddress, serverPort);
//                serviceRegistry.register(serviceName,String.format("%s:%d",serverAddress,serverPort));
//            }
//        }

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

 5、register-client2和register-client3与register-client1一样,只是参数client1和client2 都是“slave”,client3参数是“master”。

6、运行结果:运行client1、client2、client3 ;结果如下:

猜你喜欢

转载自blog.csdn.net/LiaoHongHB/article/details/84950486