阶段2(上):后端专题 Go/Gin/PostgreSQL/MySQL/Redis/MQ/gRPC 的课程、企业场景、面试题和可运行示例
This commit is contained in:
1 parent
0bae9916a9
commit
5eb67c5d08
65 files changed
+6457
-77
No files matched your search
@@ -0,0 +1,81 @@
|
||||
# requires: grpc, grpc_tools
|
||||
"""gRPC 演示:从 user.proto 生成代码 → 启动服务端 → 客户端调用(一元、服务端流、超时、错误码)。
|
||||
|
||||
运行:pip install grpcio grpcio-tools && python demo.py
|
||||
生成的代码放在临时目录,不污染仓库。
|
||||
"""
|
||||
import importlib
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from concurrent import futures
|
||||
from pathlib import Path
|
||||
|
||||
import grpc
|
||||
from grpc_tools import protoc
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def generate(out: Path):
|
||||
rc = protoc.main(["protoc", f"-I{HERE}", f"--python_out={out}", f"--grpc_python_out={out}", str(HERE / "user.proto")])
|
||||
assert rc == 0, "protoc 生成失败"
|
||||
sys.path.insert(0, str(out))
|
||||
return importlib.import_module("user_pb2"), importlib.import_module("user_pb2_grpc")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
pb, pb_grpc = generate(Path(tmp))
|
||||
users = {i: pb.User(id=i, name=f"用户{i}", email=f"u{i}@example.com") for i in range(1, 6)}
|
||||
|
||||
class UserService(pb_grpc.UserServiceServicer):
|
||||
def GetUser(self, request, context):
|
||||
if request.id == 99:
|
||||
time.sleep(0.5) # 模拟慢请求
|
||||
user = users.get(request.id)
|
||||
if user is None:
|
||||
context.abort(grpc.StatusCode.NOT_FOUND, f"用户 {request.id} 不存在")
|
||||
return user
|
||||
|
||||
def ListUsers(self, request, context):
|
||||
for i, u in enumerate(users.values()):
|
||||
if i >= request.page_size:
|
||||
break
|
||||
yield u
|
||||
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
|
||||
pb_grpc.add_UserServiceServicer_to_server(UserService(), server)
|
||||
port = server.add_insecure_port("127.0.0.1:0") # 0 = 随机可用端口
|
||||
server.start()
|
||||
try:
|
||||
with grpc.insecure_channel(f"127.0.0.1:{port}") as ch:
|
||||
stub = pb_grpc.UserServiceStub(ch)
|
||||
u = stub.GetUser(pb.GetUserRequest(id=1), timeout=1.0) # 每次调用都带超时
|
||||
print("一元调用:", u.id, u.name)
|
||||
assert u.name == "用户1"
|
||||
|
||||
names = [x.name for x in stub.ListUsers(pb.ListUsersRequest(page_size=3), timeout=1.0)]
|
||||
print("服务端流:", names)
|
||||
assert len(names) == 3
|
||||
|
||||
try:
|
||||
stub.GetUser(pb.GetUserRequest(id=42), timeout=1.0)
|
||||
raise AssertionError("应该返回 NOT_FOUND")
|
||||
except grpc.RpcError as e:
|
||||
print("错误码:", e.code().name, e.details())
|
||||
assert e.code() == grpc.StatusCode.NOT_FOUND
|
||||
|
||||
try:
|
||||
stub.GetUser(pb.GetUserRequest(id=99), timeout=0.1)
|
||||
raise AssertionError("应该超时")
|
||||
except grpc.RpcError as e:
|
||||
print("超时:", e.code().name)
|
||||
assert e.code() == grpc.StatusCode.DEADLINE_EXCEEDED
|
||||
finally:
|
||||
server.stop(grace=None)
|
||||
print("gRPC 演示通过")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user