Для нашего нового открытого стандарта автоматизации лабораторных устройств (https://gitlab.com/SiLA2/sila_python)) мы хотели бы запустить устройства (= серверы gRPC) в двух режимах: режиме моделирования и реальном режиме (с одинаковым набором удаленных вызовов). , но в первом случае он должен просто возвращать смоделированные ответы, во втором он должен связываться с оборудованием.
Моя первая идея состояла в том, чтобы создать два почти идентичных класса Python обслуживающего устройства gRPC в отдельных модулях, как в этом примере:
in 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")
in 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")
и затем, после создания сервера gRPC в server.py, я мог переключаться между симуляцией и реальным режимом путем повторной регистрации сервера на сервере gRPC, например ::
server.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)
для возможности вызова реального аппаратного кода;
или путем обмена ссылкой на объект обслуживающего устройства, например, например ::1010*
# 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 и перерегистрация, конечно, будет работать, но это не то, чего мы хотим.)