Dubbo+Zookeeper ╰半夏微凉° 2022-05-08 07:24 208阅读 0赞 # [Dubbo+Zookeeper][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 举例子说明: 创建服务端工程: 引入依赖: <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> **创建服务接口的实现类** import com.alibaba.dubbo.demo.DemoService; public class DemoServiceImpl implements DemoService { public String sayHello(String name) { return "Hi " + name; } } Spring配置文件: <!-- 配置当前应用模块名称 --> <dubbo:application name="demo-provider"/> <!-- 配置注册中心的位置 --> <!-- Multicast 注册中心:multicast://224.5.6.7:1234 --> <!-- 配置ZooKeeper注册中心位置方式如下 --> <dubbo:registry address="172.16.166.1: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"/> **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="172.16.166.1: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,创建节点的事务的zxid(ZooKeeper Transaction Id) ctime:znode被创建的毫秒数(从1970年开始) mzxid:znode最后更新的zxid mtime:znode最后修改的毫秒数(从1970年开始) pZxid:znode最后更新的子节点zxid cversion:znode子节点变化号,znode子节点修改次数 dataversion:znode数据变化号 aclVersion:znode访问控制列表的变化号 ephemeralOwner:如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。 dataLength:znode的数据长度 numChildren:znode子节点数量 ZooKeeper四字命令: ruok:测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何响应 stat:输出关于性能和连接的客户端的列表 conf:输出相关服务配置的详细信息 cons:列出所有连接到服务器的客户端的完全的连接 /会话的详细信息。包括“接受 / 发送”的包数量、会话id 、操作延迟、最后的操作执行等等信息 dump:列出未经处理的会话和临时节点 envi:输出关于服务环境的详细信息(区别于conf命令) reqs:列出未经处理的请求 wchs:列出服务器watch的详细信息 wchc:通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表 wchp:通过路径列出服务器 watch的详细信息。它输出一个与 session相关的路径 通过Java程序操作Zookeeper 依赖信息: <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> 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 = "172.16.166.1: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); } } ### 通知机制 ### ![554581-20171017110653490-53356700.png][] **使用方法的递归调用实现持续观察** **![554581-20171017110812271-1622330274.png][]** 代码实现: 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; } } [Dubbo_Zookeeper]: https://www.cnblogs.com/androidsuperman/p/7678536.html [554581-20171017110653490-53356700.png]: /images/20220508/92d19ea82dbe4160b6352b5f7e5d5d0a.png [554581-20171017110812271-1622330274.png]: /images/20220508/965bcd9c80284c49b3d3b097f6041d49.png
还没有评论,来说两句吧...