在Java中调用ETCD使用JETCD--API3 基础部分

前言

ETCD是用于共享配置和服务发现的分布式,一致性的KV存储系统。有很多使用场景,包括:配置管理、服务注册于发现、选主、应用调度、分布式队列和分布式锁。因此本文主要介绍JAVA中使用ETCD实现分布式管理。使用工具JETCD


一、ETCD简单介绍

etcd 是云原生架构中重要的基础组件,由 CNCF 孵化托管。etcd 在微服务和 Kubernates 集群中不仅可以作为服务注册于发现,还可以作为 key-value 存储的中间件。
ETCD使用Raft协议来维护集群内各个节点状态的一致性。简单说,ETCD集群是一个分布式系统,由多个节点相互通信构成整体对外服务,每个节点都存储了完整的数据,并且通过Raft协议保证每个节点维护的数据是一致的。
ETCD比较多的应用场景是用于服务发现,服务发现 (Service Discovery) 要解决的是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务如何才能找到对方并建立连接。etcd 有很多使用场景,包括:配置管理、服务注册发现、选主、应用调度、分布式队列和分布式锁的应用
具体了解:https://etcd.io/docs/v3.4/quickstart

二、JETCD简介

1.引入库

jetcd是etcd v3版本的官方java客户端工具,java项目通过该库可以对etcd执行各种操作,当前最新发布版本是0.5.7
jetcd官方github:https://github.com/etcd-io/jetcd

1.MAVEN 中引入依赖

<dependency>
  <groupId>io.etcd</groupId>
  <artifactId>jetcd-core</artifactId>
  <version>${jetcd-version}</version>
</dependency>
c
 
运行

2.构建JETCD链接ETCD

对应获取各个Clients:

String endpoints="http://127.0.0.1:2379,http://127.0.0.2:2379" ;
		//需要参数自己可以添加认证
		Client etcdClient=Client.builder().endpoints(endpoints.split(",")).build();
		//获取键值对client
		KV kv=etcdClient.getKVClient();
		//获取租约client
		Lease lease=etcdClient.getLeaseClient();
		//监听
		Watch watch =etcdClient.getWatchClient();
		//选举
		Election election =etcdClient.getElectionClient();
		//锁
		Lock lock=etcdClient.getLockClient();
c
 
运行

3.JETCD 的使用

3.1 JETCD — KV
	ByteSequence key=ByteSequence.from("test-key",StandardCharsets.UTF_8);
	ByteSequence value=ByteSequence.from("test-value",StandardCharsets.UTF_8);
	//推送
	CompletableFuture<PutResponse> putFuture = kv.put(key, value);
	//拉取
	CompletableFuture<GetResponse> getFuture = kv.get(key);
	try {
		String tmpValue=getFuture.get().getKvs().get(0).getValue().toString(StandardCharsets.UTF_8);
	} catch (InterruptedException | ExecutionException e) {
		e.printStackTrace();
	}
	//删除
	kv.delete(key);
c
 
运行
3.2 JETCD — Watch
watch.watch(key, listener ->{
			listener.getEvents().forEach(event->{
				switch (event.getEventType()) {
				case DELETE:
					//当KEY被删除触发
					break;
				case PUT:
					//当key推送触发
					break;
				default:
					break;
				}
			});;
		});
c
 
运行
3.3 JETCD — Lease
		
		//创建一个租约,存在60秒,创建开始倒计时
		long leaseId=0L;
		try {
			leaseId = lease.grant(60).get().getID();
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//参数构建
		LeaseOption leaseOption=LeaseOption.newBuilder().withAttachedKeys().build();
		CompletableFuture<LeaseTimeToLiveResponse> leaseFuture= lease.timeToLive(leaseId, leaseOption);
		try {
			//获取绑定租约的对象
		List<ByteSequence> keys = leaseFuture.get().getKeys();
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
		//租约重新开始计数
		lease.keepAliveOnce(leaseId);
		//长时间生效每次租约到期触发
		StreamObserver<LeaseKeepAliveResponse> observer =new StreamObserver<LeaseKeepAliveResponse>() {
			@Override
			public void onNext(LeaseKeepAliveResponse value) {
				System.out.println("租约时间到达");
			}
			@Override
			public void onError(Throwable t) {
			}
			@Override
			public void onCompleted() {
			}
		};
		lease.keepAlive(leaseId, observer);
		//KV使用租约到期删除
		PutOption option=PutOption.newBuilder().withLeaseId(leaseId).build();
		kv.put(key, value, option);
		//撤销一个租约
		lease.revoke(leaseId);
c
 
运行
3.4 JETCD — Election
		ByteSequence electionName=ByteSequence.from("electionName",StandardCharsets.UTF_8);
		ByteSequence proposal_1=ByteSequence.from("proposal_1",StandardCharsets.UTF_8);
		ByteSequence proposal_2=ByteSequence.from("proposal_2",StandardCharsets.UTF_8);
		Listener listener=new Listener() {
			@Override
			public void onNext(LeaderResponse response) {
				System.out.println(response.getKv().getValue().toString(StandardCharsets.UTF_8));
			}
			@Override
			public void onError(Throwable throwable) {
			}			
			@Override
			public void onCompleted() {
			}
		};
		//监听选举范围类当选者事件
		election.observe(electionName, listener);
		//参与,租约到期,竞选者推出
		CompletableFuture<CampaignResponse> campaign = election.campaign(electionName, leaseId, proposal_1);
		try {
			//阻塞获取领导权限
			LeaderKey leaderKey = campaign.get().getLeader();
			//获取当选者
			CompletableFuture<LeaderResponse> leaderFuture = election.leader(electionName);
			String lead= leaderFuture.get().getKv().getValue().toString(StandardCharsets.UTF_8);
			System.out.println(lead);
			//领导位置宣布给另一个;
			election.proclaim(leaderKey, proposal_2);
			//辞退当选位置
			election.resign(leaderKey);
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
c
 
运行
3.5 JETCD — lock

锁的使用要注意阻塞获取下锁,释放锁这个好像有点问题,还要等租约。使用请注意

    ByteSequence lock_key=ByteSequence.from("lock_key",StandardCharsets.UTF_8);
   	//加锁,租约到期释放
   	CompletableFuture<LockResponse> lockFuture = lock.lock(lock_key, leaseId);
   	try {
   		//阻塞获取锁
   		String lockStr=lockFuture.get().getKey().toString(StandardCharsets.UTF_8);
   	} catch (InterruptedException | ExecutionException e) {
   		e.printStackTrace();
   	}
   	//释放锁
   	lock.unlock(lock_key);
c
 
运行

总结

以上是在JAVA 中使用JETCD的基础操作方法。
后续会使用这些API去实现相应的场景的代码说明。

Springboot集成etcd 增删改查demo_springboot 集成etcd数据库-CSDN博客

一.客户端设置

 
  1. package com.lemon.thread.etcd.config;
  2.  
  3. import io.etcd.jetcd.*;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.context.annotation.PropertySource;
  6. import org.springframework.stereotype.Component;
  7.  
  8. import javax.annotation.PostConstruct;
  9. import javax.annotation.PreDestroy;
  10.  
  11. /**
  12. * @author william
  13. * @date 2023/3/8 0008
  14. * @apinote
  15. */
  16. @Component
  17. @PropertySource(value= {"classpath:application.properties"},ignoreResourceNotFound=true)
  18. public class EtcdClient {
  19.  
  20. @Value("${endpoints:http://127.0.0.1:2379}")
  21. private String endpoints;
  22.  
  23. private Client client;
  24.  
  25. private KV kv;
  26.  
  27. private Lock lock;
  28.  
  29. private Lease lease;
  30.  
  31. private Watch watch;
  32.  
  33. private Election election;
  34.  
  35. private final String DOUHAO = ",";
  36.  
  37. @PostConstruct
  38. private void init() {
  39. client= Client.builder().endpoints("http://127.0.0.1:2379").build();
  40. kv=client.getKVClient();
  41. lock=client.getLockClient();
  42. lease=client.getLeaseClient();
  43. watch=client.getWatchClient();
  44. election=client.getElectionClient();
  45.  
  46. }
  47.  
  48. @PreDestroy
  49. private void destroy() {
  50. election.close();
  51. kv.close();
  52. lease.close();
  53. watch.close();
  54. lock.close();
  55. client.close();
  56. }
  57.  
  58. public KV getKv() {
  59. return kv;
  60. }
  61.  
  62. public void setKv(KV kv) {
  63. this.kv = kv;
  64. }
  65.  
  66. public Lock getLock() {
  67. return lock;
  68. }
  69.  
  70. public void setLock(Lock lock) {
  71. this.lock = lock;
  72. }
  73.  
  74. public Lease getLease() {
  75. return lease;
  76. }
  77.  
  78. public void setLease(Lease lease) {
  79. this.lease = lease;
  80. }
  81.  
  82. public Watch getWatch() {
  83. return watch;
  84. }
  85.  
  86. public void setWatch(Watch watch) {
  87. this.watch = watch;
  88. }
  89.  
  90. public Election getElection() {
  91. return election;
  92. }
  93.  
  94. public void setElection(Election election) {
  95. this.election = election;
  96. }
  97. }
  98.  
 
java

二.服务端增删改查:

 
  1. package com.lemon.thread.etcd.config;
  2.  
  3.  
  4. import io.etcd.jetcd.ByteSequence;
  5. import io.etcd.jetcd.KeyValue;
  6. import io.etcd.jetcd.kv.GetResponse;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Service;
  9.  
  10. import java.nio.charset.StandardCharsets;
  11. import java.util.List;
  12. import java.util.concurrent.ExecutionException;
  13.  
  14. @Service
  15. public class EtcdService {
  16.  
  17. @Autowired
  18. private EtcdClient etcdClient;
  19.  
  20. public String get(String key) throws InterruptedException, ExecutionException {
  21. ByteSequence byteKey = ByteSequence.from(key, StandardCharsets.UTF_8);
  22. GetResponse response = etcdClient.getKv().get(byteKey).get();
  23. List<KeyValue> values = response.getKvs();
  24. if (!values.isEmpty()) {
  25. return values.get(0).getValue().toString(StandardCharsets.UTF_8);
  26. }
  27. return null;
  28. }
  29.  
  30. public void put(String key, String value) throws InterruptedException, ExecutionException {
  31. ByteSequence byteKey = ByteSequence.from(key, StandardCharsets.UTF_8);
  32. ByteSequence byteValue = ByteSequence.from(value, StandardCharsets.UTF_8);
  33. etcdClient.getKv().put(byteKey, byteValue).get();
  34. }
  35.  
  36. public void delete(String key) throws InterruptedException, ExecutionException {
  37. ByteSequence byteKey = ByteSequence.from(key, StandardCharsets.UTF_8);
  38. etcdClient.getKv().delete(byteKey).get();
  39. }
  40. }
 
java

总结:可以实现简单的增删改查

posted @ 2026-02-06 22:10  CharyGao  阅读(11)  评论(0)    收藏  举报