# etcd-running **Repository Path**: coderwing/etcd-running ## Basic Information - **Project Name**: etcd-running - **Description**: ETCD - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-21 - **Last Updated**: 2025-10-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring Boot + etcd 演练项目 这是一个用于学习和实践 etcd 的 Spring Boot 项目,包含了 etcd 的各种常用功能示例。 ## 项目简介 本项目演示了如何在 Spring Boot 应用中集成和使用 etcd,包括: - ✅ **KV 存储**:基本的键值对存储和查询 - ✅ **Lease(租约)**:带过期时间的键值对存储 - ✅ **Watch(监听)**:监听键值变化 - ✅ **分布式锁**:基于 etcd 的分布式锁实现 - ✅ **服务发现与注册**:微服务注册和发现 - ✅ **配置管理**:动态配置管理和热更新 ## 技术栈 - Spring Boot 3.2.0 - Java 17 - jetcd 0.7.7(etcd Java 客户端) - Maven - Docker & Docker Compose ## 项目结构 ``` etcd-stu/ ├── src/main/java/com/example/etcd/ │ ├── EtcdStudyApplication.java # 主应用类 │ ├── config/ │ │ ├── EtcdConfig.java # etcd 客户端配置 │ │ └── EtcdProperties.java # etcd 配置属性 │ ├── controller/ │ │ ├── HomeController.java # 首页控制器 │ │ ├── EtcdKVController.java # KV 操作控制器 │ │ ├── EtcdLeaseController.java # Lease 操作控制器 │ │ ├── EtcdLockController.java # 分布式锁控制器 │ │ ├── EtcdServiceDiscoveryController.java # 服务发现控制器 │ │ └── EtcdConfigController.java # 配置管理控制器 │ ├── service/ │ │ ├── EtcdKVService.java # KV 操作服务 │ │ ├── EtcdLeaseService.java # Lease 操作服务 │ │ ├── EtcdWatchService.java # Watch 服务 │ │ ├── EtcdLockService.java # 分布式锁服务 │ │ ├── EtcdServiceDiscoveryService.java # 服务发现服务 │ │ └── EtcdConfigService.java # 配置管理服务 │ └── model/ │ └── ServiceInstance.java # 服务实例模型 └── src/main/resources/ ├── application.yml # 应用配置 └── application-docker.yml # Docker 环境配置 ``` ## 快速开始 ### 1. 启动 etcd 使用 Docker Compose 启动 etcd: ```bash docker-compose up -d ``` 这将启动一个单节点的 etcd 服务,监听在 `localhost:2379`。 ### 2. 编译项目 ```bash mvn clean package ``` ### 3. 运行应用 ```bash mvn spring-boot:run ``` 或者运行打包后的 jar: ```bash java -jar target/etcd-stu-1.0.0.jar ``` ### 4. 访问应用 打开浏览器访问:http://localhost:8080 你将看到所有可用的 API 端点列表。 ## API 文档 ### 1. KV 操作 #### 存储键值对 ```bash curl -X POST "http://localhost:8080/api/kv/put?key=test&value=hello" ``` #### 获取值 ```bash curl "http://localhost:8080/api/kv/get?key=test" ``` #### 获取指定前缀的所有键值对 ```bash curl "http://localhost:8080/api/kv/prefix?prefix=/app/" ``` #### 删除键 ```bash curl -X DELETE "http://localhost:8080/api/kv/delete?key=test" ``` #### 删除指定前缀的所有键 ```bash curl -X DELETE "http://localhost:8080/api/kv/prefix?prefix=/app/" ``` ### 2. Lease(租约)操作 #### 创建租约 ```bash curl -X POST "http://localhost:8080/api/lease/grant?ttl=10" ``` #### 存储带过期时间的键值对 ```bash curl -X POST "http://localhost:8080/api/lease/put-with-lease?key=temp&value=data&ttl=10" ``` #### 查询租约 TTL ```bash curl "http://localhost:8080/api/lease/ttl?leaseId=123456" ``` #### 撤销租约 ```bash curl -X POST "http://localhost:8080/api/lease/revoke?leaseId=123456" ``` #### 开始 Keep-Alive ```bash curl -X POST "http://localhost:8080/api/lease/keep-alive?leaseId=123456" ``` ### 3. 分布式锁 #### 获取锁 ```bash curl -X POST "http://localhost:8080/api/lock/acquire?lockName=mylock&ttl=10" ``` #### 释放锁 ```bash curl -X POST "http://localhost:8080/api/lock/release?lockName=mylock" ``` #### 尝试获取锁(带超时) ```bash curl -X POST "http://localhost:8080/api/lock/try-lock?lockName=mylock&ttl=10&timeout=5" ``` #### 检查锁状态 ```bash curl "http://localhost:8080/api/lock/status?lockName=mylock" ``` #### 执行带锁的任务 ```bash curl -X POST "http://localhost:8080/api/lock/demo-task?lockName=mylock&ttl=10" ``` ### 4. 服务发现与注册 #### 注册服务 ```bash curl -X POST "http://localhost:8080/api/service/register?serviceName=user-service&host=127.0.0.1&port=8081&ttl=30" ``` #### 注销服务 ```bash curl -X POST "http://localhost:8080/api/service/deregister?serviceName=user-service&instanceId=xxx" ``` #### 发现服务 ```bash curl "http://localhost:8080/api/service/discover?serviceName=user-service" ``` #### 列出所有服务 ```bash curl "http://localhost:8080/api/service/list" ``` #### 监听服务变化 ```bash curl -X POST "http://localhost:8080/api/service/watch?serviceName=user-service" ``` ### 5. 配置管理 #### 设置配置 ```bash curl -X POST "http://localhost:8080/api/config/set?key=database.url&value=jdbc:mysql://localhost:3306/db" ``` #### 获取配置 ```bash curl "http://localhost:8080/api/config/get?key=database.url" ``` #### 获取所有配置 ```bash curl "http://localhost:8080/api/config/all" ``` #### 删除配置 ```bash curl -X DELETE "http://localhost:8080/api/config/delete?key=database.url" ``` #### 监听配置变化 ```bash curl -X POST "http://localhost:8080/api/config/watch?key=database.url" ``` #### 监听配置前缀变化 ```bash curl -X POST "http://localhost:8080/api/config/watch-prefix?prefix=database" ``` #### 停止监听配置 ```bash curl -X POST "http://localhost:8080/api/config/unwatch?key=database.url" ``` #### 获取配置缓存 ```bash curl "http://localhost:8080/api/config/cache" ``` ## 使用示例 ### 分布式锁示例 ```java // 获取锁并执行任务 lockService.executeWithLock("mylock", 10, () -> { // 执行需要加锁的业务逻辑 System.out.println("执行业务逻辑..."); return "success"; }).thenAccept(result -> { System.out.println("任务执行结果: " + result); }); ``` ### 服务注册示例 ```java // 注册服务 serviceDiscoveryService.registerService("user-service", "127.0.0.1", 8081, 30) .thenAccept(instanceId -> { System.out.println("服务注册成功,实例 ID: " + instanceId); }); // 发现服务 serviceDiscoveryService.discoverService("user-service") .thenAccept(instances -> { instances.forEach(instance -> { System.out.println("发现服务实例: " + instance.getAddress()); }); }); ``` ### 配置管理示例 ```java // 设置配置 configService.setConfig("database.url", "jdbc:mysql://localhost:3306/db"); // 监听配置变化 configService.watchConfig("database.url", newValue -> { System.out.println("配置已更新: " + newValue); // 在这里可以重新加载数据库连接等 }); // 获取配置 configService.getConfig("database.url").thenAccept(value -> { System.out.println("数据库 URL: " + value); }); ``` ## etcd 常用命令 ### 使用 etcdctl 客户端 ```bash # 进入 etcd 容器 docker exec -it etcd /bin/sh # 查看所有键 etcdctl get "" --prefix --keys-only # 查看指定前缀的键值 etcdctl get /services/ --prefix # 设置键值 etcdctl put /test/key1 "value1" # 获取键值 etcdctl get /test/key1 # 删除键 etcdctl del /test/key1 # 监听键变化 etcdctl watch /test/key1 # 查看集群成员 etcdctl member list # 查看集群健康状态 etcdctl endpoint health ``` ## 配置说明 ### application.yml ```yaml etcd: # etcd 服务器端点,多个用逗号分隔 endpoints: http://localhost:2379 # 连接超时时间(毫秒) connect-timeout: 5000 # 请求超时时间(毫秒) request-timeout: 3000 # 命名空间前缀 namespace: /etcd-study/ ``` ## etcd 核心概念 ### 1. Key-Value 存储 etcd 是一个分布式键值存储系统,提供可靠的数据存储和访问。 ### 2. Lease(租约) 租约是一个有生存时间(TTL)的对象,可以关联到键上,当租约过期时,相关的键会自动删除。 ### 3. Watch(监听) Watch 允许客户端监听指定键或键前缀的变化,当键发生变化时,会收到通知。 ### 4. MVCC(多版本并发控制) etcd 使用 MVCC 模型,每次修改都会创建新版本,支持历史版本查询。 ### 5. Transaction(事务) etcd 支持事务操作,可以在一个原子操作中执行多个操作。 ## 常见使用场景 1. **配置中心**:存储和管理应用配置,支持配置热更新 2. **服务发现**:微服务注册和发现 3. **分布式锁**:实现分布式系统的互斥访问 4. **选举**:实现主从选举和 Leader 选举 5. **分布式协调**:协调分布式系统中的各个节点 6. **消息队列**:实现简单的消息队列功能 ## 注意事项 1. etcd 适合存储少量的元数据,不适合存储大量数据 2. 建议键的大小不超过 1.5 MB,值的大小不超过 1.5 MB 3. 使用 Lease 时,记得定期 Keep-Alive,否则键会自动过期 4. Watch 操作会持续监听,使用完后记得关闭 5. 分布式锁使用完毕后一定要释放,避免死锁 ## 故障排查 ### etcd 连接失败 1. 检查 etcd 服务是否启动:`docker ps | grep etcd` 2. 检查 etcd 端口是否可访问:`telnet localhost 2379` 3. 查看 etcd 日志:`docker logs etcd` ### 应用启动失败 1. 检查配置文件中的 etcd 端点配置 2. 确保 Java 版本为 17 或更高 3. 查看应用日志,检查详细错误信息 ## 参考资料 - [etcd 官方文档](https://etcd.io/docs/) - [jetcd GitHub](https://github.com/etcd-io/jetcd) - [Spring Boot 官方文档](https://spring.io/projects/spring-boot) ## License MIT License ## 作者 coderwing --- **Happy Learning! 🎉**