kv-store-grpc
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesegRPC Key-Value Store Implementation
基于gRPC的键值存储服务实现
Overview
概述
This skill provides procedural guidance for implementing gRPC-based key-value store services in Python. It covers the full workflow from protobuf definition to server implementation and verification, with emphasis on avoiding common pitfalls.
本指南提供了在Python中实现基于gRPC的键值存储服务的分步指导。内容涵盖从protobuf定义到服务器实现与验证的完整工作流程,并重点介绍如何避免常见陷阱。
Implementation Workflow
实现流程
Step 1: Install Dependencies
步骤1:安装依赖
Install the required gRPC packages:
bash
pip install grpcio grpcio-toolsVerification: After installation, confirm packages are available:
bash
pip list | grep grpcDo not proceed until installation is verified. Missing or incorrect package versions cause silent failures during code generation.
安装所需的gRPC包:
bash
pip install grpcio grpcio-tools验证:安装完成后,确认包已成功安装:
bash
pip list | grep grpc在验证安装完成前不要继续操作。缺失或版本错误的包会导致代码生成过程中出现静默失败。
Step 2: Define the Protocol Buffer
步骤2:定义Protocol Buffer
Create a file with the service definition. Key considerations:
.protoType Selection for Values:
- Use for integer values (standard choice for most use cases)
int32 - Use if values may exceed 32-bit range
int64 - Use for keys (allows flexible key naming)
string
Message Design Pattern:
protobuf
syntax = "proto3";
message SetRequest {
string key = 1;
int32 value = 2;
}
message SetResponse {
bool success = 1;
}
message GetRequest {
string key = 1;
}
message GetResponse {
int32 value = 1;
bool found = 2; // Consider adding to distinguish missing keys from zero values
}Edge Case Consideration: When returning values for non-existent keys, returning a default value (e.g., 0) is ambiguous. Consider:
- Adding a or
foundboolean field to responsesexists - Using gRPC status codes to indicate missing keys
- Documenting the chosen behavior explicitly
创建包含服务定义的文件。关键注意事项:
.proto值的类型选择:
- 整数值使用(大多数场景的标准选择)
int32 - 如果值可能超出32位范围,使用
int64 - 键使用类型(支持灵活的键命名)
string
消息设计示例:
protobuf
syntax = "proto3";
message SetRequest {
string key = 1;
int32 value = 2;
}
message SetResponse {
bool success = 1;
}
message GetRequest {
string key = 1;
}
message GetResponse {
int32 value = 1;
bool found = 2; // 建议添加此字段,以区分不存在的键与值为零的键
}边缘情况考虑:当返回不存在的键对应的值时,返回默认值(如0)会产生歧义。可以考虑以下方案:
- 在响应中添加或
found布尔字段exists - 使用gRPC状态码标识不存在的键
- 明确记录所选的处理行为
Step 3: Generate Python Code
步骤3:生成Python代码
Run the protobuf compiler to generate Python gRPC code:
bash
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. <filename>.protoThis generates two files:
- - Message classes
<filename>_pb2.py - - Service stubs and servicer base classes
<filename>_pb2_grpc.py
Verification: Confirm both files were generated before proceeding:
bash
ls -la *_pb2*.py运行protobuf编译器生成Python gRPC代码:
bash
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. <filename>.proto此命令会生成两个文件:
- - 消息类
<filename>_pb2.py - - 服务存根和服务基类
<filename>_pb2_grpc.py
验证:继续操作前确认两个文件已生成:
bash
ls -la *_pb2*.pyStep 4: Implement the Server
步骤4:实现服务器
Create the server implementation with these considerations:
Server Class Structure:
python
class KVStoreServicer(kv_pb2_grpc.KVStoreServicer):
def __init__(self):
self.store = {}
def SetVal(self, request, context):
self.store[request.key] = request.value
return kv_pb2.SetResponse(success=True)
def GetVal(self, request, context):
value = self.store.get(request.key, 0)
# Document: Returns 0 for non-existent keys
return kv_pb2.GetResponse(value=value)Server Initialization:
python
def serve(port):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
kv_pb2_grpc.add_KVStoreServicer_to_server(KVStoreServicer(), server)
server.add_insecure_port(f'[::]:{port}')
server.start()
print(f"Server started on port {port}", flush=True) # flush=True is critical
server.wait_for_termination()Critical: Use for print statements when running servers in background processes. Without flushing, output may not appear immediately, making it difficult to verify server startup.
flush=True创建服务器实现时需注意以下事项:
服务器类结构:
python
class KVStoreServicer(kv_pb2_grpc.KVStoreServicer):
def __init__(self):
self.store = {}
def SetVal(self, request, context):
self.store[request.key] = request.value
return kv_pb2.SetResponse(success=True)
def GetVal(self, request, context):
value = self.store.get(request.key, 0)
# 文档说明:不存在的键返回0
return kv_pb2.GetResponse(value=value)服务器初始化:
python
def serve(port):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
kv_pb2_grpc.add_KVStoreServicer_to_server(KVStoreServicer(), server)
server.add_insecure_port(f'[::]:{port}')
server.start()
print(f"Server started on port {port}", flush=True) # flush=True至关重要
server.wait_for_termination()关键注意:在后台进程中运行服务器时,打印语句需使用。如果不刷新输出,信息可能不会立即显示,导致难以验证服务器是否启动。
flush=TrueStep 5: Verify Server Operation
步骤5:验证服务器运行
Prefer functional testing over system diagnostics. Testing with an actual gRPC client is the definitive verification method.
Avoid this approach (unreliable, tool-dependent):
bash
undefined优先使用功能测试而非系统诊断。使用实际的gRPC客户端进行测试是最可靠的验证方法。
避免以下不可靠的方法(依赖特定工具):
bash
undefinedThese may not be available and don't confirm gRPC functionality
这些工具可能未安装,且无法确认gRPC功能是否正常
netstat -tlnp | grep <port>
ss -tlnp | grep <port>
lsof -i :<port>
**Use this approach** (direct functional test):
```python
import grpc
import kv_pb2
import kv_pb2_grpc
channel = grpc.insecure_channel('localhost:<port>')
stub = kv_pb2_grpc.KVStoreStub(channel)netstat -tlnp | grep <port>
ss -tlnp | grep <port>
lsof -i :<port>
**推荐使用以下方法**(直接功能测试):
```python
import grpc
import kv_pb2
import kv_pb2_grpc
channel = grpc.insecure_channel('localhost:<port>')
stub = kv_pb2_grpc.KVStoreStub(channel)Test Set operation
测试设置操作
response = stub.SetVal(kv_pb2.SetRequest(key="test", value=42))
print(f"Set success: {response.success}")
response = stub.SetVal(kv_pb2.SetRequest(key="test", value=42))
print(f"Set success: {response.success}")
Test Get operation
测试获取操作
response = stub.GetVal(kv_pb2.GetRequest(key="test"))
print(f"Got value: {response.value}")
Run inline if possible to avoid creating temporary test files:
```bash
python -c "import grpc; ..."response = stub.GetVal(kv_pb2.GetRequest(key="test"))
print(f"Got value: {response.value}")
如果可能,直接在命令行运行以避免创建临时测试文件:
```bash
python -c "import grpc; ..."Common Pitfalls
常见陷阱
1. Missing Key Ambiguity
1. 不存在的键歧义
Returning default values (0, empty string) for missing keys is indistinguishable from keys with those actual values. Design the protocol to handle this explicitly.
返回默认值(0、空字符串)表示不存在的键时,无法与实际值为默认值的键区分开。需在协议设计中明确处理这种情况。
2. Output Buffering in Background Processes
2. 后台进程中的输出缓冲
Print statements without may never appear when running servers in background. Always flush output for startup confirmation messages.
flush=True在后台运行服务器时,未使用的打印语句可能永远不会显示。启动确认消息务必刷新输出。
flush=True3. Excessive Diagnostic Commands
3. 过多的诊断命令
Avoid chaining system utilities (netstat, ss, lsof, ps) to verify server status. These tools may not be installed and don't confirm gRPC protocol functionality. Use a real client instead.
避免链式使用系统工具(netstat、ss、lsof、ps)来验证服务器状态。这些工具可能未安装,且无法确认gRPC协议功能是否正常。应使用真实客户端进行测试。
4. Unverified Package Installation
4. 未验证包安装
Always verify pip installations succeeded before proceeding. Silent installation failures cause confusing errors during code generation or runtime.
继续操作前务必确认pip安装已成功。静默安装失败会导致代码生成或运行时出现难以理解的错误。
5. Missing Error Handling
5. 缺失错误处理
Consider adding try-except blocks around RPC method implementations to handle unexpected errors gracefully and return appropriate gRPC status codes.
建议在RPC方法实现中添加try-except块,以优雅处理意外错误并返回合适的gRPC状态码。
Verification Checklist
验证清单
Before considering the task complete:
- Dependencies installed and verified with
pip list - Proto file compiles without errors
- Both and
_pb2.pyfiles generated_pb2_grpc.py - Server starts and prints confirmation (with )
flush=True - Functional test with gRPC client succeeds for all operations
- Edge cases documented (missing keys, zero values)
在任务完成前,请确认以下事项:
- 依赖已安装并通过验证
pip list - Proto文件编译无错误
- 已生成和
_pb2.py两个文件_pb2_grpc.py - 服务器启动并打印确认信息(已使用)
flush=True - 使用gRPC客户端的功能测试所有操作均成功
- 边缘情况已记录(不存在的键、零值)