写点什么

etcd 框架实践【Java 版】

作者:FunTester
  • 2024-07-15
    河北
  • 本文字数:2334 字

    阅读完需:约 8 分钟

前文分享 etcd 框架 Go 语言的实践,今天分享一下 Java 客户端的不分。再分享之前,先简单聊一下我查阅的资料的现状,以方便各位再开始 Java 客户端学习之前,有个心理预期。


etcd 本身是 Go 语言编写的,所以在语言支持上,Go 语言是支持的最好的。其他的就差强人意,这种场景有点像 Web3j ,有人再维护,但是从使用便捷程度上,总是不能一帆风顺直接上手。


而且还有一个原因,etcd 的 Java 实现库太多了,各种库之间的细微差异也能让我搜索资料的时候难以准确找到最佳实践及其原理介绍。


大多数实现库都用了大量的异步操作,语法跟 Web3j 类似,我也不确定是哪种设计模式,如果你有 Web3j 使用经验,相信会更加容易上手。

Java 客户端比较

详细比较

  1. jetcd

  2. 优点:

  3. 官方支持,与 etcd 版本同步更新

  4. 全面支持 etcd v3 API

  5. 性能优秀,适合大规模生产环境

  6. 缺点:

  7. 依赖较重(gRPC)

  8. 学习曲线可能稍陡

  9. etcd4j

  10. 优点:

  11. 轻量级,容易集成

  12. API 简单直观

  13. 缺点:

  14. 主要支持 etcd v2 API,对 v3 支持有限

  15. 社区更新较慢

  16. 不适合需要 v3 API 特性的新项目

  17. spring-cloud-kubernetes

  18. 优点:

  19. 与 Spring Cloud 和 Kubernetes 生态系统深度集成

  20. 提供服务发现和配置管理功能

  21. 缺点:

  22. 依赖 Spring 生态系统,不适合非 Spring 项目

  23. 可能引入不必要的复杂性(如果只需要简单的 etcd 客户端)

  24. vertx-etcd-client

  25. 优点:

  26. 与 Vert.x 生态系统集成

  27. 非阻塞 API,适合高并发场景

  28. 缺点:

  29. 与 Vert.x 绑定,不适合非 Vert.x 项目

  30. 社区相对较小

Java 客户端实践

下面我选择 jetcd 作为实现库,首先我们添加依赖项目:


<dependency>      <groupId>io.etcd</groupId>      <artifactId>jetcd-core</artifactId>      <version>0.7.0</version>  </dependency>  <dependency>      <groupId>com.google.guava</groupId>      <artifactId>guava</artifactId>      <version>31.1-jre</version>  </dependency>
复制代码


如果你再运行当中遇到了 Exception in thread "main" java.lang.NoClassDefFoundError: 此类错误,请检查服务端版本,gRPC 版本,客户端版本,以及依赖项缺失。这也是劝退的原因之一。


接下来我们来看 Case,除了读写以外,我增加了监听的用例。总体来讲,语法比较熟悉 (我用过 Web3j ),下面是两个简单的例子,用来演示 jetcd 的基本使用。


package com.funtest.temp    import com.funtester.frame.SourceCode  import io.etcd.jetcd.ByteSequence  import io.etcd.jetcd.Client  import io.etcd.jetcd.Watch  import io.etcd.jetcd.kv.GetResponse  import io.etcd.jetcd.watch.WatchEvent    import java.nio.charset.Charset  import java.nio.charset.StandardCharsets  import java.util.concurrent.CompletableFuture    class TtcdTest extends SourceCode {        static Charset defaultCharset = StandardCharsets.UTF_8        // 创建客户端, 连接etcd      static def client = Client.builder().endpoints("http://localhost:2379").build()        // 创建KV客户端, 用于读写数据      static def kVClient = client.getKVClient()        static def watchClient = client.getWatchClient()        /**       * 监听etcd中的key变化, 有变化时打印出来       */      static watch() {          def key = toByteSequence("key")// 监听的key          Watch.Listener listener = Watch.listener(watchResponse -> {// 监听器              for (WatchEvent event : watchResponse.getEvents()) {// 事件                  println("watch change ------------------")// 打印                  println("修改的类型Event type: " + event.getEventType());// 事件类型, PUT, DELETE                  println("修改的Key: " + event.getKeyValue().getKey().toString(StandardCharsets.UTF_8));// 修改的Key, ByteSequence转字符串                  println("修改后Value: " + event.getKeyValue().getValue().toString(StandardCharsets.UTF_8));// 修改后的Value, ByteSequence转字符串              }          });        watchClient.watch(key, listener)// 监听key, 有变化时触发监听器      }        /**       * 写入数据, 读取数据       * @return       */      static writeRead() {          kVClient.put(toByteSequence("key"), toByteSequence("FunTester")).get()// 写入key-value          CompletableFuture<GetResponse> getFuture = kVClient.get(toByteSequence("key"))// 读取key-value          GetResponse response = getFuture.get()// 获取结果, 阻塞等待, 直到获取到结果          println("Value: " + response.getKvs().get(0).getValue().toString())// 打印结果      }        /**       * 字符串转ByteSequence       * @param str       * @param Charset       * @return       */      static ByteSequence toByteSequence(String str, Charset = defaultCharset) {          return ByteSequence.from(str, defaultCharset);      }  }
复制代码


下面我们来依次执行两个方法:


    public static void main(String[] args) {        watch()        writeRead()    }
复制代码


下面是控制台打印:


watch change ------------------修改的类型Event type: PUT修改的Key: key修改后Value: FunTesterValue: FunTester
复制代码


可以看到是满足预期的。但是问题来了,JVM 进程就是不退出,比较尴尬,即使我们加上关闭客户端的方法 client.close() 也不行,打开线程转储之后发现好几个 RUNNABLE 的线程,还有一个 forkjoin 线程池,现象跟 Web3j 很像,但是这次跟 Netty 相关,我也懒得深究原因了。

发布于: 刚刚阅读数: 6
用户头像

FunTester

关注

公众号:FunTester,800篇原创,欢迎关注 2020-10-20 加入

Fun·BUG挖掘机·性能征服者·头顶锅盖·Tester

评论

发布
暂无评论
etcd框架实践【Java版】_FunTester_InfoQ写作社区