zoukankan      html  css  js  c++  java
  • Dubbo+Zookeeper

    搭建ZooKeeper服务注册中心

    上传文件:

    zookeeper-3.4.9.tar.gz

    解压zookeeper-3.4.9.tar.gz

    /opt/zookeeper-3.4.9/conf/zoo_sample.cfg复制为/opt/zookeeper-3.4.9/conf/zoo.cfg

    新建目录:/opt/zookeeper-3.4.9/data

    修改/opt/zookeeper-3.4.9/conf/zoo.cfg文件

    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just 
    # example sakes.
    dataDir=/opt/zookeeper-3.4.9/data

    启动ZooKeeper:

    [root@right bin]# pwd
    /opt/zookeeper-3.4.9/bin
    [root@right bin]# ./zkServer.sh start
    ZooKeeper JMX enabled by default
    Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
    Starting zookeeper ... STARTED
    [root@right bin]# ./zkServer.sh status
    ZooKeeper JMX enabled by default
    Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
    Mode: standalone

    永久关闭防火墙:

    chkconfig iptables off

    举例子说明:

    创建服务端工程:

    引入依赖:

    <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>
        <groupId>com.soyoungboy.distribute</groupId>
        <artifactId>DubboConsumer</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <dependencies>
            <dependency>
                <groupId>com.soyoungboy.distribute</groupId>
                <artifactId>DubboInterfaces</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.5.6</version>
            </dependency>
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.6.8</version>
            </dependency>
            <dependency>
                <groupId>com.101tec</groupId>
                <artifactId>zkclient</artifactId>
                <version>0.10</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.3.10.RELEASE</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </project>

    创建服务接口的实现类

    import com.alibaba.dubbo.demo.DemoService;
    
    public class DemoServiceImpl implements DemoService {
    
        public String sayHello(String name) {
            return "Hello " + name;
        }
    
    }

    Spring配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        
        <!-- 配置当前应用模块名称 -->
        <dubbo:application name="demo-provider"/>
        
        <!-- 配置注册中心的位置 -->
        <!-- Multicast 注册中心:multicast://224.5.6.7:1234 -->
        <!-- 配置ZooKeeper注册中心位置方式如下 -->
        <dubbo:registry address="192.168.159.200:2181" protocol="zookeeper"/>
        
        <!-- 配置Dubbo客户端的访问端口 -->
        <dubbo:protocol name="dubbo" port="20880"/>
    
        <!-- 配置接口实现类对应的bean -->    
        <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
    
        <!-- 配置提供的服务的接口 -->
        <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
    
    </beans>

     log4j.properties

    log4j.rootLogger=DEBUG,myConsole
    log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
    log4j.appender.myConsole.ImmediateFlush=true
    log4j.appender.myConsole.Target=System.out
    log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
    log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

    创建客户端工程:DubboConsumer

    引入依赖:

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.8</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.5.5</version>
    </dependency>
    <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.10</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.10.RELEASE</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.soyoungboy.distributed</groupId>
        <artifactId>ServiceInterface</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        
        <!-- 配置当前应用模块名称 -->
        <dubbo:application name="demo-consumer"/>
        
        <!-- 配置注册中心位置 -->
        <dubbo:registry address="192.168.159.246:2181" protocol="zookeeper"/>
        
        <!-- 配置提供服务的接口类型 -->
        <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService"/>
        
        <context:component-scan base-package="com.soyoungboy.distribute.handler"/>
        
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
        
        <mvc:annotation-driven/>
        <mvc:default-servlet-handler/>
    
    </beans>

    在需要调用服务的bean中注入接口类型的bean

    import java.util.Map;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import com.alibaba.dubbo.demo.DemoService;
    
    @Controller
    public class SayHelloHandler {
        
        @Autowired
        private DemoService demoService;
        
        @RequestMapping("/testSayHello")
        public String sayHello(Map<String, Object> map) {
            
            //像调用本地方法一样调用远程服务
            String sayHello = demoService.sayHello("Tom");
            
            map.put("result", sayHello);
            
            return "result";
        }
    
    }

    ZooKeeper

    ZooKeeper=文件系统+通知机制

    文件系统:ZooKeeper使用树形结构管理数据。而且以“/”作为树形结构的根节点。

    通知机制:ZooKeeper的通知机制后,各个模块工程在特定znode上设置Watcher(观察者)来监控当前节点上值的变化。一旦Watcher检测到了数据变化就会立即通知模块工程,从而自动实现“一处修改,处处生效”的效果。

    常用命令:

    启动服务器:./zkServer.sh start
    停止服务器:./zkServer.sh stop
    启动客户端:./zkCli.sh
    退出客户端:[zk: localhost:2181(CONNECTED) 6] quit
    ls:查看当前znode中所包含的内容
    ls2:查看当前节点数据并能看到更新次数等数据
    stat:查看节点状态 stat /tebieshuai
    set:设置节点的具体值
    set 节点 value值 set /tebieshuai new_value
    get:获得节点的值 get /shuai
    get节点
    delete:可以删除指定znode,当该znode拥有子znode时,必须先删除其所有子znode,否则操作将失败。
    rmr:命令可用于代替delete命令,rmr是一个递归删除命令,如果发生指定节点拥有子节点时,rmr命令会首先删除子节点。
    rmr /chou000000008
    create:
    create [-s] [-e] path data acl
    普通创建:不带有-s、-e参数
    -s:含有序列 create -s /chou true
    -e:临时(重启或者超时消失)create -s -e /templ uuu

     stat属性内容:

    czxid:引起这个znode创建的zxid,创建节点的事务的zxidZooKeeper Transaction Id

    ctimeznode被创建的毫秒数(1970年开始)

    mzxidznode最后更新的zxid

    mtimeznode最后修改的毫秒数(1970年开始)

    pZxidznode最后更新的子节点zxid

    cversionznode子节点变化号,znode子节点修改次数

    dataversionznode数据变化号

    aclVersionznode访问控制列表的变化号

    ephemeralOwner:如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0

    dataLengthznode的数据长度

    numChildrenznode子节点数量

    ZooKeeper四字命令:

    ruok:测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何响应
    stat:输出关于性能和连接的客户端的列表
    conf:输出相关服务配置的详细信息
    cons:列出所有连接到服务器的客户端的完全的连接 /会话的详细信息。包括“接受 / 发送”的包数量、会话id 、操作延迟、最后的操作执行等等信息
    dump:列出未经处理的会话和临时节点
    envi:输出关于服务环境的详细信息(区别于conf命令)
    reqs:列出未经处理的请求
    wchs:列出服务器watch的详细信息
    wchc:通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表
    wchp:通过路径列出服务器 watch的详细信息。它输出一个与 session相关的路径

    通过Java程序操作Zookeeper

     依赖信息:

    <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>
        <groupId>com.soyoungboy.zookeeper</groupId>
        <artifactId>ZooKeeper</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <dependencies>
            <dependency>
                <groupId>com.101tec</groupId>
                <artifactId>zkclient</artifactId>
                <version>0.10</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.9</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.9</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>

    Java操作代码:

    import java.io.IOException;
    import java.util.ArrayList;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooDefs.Ids;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.ACL;
    import org.apache.zookeeper.data.Stat;
    
    public class NodeOperation {
        
        /**
         * 设置节点值
         * @param zooKeeper
         * @param path
         * @param nodeData
         * @return
         * @throws KeeperException
         * @throws InterruptedException
         */
        public Stat setNodeData(ZooKeeper zooKeeper, String path, String nodeData) throws KeeperException, InterruptedException {
            
            Stat stat = zooKeeper.setData(path, nodeData.getBytes(), -1);
            return stat;
        }
        
        /**
         * 获取指定节点上的数据
         * @param zooKeeper
         * @param path
         * @return
         * @throws KeeperException
         * @throws InterruptedException
         */
        public String getNodeData(ZooKeeper zooKeeper, String path) throws KeeperException, InterruptedException {
            
            byte[] data = zooKeeper.getData(path, false, new Stat());
            
            return new String(data);
        }
        
        /**
         * 创建节点
         * @param zooKeeper ZooKeeper服务器连接对象
         * @param path 要创建的节点的路径
         * @param nodeData 节点的数据
         * @return
         * @throws KeeperException
         * @throws InterruptedException
         */
        public String createNewNode(ZooKeeper zooKeeper, String path, String nodeData) throws KeeperException, InterruptedException {
            
            //将字符串类型的数据转换为字节数组类型
            byte[] nodeDataBytes = nodeData.getBytes();
            
            //访问控制列表
            ArrayList<ACL> openAclUnsafe = Ids.OPEN_ACL_UNSAFE;
            
            //创建模式
            CreateMode mode = CreateMode.PERSISTENT;
            
            //执行创建
            String result = zooKeeper.create(path, nodeDataBytes, openAclUnsafe, mode);
            
            return result;
            
        }
        
        /**
         * 连接ZooKeeper服务器
         * @return
         * @throws IOException
         */
        public ZooKeeper connectToZookeeper() throws IOException {
            
            //连接ZooKeeper服务器的信息
            String connectString = "192.168.159.200:2181";
            int sessionTimeout = 50 * 1000;
            
            //创建ZooKeeper对象
            ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                
                @Override
                public void process(WatchedEvent event) {
                    //暂时不做任何处理
                }
            });
            
            return zooKeeper;
        }
    
    }

    测试使用代码:

    import java.io.IOException;
    
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.Stat;
    import org.junit.Test;
    
    import com.atguigu.zookeeper.NodeOperation;
    
    public class ZooKeeperTest {
        
        private NodeOperation nodeOperation = new NodeOperation();
        private ZooKeeper zooKeeper = null;
        
        @Test
        public void testSetNodeData() throws KeeperException, InterruptedException {
            Stat stat = nodeOperation.setNodeData(
                    zooKeeper, "/shuai", "are you ok");
            System.out.println(stat);
            int cversion = stat.getCversion();
            System.out.println(cversion);
        }
        
        @Test
        public void testGetNodeData() throws KeeperException, InterruptedException {
            String nodeData = nodeOperation.getNodeData(zooKeeper, "/shuai");
            System.out.println(nodeData);
        }
        
        @Test
        public void testCreateNode() throws KeeperException, InterruptedException {
            
            //create /aaa com.atguigu.service
            
            String path = "/aaa";
            String nodeData = "com.atguigu.service";
            
            String result = nodeOperation.createNewNode(zooKeeper, path, nodeData);
            System.out.println(result);
            
        }
        
        {
            try {
                zooKeeper = nodeOperation.connectToZookeeper();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage());
            }
        }
        
        @Test
        public void testConnection() throws IOException, InterruptedException {
            ZooKeeper zooKeeper = nodeOperation.connectToZookeeper();
            System.out.println(zooKeeper);
            Thread.sleep(Long.MAX_VALUE);
        }
    
    }

     通知机制

     使用方法的递归调用实现持续观察

    代码实现:

    public class MyWatchMulti {
        
        public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
            
            final ZooKeeper zooKeeper = new ZooKeeper("192.168.159.200:2181", 50 * 1000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {}
            });
            
            byte[] nodeData = zooKeeper.getData("/notify", new Watcher() {
                
                //回调:由系统或其他对象调用我们写的方法,而不是像平时我们自己调用自己写的方法
                public void process(WatchedEvent event) {
                    System.err.println("*********接收到通知了[第一次]***********");
                    
                    MyWatchMulti multi = new MyWatchMulti();
                    
                    //调用递归方法持续观察
                    String currentValue = multi.recursionGetData(zooKeeper);
                    System.err.println("当前值="+currentValue);
                    
                    System.err.println("*********接收到通知了[第一次]***********");
                }
            }, new Stat());
            
            System.out.println(new String(nodeData));
            
            Thread.sleep(Long.MAX_VALUE);
            
        }
        
        /**
         * 以递归方式执行获取数据和设置观察者操作实现持续观察
         * @param zooKeeper
         * @return
         */
        public String recursionGetData(final ZooKeeper zooKeeper) {
            byte[] currentValue = null;
            try {
                currentValue = zooKeeper.getData("/notify", new Watcher() {
                    
                    @Override
                    public void process(WatchedEvent event) {
                        
                        //递归调用的核心
                        recursionGetData(zooKeeper);
                    }
                }, new Stat());
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage());
            }
            
            String currentResult = new String(currentValue);
            System.out.println("递归中获取的值="+currentResult);
            
            return currentResult;
        }
    
    }
  • 相关阅读:
    C# Dictionary几种遍历方式
    Android 代码中文字在手机上显示乱码问题解决方法
    【Android学习5】Clean 之后R文件丢失
    【android学习4】Eclipse中Clean作用
    Java基础语法(练习)
    Java基础语法(自定义类、ArrayList集合)
    Java基础语法(方法)
    Java基础语法(数组)
    Java基础(Scanner、Random、流程控制语句)
    Java基础(变量、运算符)
  • 原文地址:https://www.cnblogs.com/androidsuperman/p/7678536.html
Copyright © 2011-2022 走看看