7

尝试用于从 Java 代码coreos/jetcd更新 haproxy 设置。etcd

我想要实现的是:

  1. 删除单个主机的所有端点
  2. 为给定主机添加更新数据

我想通过前缀删除所有键,并将实际数据作为原子操作放入 etcd。

这就是我尝试使用 etcd 事务的原因。我的代码是:

Op.DeleteOp deleteOp = Op.delete(
        fromString(prefix),
        DeleteOption.newBuilder().withPrefix(fromString(prefix)).build()
);
Txn tx = kvClient.txn().Else(deleteOp);
newKvs.forEach((k,v) -> {
    tx.Else(Op.put(fromString(k), fromString(v), DEFAULT));
});
try {
    tx.commit().get();
} catch (InterruptedException | ExecutionException e) {
    log.error("ETCD transaction failed", e);
    throw new RuntimeException(e);
}

使用 ETCD v3 API (etcd v3.2.9)。KVstore 最初是空的,我想添加 3 条记录。 prefix值为:

/proxy-service/hosts/example.com

并且kvs是一个地图:

"/proxy-service/hosts/example.com/FTP/0" -> "localhost:10021"
"/proxy-service/hosts/example.com/HTTPS/0" -> "localhost:10443"
"/proxy-service/hosts/example.com/HTTP/0" -> "localhost:10080"

异常发生commit().get()在线与以下根本原因:

Caused by: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: etcdserver: duplicate key given in txn request
    at io.grpc.Status.asRuntimeException(Status.java:526)
    at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:427)
    at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
    at com.coreos.jetcd.internal.impl.ClientConnectionManager$AuthTokenInterceptor$1$1.onClose(ClientConnectionManager.java:267)
    at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:419)
    at io.grpc.internal.ClientCallImpl.access$100(ClientCallImpl.java:60)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:493)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$500(ClientCallImpl.java:422)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:525)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:102)
    ... 3 more

我做错了什么,我还能如何完成几个 etcd 更改作为原子操作?

4

1 回答 1

0

看起来删除一个键然后为同一个键添加一个新值的操作不能在同一个txn. 根据etcd APIv3 文档

Txn 在单个事务中处理多个请求。一个 txn 请求会增加键值存储的修订,并为每个完成的请求生成具有相同修订的事件。一个 txn 内不允许多次修改同一个 key

于 2018-08-24T18:31:53.333 回答