PHP code example of chenbool / etcd-v3
1. Go to this page and download the library: Download chenbool/etcd-v3 library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
chenbool / etcd-v3 example snippets
chenbool\Etcd\Client;
// 创建客户端实例
$client = new Client('127.0.0.1:2379');
// 设置键值
$client->put('name', 'etcd-client');
echo "Put name: etcd-client\n";
// 获取值
$value = $client->get('name');
echo "Get name: {$value}\n";
// 删除键
$client->del('name');
echo "Delete name\n";
// 基本设置
$client->put('redis', '127.0.0.1:6379');
echo "Put redis: 127.0.0.1:6379\n";
// 设置值并返回旧值(prev_kv)
$result = $client->put('redis', '127.0.0.1:6579', ['prev_kv' => true]);
echo "Put redis with prev_kv\n";
// 如果有旧值,可以在 $result 中获取
// 设置值并绑定租约(键会在租约过期后自动删除)
$lease = $client->grant(3600); // 创建 3600 秒的租约
$leaseId = $lease['ID'] ?? 0;
if ($leaseId > 0) {
$client->put('redis', '127.0.0.1:6579', ['lease' => $leaseId]);
echo "Put redis with lease: {$leaseId}\n";
}
// 获取单个键的值
$value = $client->get('redis');
echo "Get redis: {$value}\n";
// 获取所有键
$keys = $client->getAllKeys();
echo "All keys: " . implode(', ', $keys) . "\n";
// 获取原始响应(包含元数据如 version、create_revision、mod_revision 等)
$raw = $client->getRaw('redis');
echo "Raw data: " . json_encode($raw) . "\n";
// 获取时指定版本号
$value = $client->get('redis', ['revision' => 100]);
// 仅获取计数
$count = $client->get('prefix/', ['count_only' => true, 'range_end' => "prefix/\xFF"]);
// 删除单个键
$client->del('redis');
echo "Delete redis\n";
// 删除并返回旧值
$result = $client->del('redis', ['prev_kv' => true]);
// 范围删除(删除所有以 "config/" 开头的键)
$client->del('config/', ['range_end' => "config/\xFF"]);
// 持续监听键的变化(阻塞式)
$client->watch('redis', function($result) {
if (isset($result['events'])) {
foreach ($result['events'] as $event) {
echo "事件类型: " . $event['type'] . "\n"; // PUT 或 DELETE
echo "键: " . base64_decode($event['kv']['key']) . "\n";
if (isset($event['kv']['value'])) {
echo "值: " . base64_decode($event['kv']['value']) . "\n";
}
}
}
});
// 单次监听
$watchResult = $client->watchOnce('redis');
if ($watchResult) {
echo "Watch ID: " . $watchResult['watch_id'] . "\n";
}
// 从指定版本开始监听
$client->watch('redis', $callback, ['revision' => 100]);
// 监听时包含旧值
$client->watch('redis', $callback, ['prev_kv' => true]);
// 压缩到指定版本(删除该版本之前的历史数据)
try {
$client->compaction(100);
echo "Compaction 100\n";
} catch (\Exception $e) {
echo "Compaction failed: " . $e->getMessage() . "\n";
}
// 物理压缩(彻底删除数据,释放空间)
$client->compaction(100, true);
// 授予租约,TTL 为 3600 秒(1小时)
$lease = $client->grant(3600);
echo "Grant lease: " . json_encode($lease) . "\n";
// 输出示例: {"ID": 7587894738292371267, "TTL": 3600}
// 指定 ID 授予租约(注意:如果 ID 已存在会报错)
$leaseId = 7587894738292371267;
try {
$client->revoke($leaseId); // 先撤销已存在的
} catch (\Exception $e) {
// 忽略不存在的错误
}
$lease = $client->grant(3600, $leaseId);
echo "Grant lease with ID: " . json_encode($lease) . "\n";
// 使用租约设置键值(键将在租约过期后自动删除)
$client->put('service/node1', '192.168.1.100:8080', ['lease' => $leaseId]);
// 撤销租约(立即删除关联的所有键)
$client->revoke($leaseId);
echo "Revoke lease\n";
// 保持租约活跃(续约)
$client->keepAlive($leaseId);
echo "Keep alive lease\n";
// 查询租约信息
$ttl = $client->timeToLive($leaseId);
echo "Time to live: " . json_encode($ttl) . "\n";
// 输出: {"ID": 7587894738292371267, "TTL": 3600}
// 查询租约信息并获取关联的键
$ttlWithKeys = $client->timeToLive($leaseId, true);
echo "TTL with keys: " . json_encode($ttlWithKeys) . "\n";
// 输出: {"ID": ..., "TTL": ..., "keys": ["service/node1"]}
// 列出所有租约
$leases = $client->leases();
echo "All leases: " . json_encode($leases) . "\n";
// 输出: [7587894738292371267, 7587894738292371268]
// 注意:启用认证前必须先创建 root 用户!
// 步骤 1: 创建 root 用户
$client->addUser('root', 'root123');
echo "Add root user\n";
// 步骤 2: 创建 root 角色(通常已存在)
$client->addRole('root');
echo "Add root role\n";
// 步骤 3: 授予 root 用户 root 角色
$client->grantUserRole('root', 'root');
echo "Grant root role to root user\n";
// 步骤 4: 启用认证
$client->authEnable();
echo "Auth enabled\n";
// 步骤 5: 使用 root 登录获取令牌
$token = $client->authenticate('root', 'root123');
echo "Authenticate: {$token}\n";
// 步骤 6: 设置令牌(后续请求将自动携带)
$client->setToken($token);
echo "Set token\n";
// 现在可以进行需要认证的操作了...
// 禁用认证(需要 root 权限)
$client->authDisable();
echo "Auth disabled\n";
// 清除令牌
$client->clearToken();
echo "Clear token\n";
// 添加用户
$client->addUser('alice', 'password123');
echo "Add user: alice\n";
// 获取用户信息
$user = $client->getUser('alice');
echo "Get user: " . json_encode($user) . "\n";
// 输出包含: name, roles 等信息
// 修改用户密码
$client->changeUserPassword('alice', 'new-password');
echo "Change user password\n";
// 删除用户
$client->deleteUser('alice');
echo "Delete user\n";
// 列出所有用户
$users = $client->userList();
echo "User list: " . json_encode($users) . "\n";
// 输出: {"users": [{"name": "root"}, {"name": "alice"}]}
// 创建角色
$client->addRole('readonly');
echo "Add role: readonly\n";
// 获取角色信息(包含权限列表)
$role = $client->getRole('readonly');
echo "Get role: " . json_encode($role) . "\n";
// 删除角色
$client->deleteRole('readonly');
echo "Delete role\n";
// 列出所有角色
$roles = $client->roleList();
echo "Role list: " . json_encode($roles) . "\n";
// 输出: {"roles": [{"name": "root"}, {"name": "readonly"}]}
use chenbool\Etcd\Client;
// 授予角色权限
// PERMISSION_READ = 0, PERMISSION_WRITE = 1, PERMISSION_READWRITE = 2
// 给 readonly 角色授予对 config/ 前缀的读权限
$client->roleGrantPermission(
'readonly',
Client::PERMISSION_READ,
'config/',
"config/\xFF" // 范围结束,表示 config/ 开头的所有键
);
echo "Grant read permission on config/* to readonly\n";
// 给 admin 角色授予对所有键的读写权限
$client->roleGrantPermission(
'admin',
Client::PERMISSION_READWRITE,
"\x00",
"\xFF"
);
echo "Grant readwrite permission on all keys to admin\n";
// 撤销角色权限
$client->roleRevokePermission('readonly', 'config/', "config/\xFF");
echo "Revoke permission\n";
// 授予角色给用户
$client->grantUserRole('alice', 'readonly');
echo "Grant readonly role to alice\n";
// 撤销用户的角色
$client->revokeUserRole('alice', 'readonly');
echo "Revoke readonly role from alice\n";
// 用户登录获取 Token
$token = $client->authenticate('alice', 'password123');
echo "Token: {$token}\n";
// 手动设置 Token
$client->setToken($token);
// 获取当前 Token
$currentToken = $client->getToken();
echo "Current token: {$currentToken}\n";
// 清除 Token(匿名访问)
$client->clearToken();
// 获取集群成员列表
$members = $client->getMembers();
echo "Members: " . json_encode($members) . "\n";
// 输出包含: members(数组,包含 ID、name、peerURLs、clientURLs)
// 添加新成员
$result = $client->addMember(['http://192.168.1.100:2380']);
echo "Add member: " . json_encode($result) . "\n";
// 返回新成员的 ID 和集群当前成员列表
// 移除成员
$client->removeMember(123456789);
echo "Remove member\n";
// 更新成员地址
$client->updateMember(123456789, ['http://192.168.1.101:2380']);
echo "Update member\n";
// 提升 learner 成员为投票成员
$client->promoteMember(123456789);
echo "Promote member\n";
// 迁移成员(更新 peer URL)
$client->moveMember(123456789, 'http://192.168.1.102:2380');
echo "Move member\n";
// 获取 Leader 信息
$leader = $client->getLeader();
echo "Leader: " . json_encode($leader) . "\n";
// 输出包含: leader(ID)、raftTerm
// 转移 Leader 到其他成员
$client->moveLeader('8e9e05c52164694d');
echo "Move leader\n";
// 获取 Etcd 版本信息
$version = $client->getVersion();
echo "Version: " . json_encode($version) . "\n";
// 输出: {"etcdserver": "3.5.0", "etcdcluster": "3.5.0"}
// 获取服务器状态
$status = $client->getStatus();
echo "Status: " . json_encode($status) . "\n";
// 输出包含: version、dbSize、leader、raftIndex、raftTerm 等
// 创建快照(保存到 snapshot.db 文件)
$client->snapshot();
echo "Snapshot saved to snapshot.db\n";
// 获取数据哈希(用于数据一致性校验)
$hash = $client->hash();
echo "Hash: " . json_encode($hash) . "\n";
// 碎片整理(释放已删除键占用的空间)
// 注意:此操作会锁定数据库,建议在低峰期执行
$client->defragment();
echo "Defragment completed\n";
// 获取告警列表
$alarms = $client->alarmList();
echo "Alarms: " . json_encode($alarms) . "\n";
// 发送告警
$client->alarmPost('NOSPACE');
echo "Alarm posted: NOSPACE\n";
// 为特定成员发送告警
$client->alarmPost('NOSPACE', '8e9e05c52164694d');
// 获取降级信息
$downgrades = $client->downgradeList();
echo "Downgrades: " . json_encode($downgrades) . "\n";
// 启用降级(降级到指定版本)
$client->downgradeEnable('3.5.0');
echo "Downgrade enabled to 3.5.0\n";
// 取消降级
$client->downgradeCancel();
echo "Downgrade cancelled\n";
// 获取健康状态
$health = $client->getHealth();
echo "Health: " . json_encode($health) . "\n";
// 输出: {"health": "true"} 或 {"health": "false"}
// 获取 Prometheus 格式的监控指标
$metrics = $client->getMetrics();
echo "Metrics: " . substr($metrics, 0, 500) . "...\n";
// 包含: etcd 各种内部指标如 grpc、mvcc、wal 等
// 获取调试信息
$debugInfo = $client->getDebugInfo();
echo "Debug info: {$debugInfo}\n";
// 获取调试变量
$debugVars = $client->getDebugVars();
echo "Debug vars: " . json_encode($debugVars) . "\n";
// 获取 Leader 性能分析
$leaders = $client->getPprofLeaders();
echo "Pprof leaders: " . json_encode($leaders) . "\n";
// 获取 CPU profile(采集 30 秒)
$cpuProfile = $client->getPprofProfile('cpu', 30);
file_put_contents('cpu.pprof', $cpuProfile);
echo "CPU profile saved\n";
// 获取其他类型的 profile
// 可用类型: cpu, heap, goroutine, threadcreate, block, mutex
$heapProfile = $client->getPprofProfile('heap', 30);
// 获取执行追踪数据(采集 30 秒)
$trace = $client->getPprofTrace(30);
file_put_contents('trace.out', $trace);
echo "Trace saved\n";
// 获取符号表
$symbols = $client->getPprofSymbol();
echo "Symbols: " . json_encode($symbols) . "\n";
// 事务:如果 counter 的值等于 10,则更新为 11,否则获取当前值
$result = $client->transaction(
// 比较条件
[
[
'key' => 'counter',
'value' => '10',
'result' => 'EQUAL' // 可选: EQUAL, GREATER, LESS, NOT_EQUAL
]
],
// 条件满足时执行的操作(success)
[
[
'request_put' => [
'key' => base64_encode('counter'),
'value' => base64_encode('11')
]
]
],
// 条件不满足时执行的操作(failure)
[
[
'request_range' => [
'key' => base64_encode('counter')
]
]
]
);
echo "Transaction result: " . json_encode($result) . "\n";
// 输出包含: succeeded(true/false)、responses
// 批量设置(一次性设置多个键值对)
$results = $client->batchPut([
'config/database' => 'mysql://localhost:3306',
'config/redis' => 'redis://localhost:6379',
'config/cache' => 'memcached://localhost:11211'
]);
echo "Batch put completed: " . count($results) . " items\n";
// 批量设置并绑定租约
$results = $client->batchPut([
'service/web1' => '192.168.1.10:8080',
'service/web2' => '192.168.1.11:8080'
], $leaseId);
// 批量获取
$values = $client->batchGet(['config/database', 'config/redis', 'config/cache']);
echo "Batch get: " . json_encode($values) . "\n";
// 输出: {"config/database": "mysql://...", "config/redis": "redis://...", ...}
// 批量删除
$results = $client->batchDelete(['config/database', 'config/redis', 'config/cache']);
echo "Batch delete completed\n";
public function __construct(
string $address = '127.0.0.1:2379', // 服务器地址,格式: host:port
int $timeout = 10 // 请求超时时间(秒)
)
bash
php index.php