对于我们新的开放实验室设备自动化标准(https://gitlab.com/SiLA2/sila_python),我们希望以两种模式运行设备(=gRPC 服务器):模拟模式和真实模式(具有相同的设置远程调用,但在第一种情况下,它应该只返回模拟响应,在第二种情况下它应该与硬件通信。
我的第一个想法是在单独的模块中创建两个几乎相同的 gRPC 服务程序 python 类,如下例所示:
在hello_sim.py中:
class SayHello(SayHello_pb2_grpc.SayHelloServicer):
#... implementation of the simulation servicer
def SayHello(self, request, context):
# simulation code ...
return SayHello_pb2.SayHello_response("simulation")
在hello_real.py中:
class SayHello(SayHello_pb2_grpc.SayHelloServicer):
#... implementation of the real servicer
def SayHello(self, request, context):
# real hardware code
return SayHello_pb2.SayHello_response("real")
然后,在 server.py 中创建 gRPC 服务器后,我可以通过在 gRPC 服务器上重新注册 servcier 来在模拟和实模式之间切换,例如:
服务器.py
# imports, init ...
grpc_server = GRPCServer(ThreadPoolExecutor(max_workers=10))
sh_sim = SayHello_sim.SayHello()
sh_real = SayHello_real.SayHello()
SayHello_pb2_grpc.add_SayHelloServicer_to_server(sh_sim, grpc_server)
grpc_server.run()
# ..... and later, still while the same grpc server is running, re-register, like
SayHello_pb2_grpc.add_SayHelloServicer_to_server(sh_real, grpc_server)
能够调用真正的硬件代码;或通过交换对服务对象的引用,例如:
# imports, init ...
grpc_server = GRPCServer(ThreadPoolExecutor(max_workers=10))
sh_sim = SayHello_sim.SayHello()
sh_real = SayHello_real.SayHello()
sh_current = sh_sim
SayHello_pb2_grpc.add_SayHelloServicer_to_server(sh_current , grpc_server)
grpc_server.run()
# ..... and then later, still while the same grpc server is running, re-register the real Servicer, like
sh_current = sh_real
# so that the server would just use the other servicer object for the next calls ...
但是这两种策略都不起作用:(
从 gRPC 客户端以模拟模式调用服务器时,我希望它应该回复(根据示例):“模拟”
gRPC_client.py
# imports, init ....
response = self.SayHello_stub.SayHello()
print(response)
>'simulation'
并在切换到实模式(通过任何机制)“真实”之后:
# after switching to real mode ...
response = self.SayHello_stub.SayHello()
print(response)
>'real'
在不完全关闭 gRPC 服务器(以及失去与客户端的连接)的情况下实现这种模式切换的最简洁和优雅的解决方案是什么?
非常感谢您提前提供的帮助!
PS:(关闭 gRPC 服务器并重新注册当然可以,但这不是我们想要的。)