Zookeeper 系列(三)Zookeeper API

本节首先介绍 Zookeeper 的 Shell 命令,再对 Java 操作 Zookeeper 的三种方式进行讲解,本节先介绍 Zookeeper 的原生 API。

  • Zookeeper API:Zookeeper 原生 api
  • ZKClient API
  • Curator API

一、Shell 命令

启动 Zookeeper 服务之后,输入以下命令,连接到 Zookeeper 服务:

  1. zkCli.sh -server localhost:2181

注意: window 下直接 zkCli 启动,不要带参数,否则会报错,详见zookeeper启动抛出NumberFormatException 异常

连接成功之后,输入 help 之后,屏幕会输出可用的 Zookeeper 命令,如下所示:

  1. ZooKeeper -server host:port cmd args
  2. stat path [watch]
  3. set path data [version]
  4. ls path [watch]
  5. delquota [-n|-b] path
  6. ls2 path [watch]
  7. setAcl path acl
  8. setquota -n|-b val path
  9. history
  10. redo cmdno
  11. printwatches on|off
  12. delete path [version]
  13. sync path
  14. listquota path
  15. rmr path
  16. get path [watch]
  17. create [-s] [-e] path data acl
  18. addauth scheme auth
  19. quit
  20. getAcl path
  21. close
  22. connect host:port

(1) 查询 ls

  1. [zk: localhost:2181(CONNECTED) 0] ls /
  2. [zookeeper]
  3. [zk: localhost:2181(CONNECTED) 1] ls /zookeeper
  4. [quota]

(2) 创建新的 Znode 节点 create

  1. [zk: localhost:2181(CONNECTED) 7] create /date 2018-04-05
  2. Created /date
  3. [zk: localhost:2181(CONNECTED) 8] ls /
  4. [date, zookeeper]

(3) 获取 Znode 节点 get

  1. [zk: localhost:2181(CONNECTED) 9] get /date
  2. 2018-04-05
  3. cZxid = 0x7
  4. ctime = Thu Apr 05 14:21:20 CST 2018
  5. mZxid = 0x7
  6. mtime = Thu Apr 05 14:21:20 CST 2018
  7. pZxid = 0x7
  8. cversion = 0
  9. dataVersion = 0
  10. aclVersion = 0
  11. ephemeralOwner = 0x0
  12. dataLength = 10
  13. numChildren = 0

(4) 修改 Znode 节点 set

  1. set /date 2018-04-06

(4) 删除 Znode 节点 delete/rmr

  1. delete /date # 不能删除非空目录
  2. rmr /date # 递归删除

二、Zookeeper API

  1. <dependency>
  2. <groupId>org.apache.zookeeper</groupId>
  3. <artifactId>zookeeper</artifactId>
  4. <version>3.5.0-alpha</version>
  5. </dependency>

示例:

  1. package com.github.binarylei.zookeeper;
  2. import org.apache.zookeeper.*;
  3. import org.apache.zookeeper.data.Stat;
  4. import java.io.IOException;
  5. import java.util.List;
  6. import java.util.concurrent.CountDownLatch;
  7. /**
  8. * @author: leigang
  9. * @version: 2018-04-05
  10. */
  11. public class ZookeeperBase {
  12. /** zookeeper 地址,多个用 , 隔开 */
  13. static final String CONNECT_ADDR = "127.0.0.1";
  14. /** session 超时时间,单位:ms */
  15. static final int SESSION_OUTTIME = 5000;
  16. /** 阻塞程序执行,用于等待zookeeper 连接成功,发送成功信号 */
  17. static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
  18. public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
  19. ZooKeeper zooKeeper = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher() { // (1)
  20. @Override
  21. public void process(WatchedEvent event) {
  22. // 获取事件的状态
  23. Event.KeeperState state = event.getState();
  24. Event.EventType type = event.getType();
  25. // 如果是建立连接
  26. if (state == Event.KeeperState.SyncConnected) {
  27. if (type == Event.EventType.None) {
  28. // 如果连接建立成功,则发送信号,让后续阻塞程序向下执行
  29. connectedSemaphore.countDown();
  30. System.out.println("zookeeper 连接建立");
  31. }
  32. }
  33. }
  34. });
  35. // 进行阻塞,等待与 Zookeeper 的连接建立完成
  36. connectedSemaphore.await();
  37. System.out.println("============================");
  38. //1. 创建节点
  39. zooKeeper.create( // (2)
  40. "/testRoot", // 节点路径,不允许递归创建节点
  41. "testRoot".getBytes(), // 节点内容
  42. ZooDefs.Ids.OPEN_ACL_UNSAFE, // 节点权限,一般情况下不用关注
  43. CreateMode.PERSISTENT); // 节点类型
  44. //2. 获取节点
  45. byte[] data = zooKeeper.getData("/testRoot", false, null);
  46. System.out.println("获取节点:" + new String(data));
  47. //3. 获取子节点
  48. List<String> nodes = zooKeeper.getChildren("/", false);
  49. for (String node : nodes) {
  50. System.out.println("获取" + node + "子节点:" +
  51. new String(zooKeeper.getData("/" + node, false, null)));
  52. }
  53. //4. 修改节点的值
  54. Stat stat = zooKeeper.setData("/testRoot", "111".getBytes(), -1);
  55. //5. 判断节点是否存在
  56. System.out.println("节点是否存在:" + zooKeeper.exists("/testRoot", false));
  57. //6. 删除节点,不支持递归删除
  58. zooKeeper.delete("/testRoot", -1, new AsyncCallback.VoidCallback() {
  59. @Override
  60. public void processResult(int rc, String path, Object ctx) {
  61. System.out.println("响应码:" + rc);
  62. System.out.println("路径:" + path);
  63. System.out.println("上下文:" + ctx);
  64. }
  65. }, 1);
  66. zooKeeper.close();
  67. }
  68. }

(1) 创建会话方法 :客户端可以通过创建一个 Zookeeper 实例来连接 Zookeeper 服务器。ZooKeeper 构造方法 有 4 个,参数说明如下:

  1. connectstring :连接服务器列表,已","分割。
  2. sessiontimeout :心跳检测时间周期期(秒)
  3. wather :事件处理通知器。
  4. canbereadonly :标识当前会话是否支持只读。
  5. session 和 sessionpasswd :提供连接 zookeeper 的 session 和密码,通过这俩个确定唯一台客户端,目的是可以提供重复会话。

注意: Zookeeper 客户端和服务器端会话的建立是一个异步的过程 ,程序方法在处理完客户端初始化后立即返回,也就是说程序继续往下执行代码,这样,大多数情况下我们并没有真正构建好一个可用会话,在会话的生命周期处于 "SyncConnected" 时才算真正建立完毕。解决方案是使用 CountDownLatch 阻塞,起到连接建立完成。

(2) 创建节点

  1. create(final String path, byte data[], List<ACL> acl, CreateMode createMode)
  1. path :节点路径,/nodeName。不允许递归创建节点。
  2. data :节点内容,要求类型是字节数组。
  3. acl :节点权限,一般使用 ZooDefs.Ids.OPEN_ACL_UNSAFE 即可。
  4. createMode :节点类型。PERSISTENT(持久节点)、PERSISTENT_SEQUENTIAL(持久顺序节点)、EPHEMERAL(临时节点)、EPHEMERAL_SEQUENTIAL(临时顺序节点)。

(3) 获取节点

  1. getData(String path, boolean watch, Stat stat)

(4) 获取子节点

  1. getChildren(String path, boolean watch)

(5) 修改节点的值

  1. # version = -1 表示全部的历史版本,一般使用 -1 即可
  2. setData(final String path, byte data[], int version)

(6) 判断节点是否存在

  1. exists(String path, boolean watch)

(7) 删除节点

  1. delete(final String path, int version)

(8) 所有的节点都有同步和异步区分,以delete为例

  1. // 参数分别为:路径,版本(-1即可),回调函数,上下文环境
  2. zooKeeper.delete("/testRoot", -1, new AsyncCallback.VoidCallback() {
  3. @Override
  4. public void processResult(int rc, String path, Object ctx) {
  5. System.out.println("响应码:" + rc);
  6. System.out.println("路径:" + path);
  7. System.out.println("上下文:" + ctx);
  8. }
  9. }, 1);

注册一个异步回调函数,要实现 AsyncCallback.VoidCallback 接口,重写 processResult(int rc, String path, Object ctx) 方法,当节点创建完毕后执行此方法。

  1. rc :为服务端响应码 0(调用成功)、-4(端口连接)、-110(指定节点存在)、-112(会话已经过期)。
  2. path :接口调用时传入 API 的数据节点的路径参数
  3. ctx :为调用接口传入 API 的 ctx 值

三、Zookeeper Watcher

3.1 watcher 的概念

Zookeeper Watcher 事件触发机制详见 Watch 触发器。当 watch 监视的数据发生变化时,通知设置了该 watch 的 client,即 watcher。

同样,其 watcher 是监听数据发送了某些变化,那就一定会有对应的事件类型,和状态类型。

(1) 事件类型(znode节点相关):

  1. EventType.None :客户端连接成功
  2. EventType.NodeCreated :节点创建
  3. EventType.NodeDataChanged :节点变更
  4. EventType.NodeChildrenChanged :子节点变量
  5. EventType.NodeDeleted :节点删除

(2) 状态类型(客户端状态):

  1. KeeperState.Disconnected :客户端连接断开
  2. KeeperState.SyncConnected :客户端连接成功
  3. KeeperState.AuthFailed :客户端认证失败
  4. KeeperState.Expired :客户端连接过期

3.2 watcher 的特性

Watcher 的特性:一次性、客户端串行执行、轻量。

(1) 一次性

对于 ZK 的 watcher,你只需要记住一点: zookeeper 有 watch事件,是一次性触发的,当 watch 监视的数据发生变化时,通知设置了该 watch 的 client,即 watcher,由于 zookeeper 的监控都是一次性的所以每次必须设置监控。

(2) 客户端串行执行

客户端 Watcher 回调的过程是一个串行同步的过程,这为我们保证了顺序,同时需要开发人员注意一点,千万不要因为一个 Watcher 的处理逻辑影响了整个客户端的 Watcher 回调。

(3) 轻量

Watched Event 是 Zookeeper 整个 Watcher 通知机制的最小通知单元,整个结构只包含三部分:通知状态、事件类型和节点路径。也就是说 Watcher 通知非常的简单,只会告诉客户端发生了事件而不会告知其具体内容,需要客户自己去进行获取,比如 NodeDataChanged 事件, Zookeeper 只会通知客户端指定节点的数据发生了变更,而不会直接提供具体的数据内容。

我们通过一个示例,详细学习下 Watcher 的概念和其目的。

3.3 Watcher 示例

  1. package com.github.binarylei.zookeeper.watcher;
  2. import java.io.Closeable;
  3. import java.io.IOException;
  4. import java.util.concurrent.CountDownLatch;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6. import org.apache.zookeeper.WatchedEvent;
  7. import org.apache.zookeeper.Watcher;
  8. import org.apache.zookeeper.Watcher.Event.KeeperState;
  9. import org.apache.zookeeper.Watcher.Event.EventType;
  10. import org.apache.zookeeper.ZooKeeper;
  11. /**
  12. * @author: leigang
  13. * @version: 2018-04-05
  14. */
  15. public class ConnectionWatcher implements Watcher, Closeable {
  16. private static final int SESSION_TIMEOUT = 5000;
  17. /** 定义原子变量,用于记录watcher数 */
  18. private AtomicInteger seq = new AtomicInteger();
  19. protected ZooKeeper zk;
  20. private CountDownLatch connectedSignal = new CountDownLatch(1);
  21. public void connect(String host) {
  22. this.close();
  23. try {
  24. this.zk = new ZooKeeper(host, SESSION_TIMEOUT, this);
  25. this.connectedSignal.await();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. @Override
  33. public void process(WatchedEvent event) {
  34. if (event == null) {
  35. return;
  36. }
  37. // 连接状态
  38. KeeperState keeperState = event.getState();
  39. // 事件类型
  40. EventType eventType = event.getType();
  41. // 受影响的path
  42. String path = event.getPath();
  43. String logPrefix = "【Watcher-" + seq.incrementAndGet() + "】";
  44. if(keeperState == KeeperState.SyncConnected) {
  45. // 成功连接上服务器
  46. if (eventType == EventType.None) {
  47. System.out.println(logPrefix + "成功连接上服务器");
  48. this.connectedSignal.countDown();
  49. }
  50. // 节点创建
  51. else if (eventType == EventType.NodeCreated) {
  52. System.out.println(logPrefix + "节点创建:" + path);
  53. }
  54. // 节点数据更新
  55. else if (eventType == EventType.NodeDataChanged) {
  56. System.out.println(logPrefix + "节点数据更新:"+ path);
  57. }
  58. // 节点删除
  59. else if (eventType == EventType.NodeDeleted) {
  60. System.out.println(logPrefix + "节点删除:" + path);
  61. }
  62. } else if (keeperState == KeeperState.Disconnected) {
  63. System.out.println(logPrefix + "连接断开");
  64. } else if (keeperState == KeeperState.AuthFailed) {
  65. System.out.println(logPrefix + "权限认证失败");
  66. } else if (keeperState == KeeperState.Expired) {
  67. System.out.println(logPrefix + "连接过期");
  68. }
  69. }
  70. // 关闭连接
  71. public void close() {
  72. if (this.zk != null) {
  73. try {
  74. this.zk.close();
  75. } catch (InterruptedException e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. }
  80. public ZooKeeper getZk() {
  81. return zk;
  82. }
  83. public void setZk(ZooKeeper zk) {
  84. this.zk = zk;
  85. }
  86. }
  87. public class ConnectionWatcherTest {
  88. @Test
  89. public void test() throws KeeperException, InterruptedException {
  90. ConnectionWatcher zkWatcher = new ConnectionWatcher();
  91. zkWatcher.connect("127.0.0.1:2181");
  92. ZooKeeper zk = zkWatcher.getZk();
  93. zk.create("/date", String.valueOf(System.currentTimeMillis()).getBytes(),
  94. ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
  95. //1. 注册watch事件
  96. zk.exists("/date", true);
  97. zk.setData("/date", String.valueOf(System.currentTimeMillis()).getBytes(), -1);
  98. //2. watch的触发是一次性的,要想再次触发必须重新注册
  99. zk.exists("/date", true);
  100. zk.setData("/date", String.valueOf(System.currentTimeMillis()).getBytes(), -1);
  101. zk.delete("/date", -1);
  102. zkWatcher.close();
  103. }
  104. }

测试结果如下:

  1. Watcher-1】成功连接上服务器
  2. Watcher-2】节点数据更新:/date
  3. # 当第二个 zk.exists("/date", true); 注释后,【Watcher-3】就不会触发了
  4. Watcher-3】节点数据更新:/date

四、Zookeeper 安全机制

ACL(Access Control List), Zookeeper 作为分布式协调框架,其内部存储的都是一些关乎分布式系统运行时状态的元数据,尤其是设计到分布式锁、 Master 选举和协调等应用场景。我们需要有效地保障 Zookeeper 中的数据安全,Zookeeper 提供一套完善的 ACL 权限控制机酮来保障数据的安全。

Zookeeper 提供了三种模式。权限模式、授权对象、权限。

(1) 权限模式: Scheme,开发人员最多使用的如下四种权限模式:

  1. IP :ip 模式通过 ip 地址粒度来进行控制权限,例如配置了 192.168.1.107 即表示权限控都针对这个 ip 地址的,同时也支持按网段分配,比如 192.168.1.*
  2. Diges :digest 是最常用的权限控制模式 ,也更符合我们对权限控制的认识,其类似于 "username: password" 形式的权限标识进行权限配置。zK 会对形成的权限标识先后进行俩次编码处理,分别是 SHA-1 加密算法、BASE64 编码。
  3. World :World 是一直最开放的权限控制模式。这种模式可以看做为特殊的 Digest。他仅仅是一个标识而已。
  4. Super :超级用户模式_在超级用户模式下可以对 ZK 任意进行操作。

(2) 权限对象:指的是权限赋予的用户或者一个指定的实体,例如 ip 地址或机器等。在不的模式下,授权对象是不同的。这种模式和权限对象一一对应。

(3) 权限:权限就是指那些通过权限检测后可以被允许执行的操作,在 ZK 中,对数据的操作权限分为以下五大类:

  1. CREATEDELETEREADWRITEADMIN

4.1 代码示例

  1. // 修改connect连接,在实例化ZooKeeper后,添加认证信息
  2. public class ZookeeperAuth implements Watcher, Closeable {
  3. public void connect(String host) {
  4. connect(host, null);
  5. }
  6. // 添加认证
  7. public void connect(String host, String password) {
  8. this.close();
  9. try {
  10. this.zk = new ZooKeeper(host, SESSION_TIMEOUT, this);
  11. if (password != null) {
  12. this.zk.addAuthInfo("digest", password.getBytes());
  13. }
  14. this.connectedSignal.await();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }

测试代码如下:

  1. public class ZookeeperAuthTest{
  2. @Test
  3. public void test1() throws KeeperException, InterruptedException { // (1)
  4. ZookeeperAuth zkAuth = new ZookeeperAuth();
  5. zkAuth.connect("127.0.0.1", "123456");
  6. ZooKeeper zk = zkAuth.getZk();
  7. zk.create("/testAuth", "test".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);
  8. zkAuth.close();
  9. }
  10. @Test
  11. public void test2() throws KeeperException, InterruptedException { // (2)
  12. ZookeeperAuth zkAuth = new ZookeeperAuth();
  13. zkAuth.connect("127.0.0.1:2181", "1234568");
  14. ZooKeeper zk = zkAuth.getZk();
  15. byte[] data = zk.getData("/testAuth", false, null);
  16. System.out.println(new String(data));
  17. zkAuth.close();
  18. }
  19. }

(1) Client-1 使用密码 123456 创建一个连接,并创建一个 znode 节点 /testAuth,注意创建节点时权限使用 ZooDefs.Ids.CREATOR_ALL_ACL

(2) Client-2 使用密码 1234568 创建一个连接,并打算修改节点 /testAuth ,结果出现权限不足的错误。

  1. org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /testAuth
  2. at org.apache.zookeeper.KeeperException.create(KeeperException.java:117)
  3. at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
  4. at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1611)
  5. at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1640)
  6. at com.github.binarylei.zookeeper.auth.ZookeeperAuthTest.test2(ZookeeperAuthTest.java:33)
  7. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  8. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  9. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  10. at java.lang.reflect.Method.invoke(Method.java:498)
  11. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  12. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  13. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  14. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  15. at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  16. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  17. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  18. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  19. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  20. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  21. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  22. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  23. at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  24. at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  25. at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
  26. at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
  27. at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
  28. at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Zookeeper 系列(三)Zookeeper API的更多相关文章

  1. Zookeeper系列三:Zookeeper客户端的使用(Zookeeper原生API如何进行调用、ZKClient、Curator)和Zookeeper会话

    一.Zookeeper原生API如何进行调用 准备工作: 首先在新建一个maven项目ZK-Demo,然后在pom.xml里面引入zk的依赖 <dependency> <groupI ...

  2. Zookeeper系列2 原生API 以及核心特性watcher

    原生API 增删改查询 public class ZkBaseTest { static final String CONNECT_ADDR = "192.168.0.120"; ...

  3. 【Zookeeper系列】ZooKeeper机制架构(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4133784.html 一.ZooKeeper权限管理机制 1.1 权限管理ACL(Access Control L ...

  4. 【Zookeeper系列】ZooKeeper管理分布式环境中的数据(转)

    原文地址:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  5. 【Zookeeper系列】Zookeeper命令操作(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4031881.html 一.Zookeeper的四字命令 Zookeeper支持某些特定的四字命令字母与其的交互.他 ...

  6. zookeeper系列之六—zookeeper之应用

    http://www.cnblogs.com/sharpxiajun/archive/2013/06/02/3113923.html Zookeeper是hadoop的一个子项目,虽然源自hadoop ...

  7. 【Zookeeper系列】ZooKeeper一致性原理(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4138580.html 一.ZooKeeper 的实现 1.1 ZooKeeper处理单点故障 我们知道可以通过Zo ...

  8. 【Zookeeper系列】ZooKeeper安装配置(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4018459.html 一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪 ...

  9. 【Zookeeper系列】Zookeeper简单介绍(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技 ...

  10. 【Zookeeper系列】zookeeper面试题(转)

    原文链接:https://segmentfault.com/a/1190000014479433 1.ZooKeeper是什么? ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是 ...

随机推荐

  1. python内置函数详细介绍

    知识内容: 1.python内置函数简介 2.python内置函数详细介绍 一.python内置函数简介 python中有很多内置函数,实现了一些基本功能,内置函数的官方介绍文档:    https: ...

  2. c# 导入导出excel表格式

    c#使用代码导入excel时,当遇到纯数字且大于15位时会出现编码混乱(表现为科学计数法),要想呈现与excel表中纯数字格式和在数据库中呈现纯数字,操作如下: 完成即可. 导出取决于导入的内容排版.

  3. centos7防火墙使用方法

    参考网站:https://blog.csdn.net/achang21/article/details/52538049 添加开放指定端口: [root@yao bin]# firewall-cmd ...

  4. docker容器中搭建kafka集群环境

    Kafka集群管理.状态保存是通过zookeeper实现,所以先要搭建zookeeper集群 zookeeper集群搭建 一.软件环境: zookeeper集群需要超过半数的的node存活才能对外服务 ...

  5. 删除数据恢复数据语句 Oracle

    SELECT * FROM TBL_DZYJ_GEORELICSINFO AS OF TIMESTAMP TO_TIMESTAMP('2017-5-8 9:00:00','YYYY-MM-DD HH: ...

  6. apiCloud事件发送与监听

    apiCloud事件发送与监听 1.sendEvent 将任意一个自定义事件广播出去,该事件可在任意页面通过 addEventListener 监听收到. sendEvent({params}) 2. ...

  7. javascript中 try catch用法

    javascript中 try catch用法 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2015-08-16我要评论 JS try catch语句一般在什么情况下使用?是必须使 ...

  8. spring cloud: eureka搭建

    1. 添加pom 依赖: <parent> <groupId>org.springframework.boot</groupId> <artifactId&g ...

  9. 快速可靠网络传输协议 KCP(转)

    KCP 是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低30%-40%,且最大延迟降低三倍的传输效果.纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定 ...

  10. HQL中的Like查询需要注意的地方

    public List getOrgan(String organCode, String organName) {    String hsql;    List list; if (organCo ...