轻聆月下
轻聆月下
发布于 2024-03-24 / 38 阅读
0
0

python3 连接 ETCD3 操作纪要

一、安装

1.1 安装ETCD包

python3 -m pip install etcd3

1.2 问题解决

直接安装完成后,在使用过程中可能会出现一些问题,作以记录如下。

1.2.1 protos 问题

在使用过程中,可能会遇到下述报错:

......
If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
 1. Downgrade the protobuf package to 3.20.x or lower.
 2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).

意思是 protoc 这个玩意儿版本低了,调用有问题。你要是不能重新生成,可以通过两个步骤解决此问题:

  1. protobuf 使用3.20.x 版本或者更低的版本:python3 -m pip install protobuf==3.20.1
  2. 设置一个环境变量:export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
    环境变量建议设置在 ~/.bashrc 或者 /etc/profile

1.2.2 UNAUTHENTICATED 问题

......
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAUTHENTICATED
        details = "Established channel does not have a sufficient security level to transfer call credential."
......

此问题是grpc的认证问题,在高版本的grpc中要求安全的通讯信道,比如SSL。

如果不能对ETCD服务设置SSL,那么可以通过降低grpc版本解决。参考:etcd3 and python: UNAUTHENTICATED: Established channel does not have a sufficient security level to transfer call credential · Issue #29643 · grpc/grpc (github.com)

执行下述安装即可,会卸载当前版本的grpcio,安装指定版本:

python3 -m pip install grpcio==1.44.0

二、获取数据

使用可以参考:API Usage — python-etcd3 0.8.1 documentation

正常的Get、Put直接操作即可,如果通过 get_prefix 获取,可能会遇到如下错误:

grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.RESOURCE_EXHAUSTED
        details = "Received message larger than max (135558824 vs. 4194304)"

意思是获取的消息内容太大,超过了grpc设置。此时我们可以通过在etcd创建的时候指定grpc设置,来修改消息内容上限:

etcd_client = etcd3.client(host="127.0.0.1", port=2379,
                 grpc_options={
                     "grpc.max_send_message_length": 1024*1024*1024,    # 设置发送消息的尺寸上限
                     "grpc.max_receive_message_length": 1024*1024*1024, # 设置接受消息的尺寸上限
                   }.items()
                 )

上述代码在etcd客户端初始化时设置了发送和接受消息的大小上限。可以缓解 “Received message larger than max” 错误。

如果改到足够大的尺寸,还是不能缓解问题,则需要通过其他手段限制获取的内容大小。比如,使用 get_range 方法分段获取所需内容。下述代码是通过 get_range 获取所有ETCD内容:

start_key = "/"      # 起始 key
end_key = "\0"       # 结束 key,若没有,则应设为 \0,此处不设置结束 key,以便获取所有 key
limit_per_get = 1000 # 每次获取的最大数量
while True:
    items = etcd_client.get_range(range_start=start_key,
                        range_end=end_key,
                        limit=limit_per_get)
    count = 0 # 记录本次获取数量
    for item in items:
        count += 1
        #
        # 这里可以对 item 进行处理
        #

        # 重设起始 key
        start_key = item[1].key
    # 若本次获取小于 limit_per_get,则说明已经获取完毕
    if count < limit_per_get:
        break

通过控制每次获取的key的数量控制响应内容的大小,虽然多次获取会影响效率,但是比报错要好点儿。


评论