grpc
-
rpc使服务之间的方法调用像本地一样,感知不到网络通信的存在。
-
rpc是基于tcp协议的,但grpc是基于http2协议的。http2的好处是公开通用。
-
rpc主要有两个工作,序列化(对象转换为二进制,用于网络传输),编解码(被调用方收到数据包,需要知道他的方法名,输入参数在数据包的起始位置等)
-
grpc中函数中的context参数是啥意思
在 gRPC 中,函数中的
context
参数是用于传递上下文信息的对象。它提供了一种在不同的函数调用之间共享状态、传递截止时间、取消信号以及其他相关信息的方式。context
参数通常被用作第一个参数传递给 gRPC 服务方法。通过
context
,可以实现以下功能:- 截止时间控制:可以设置请求的截止时间,当超过截止时间时,gRPC 框架可以自动取消请求。
- 取消请求:可以通过
context
发送取消信号,通知正在进行的请求取消操作。 - 传递元数据:可以在
context
中添加键值对形式的元数据,这些元数据可以在服务端和客户端之间进行传递。 - 共享状态:可以在
context
中存储和共享一些与请求相关的状态信息。context
的使用使得 gRPC 服务能够更好地处理并发请求、超时情况和取消操作,同时也方便了在不同函数之间传递相关的上下文信息。
-
context.abort()
context.abort()
是 gRPC 框架中用于终止 RPC(Remote Procedure Call)调用的方法。它可以在服务器端或客户端使用,用于在出现错误或异常情况时,主动中断正在进行的 RPC 调用,并向对方发送一个错误状态码和可选的详细信息。 以下是context.abort()
的一般用法:- 在服务器端,当服务器在处理 RPC 调用时遇到错误或异常情况,可以调用
context.abort()
来终止该调用。这将导致客户端收到一个错误响应,并可以根据错误状态码进行相应的处理。 - 在客户端,当客户端发现与服务器的连接出现问题或 RPC 调用超时等情况时,也可以调用
context.abort()
来中断调用。 通过使用context.abort()
,可以在 gRPC 通信中及时处理错误情况,并提供更明确的错误反馈。这样可以帮助开发者更好地处理异常情况,增强系统的健壮性和可靠性。
- 在服务器端,当服务器在处理 RPC 调用时遇到错误或异常情况,可以调用
-
proto文件可以有多个,之间通过import引入。当不确定参数类型时,可以import Any 类型,代指任何类型。
-
http1中一个TCP通道在同一时刻只能处理一个请求,也就是说只有存在response结果时,才能接着处理下一个请求
而http2中引入了流和二进制帧,在同一个TCP通道中可以处理多个请求,在一个TCP通道中,虚拟出了多个流,流之间处理请求不分先后,不会阻塞,并进行了头部压缩,大幅度提高了交互效率
-
在grpc中可以直接使用stream。
分为客户端流(请求参数前加上stream关键字),服务端流(返回参数中前加上stream关键字),双向流(请求参数和返回参数中前加上stream关键字)
客户端流:客户端发送多个流,服务端处理一次
服务端流:客户端只发送一个请求,服务端多次响应,直至完成
双向流:两端不停的发消息,可用于心跳检测,websocket
-
以下是这些流模式各自常见的使用场景:
客户端流:
- 文件上传:客户端可以逐步将一个大文件分块发送给服务器进行处理,比如图像、视频等的上传。
- 实时数据采集:例如传感器持续发送数据到服务器进行分析和存储。
服务端流:
- 实时监控数据推送:服务器主动向客户端推送实时更新的监控信息,如股票行情、天气数据等。
- 逐步返回大量查询结果:当查询结果非常多时,服务器可以逐步流式返回,而不是一次性返回导致延迟过高。
双向流:
- 实时交互应用:如在线游戏中,双方可以实时交互信息,包括动作、状态等。
- 即时通讯:客户端和服务器之间可以实时双向传递消息,类似聊天应用。
- 协作编辑:多个客户端与服务器进行双向交互,实现实时协作编辑文档等操作。
例如,在一个视频会议应用中,可能会使用双向流来实时传输音频和视频数据;在一个工业控制系统中,可能使用客户端流来上传设备状态数据,同时使用服务端流来下发控制指令。
-
sirius_pb2_grpc.GRPCServicer
sirius_pb2_grpc.GRPCServicer
通常是在使用 gRPC(Google 远程过程调用)框架时定义的一个服务类。在 gRPC 中,服务端需要实现定义好的服务接口,而这个接口是在
.proto
文件中定义的,并通过 protoc 编译器生成对应的 Python 代码(其中就包括了从GRPCServicer
继承的类)。例如,如果在
.proto
文件中有如下定义的服务:service SiriusService { rpc SomeMethod (SomeRequest) returns (SomeResponse) {} }
那么 protoc 编译器生成的 Python 代码中可能就会有一个名为
SiriusServiceServicer
的类,它继承自sirius_pb2_grpc.GRPCServicer
,服务端需要创建这个类的实例,并实现其中具体的方法(如上述例子中的SomeMethod
)来处理客户端的请求。以下是一个简单的示例代码,展示了如何创建一个继承自
GRPCServicer
的服务类并实现其中定义的方法:假设已经有一个生成的
example_pb2_grpc.py
文件(包含了ExampleServiceServicer
类),对应的.proto
文件里定义了一个rpc DoSomething (ExampleRequest) returns (ExampleResponse);
的服务方法。import grpc from concurrent import futures from example_pb2_grpc import ExampleServiceServicer from example_pb2 import ExampleRequest, ExampleResponse class MyExampleService(ExampleServiceServicer): def DoSomething(self, request, context): # 处理客户端的请求并返回响应 result = f"Received request with data: {request.data}" return ExampleResponse(result=result) def serve(): # 创建 gRPC 服务器,并指定线程池大小 server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) # 将自定义的服务类添加到服务器中 add_ExampleServiceServicer_to_server(MyExampleService(), server) # 绑定服务器的端口 server.add_insecure_port('localhost:50051') # 启动服务器 server.start() print("Server started. Listening on port 50051...") try: # 保持服务器运行,直到被中断 while True: time.sleep(60 * 60 * 24) # 一天的秒数,实际应用中可以根据需要修改 except KeyboardInterrupt: server.stop(0) if __name__ == '__main__': serve()
在上述示例中:
MyExampleService
继承自ExampleServiceServicer
。- 实现了
DoSomething
方法,该方法接收ExampleRequest
类型的请求参数request
和context
(用于处理 RPC 的上下文信息,例如设置超时、获取元数据等,这里简单示例没有用到它),并返回一个ExampleResponse
对象作为响应。 - 在
serve
函数中创建服务器实例后,通过add_ExampleServiceServicer_to_server
方法将MyExampleService
的实例添加到服务器,这样服务器就知道如何处理客户端对DoSomething
方法的调用请求了。
-
sirius_pb2_grpc.GRPCStub(channel)
在使用
grpc
库创建一个GRPCStub
对象。channel
通常是一个与 gRPC 服务器建立的连接通道。通过将这个通道传递给GRPCStub
的构造函数,可以创建一个客户端存根,用于向服务器发送请求和接收响应。