美文网首页
springboot 使用zookeeper实现服务注册和发现

springboot 使用zookeeper实现服务注册和发现

作者: 奋斗live | 来源:发表于2019-07-26 16:40 被阅读0次
    一、目录结构

    此项目实例是使用多模块maven,并配合springboot进行构建
    结构如下图所示


    image.png
    二、每个maven的配置

    这里是父maven的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <modelVersion>4.0.0</modelVersion>
        <packaging>pom</packaging>
        <modules>
            <module>order</module>
            <module>product</module>
        </modules>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.2.RELEASE</version>
            <relativePath/>
        </parent>
    
    
        <groupId>com.example</groupId>
        <artifactId>springboot_zookeeper</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springboot_zookeeper</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.12</version>
            </dependency>
            <dependency>
                <groupId>com.101tec</groupId>
                <artifactId>zkclient</artifactId>
                <version>0.10</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>4.0.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>4.0.0</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
    
            </plugins>
        </build>
    
    </project>
    
    

    order服务下的maven

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springboot_zookeeper</artifactId>
            <groupId>com.example</groupId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>order</artifactId>
    
    
    </project>
    

    product服务下的maven

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springboot_zookeeper</artifactId>
            <groupId>com.example</groupId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>product</artifactId>
    
    
    </project>
    
    三、product模块

    此模块下的Application代码

    package com.example.product;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.InputStream;
    import java.util.Properties;
    
    @SpringBootApplication
    @RestController
    public class Application {
    
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
    
        }
    
        @RequestMapping(value = "/product/id",method = RequestMethod.GET)
        public String  get(HttpServletRequest request){
            return "访问 product  服务端口:"+ request.getLocalPort();
        }
    
        @Bean
        public Register register(){
            Register register = new Register();
            register.register11(getAddressAndPort());
            return register;
        }
    
    
        private String getAddressAndPort(){
            try {
                Properties properties = new Properties();
                InputStream stream = Application.class.getClassLoader().getResourceAsStream("application.properties");
                properties.load(stream);
    
                Object port = properties.get("server.port");
                return "127.0.0.1:" + port;
            }catch (Exception e){
                throw new RuntimeException();
            }
        }
    }
    
    

    使用Register实现服务的注册

    package com.example.product;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.ZooDefs;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.Stat;
    
    public class Register {
    
        private static final String SERVER_PATH = "/product";
    
        private static final String ZK_ADDRESS = "94.*.*.51:4180";
    
        private static final int ZK_TIMEOUT = 20000;
    
        public void register11(String address){
            try{
                ZooKeeper zooKeeper = new ZooKeeper(ZK_ADDRESS,ZK_TIMEOUT, WatchEvent ->{
    
                });
                Stat stat = zooKeeper.exists(SERVER_PATH,false);
                if(stat==null){
                    zooKeeper.create(SERVER_PATH,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
                String path = address;
                //创建短暂的可排序的子节点
                zooKeeper.create(SERVER_PATH+"/instance",path.getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    

    此模块中对应的application.properties配置

    server.port=8086
    
    四、order模块

    此模块下的Application代码

    package com.example.order;
    
    
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import javax.annotation.Resource;
    
    @SpringBootApplication
    @RestController
    public class Application {
    
        @Resource
        private RestTemplate restTemplate;
    
        @Resource
        private ZookListener listener;
    
        @Bean
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    
        @Bean
        public ZookListener zookListener(){
            ZookListener listener = new ZookListener();
            listener.init();
            return listener;
        }
    
        @RequestMapping(value = "/order/id",method = RequestMethod.GET)
        public String get(){
            //从zookeeper中获取调用的ip
            String path = listener.getPath();
            if(path == null){
                return "对不起,产品暂时停止服务!";
            }
            return restTemplate.getForObject("http://"+listener.getPath()+"/product/id",String.class);
        }
    
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
        }
    }
    
    

    此模块下使用ZookListener类实现获取zookeeper的节点列表,也可以监听zookeeper里面的节点变化

    package com.example.order;
    
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooKeeper;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Random;
    
    
    public class ZookListener {
    
        private static final String SERVER_PATH="/product";
    
        private static final String ZK_ADDRESS="94.*.*.51:4180";
    
        private static final int ZK_TIMEOUT = 20000;
    
        private ZooKeeper zooKeeper;
    
        private List<String> paths = new LinkedList<>();
    
        public void init(){
            try{
                zooKeeper = new ZooKeeper(ZK_ADDRESS,ZK_TIMEOUT,(WatchEvent)->{
                    getChilds();
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private void getChilds(){
            List<String> ips = new LinkedList<>();
            try{
                //添加监听
                List<String> childs = this.zooKeeper.getChildren(SERVER_PATH,true);
                for(String child:childs){
                    byte[] obj = zooKeeper.getData(SERVER_PATH+"/"+child,false,null);
                    String path = new String(obj,"utf-8");
                    ips.add(path);
                }
                this.paths = ips;
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        public String getPath(){
            if(paths.isEmpty()){
                return null;
            }
            int index = new Random().nextInt(paths.size());
            return paths.get(index);
        }
    }
    
    

    此模块中的application.properties

    server.port = 8080
    
    四、测试

    分别启动两个模块的application,如下图


    image.png

    访问浏览器地址http://127.0.0.1:8080/order/id,如下显示

    image.png

    查看zookeeper中的节点值,如下图显示


    image.png
    停止服务

    当我们停止了product模块的时候,访问浏览器,会提示服务停止,如下图


    image.png

    再看看zookeeper中的节点,过了几秒后,就会自动删除了


    image.png

    相关文章

      网友评论

          本文标题:springboot 使用zookeeper实现服务注册和发现

          本文链接:https://www.haomeiwen.com/subject/icsdrctx.html