A comunicação por Procedimento Remoto (RPC) é um conceito bem estabelecido em desenvolvimento de software, exemplificado por protocolos como NFS. O RPC do SUN, em particular, é um mecanismo clássico de chamadas entre processos em C.
No ecossistema OpenStack, o RPC é implementado através de protocolos de mensagens avançados como AMQP. A biblioteca oslo.messaging fornece uma interface elegante sobre esses protoccolos, simplificando a adoção de RPC para desenvolvedores.
Para demonstrar a criação de um servidor RPC no OpenStack, seguiremos a documentação para desenvolvedores do oslo.messaging.
Servidor RPC
O código a seguir implementa um servidor RPC básico:
from oslo_config import cfg
import oslo_messaging
class ServerControlEndpoint(object):
target = oslo_messaging.Target(namespace='control', version='2.0')
def __init__(self, rpc_server_instance):
print("Inicializando ServerControlEndpoint")
self.rpc_server = rpc_server_instance
def stop(self, ctx):
print("Recebido comando para parar o servidor...")
if self.rpc_server:
self.rpc_server.stop()
class SampleEndpoint(object):
def sample_method(self, ctx, input_data):
print(f"Endpoint SampleEndpoint chamado com dados: {input_data}")
return f"Processado: {input_data}"
# Configuração e transporte
conf = cfg.CONF
transport = oslo_messaging.get_transport(conf)
print(f"Configuração: {conf}")
print(f"Transporte: {transport}")
# Definição do alvo do servidor RPC
server_target = oslo_messaging.Target(topic='sample_topic', server='server_instance_01')
print(f"Alvo do servidor: {server_target}")
# Lista de endpoints que o servidor irá expor
endpoints_list = [
ServerControlEndpoint(None), # O servidor real será passado após a criação
SampleEndpoint(),
]
# Criação e inicialização do servidor RPC
# O placeholder 'None' para ServerControlEndpoint será atualizado após a criação do servidor
rpc_server_instance = oslo_messaging.get_rpc_server(
transport,
server_target,
endpoints_list,
executor='blocking'
)
# Atualiza o servidor real no endpoint de controle
for endpoint in endpoints_list:
if isinstance(endpoint, ServerControlEndpoint):
endpoint.rpc_server = rpc_server_instance
break
print(f"Servidor RPC: {rpc_server_instance}")
# Inicia o servidor e o mantém em execução
rpc_server_instance.start()
print("Servidor RPC iniciado. Aguardando chamadas...")
rpc_server_instance.wait()
Para executar este servidor, salve o código como rpc_server.py e execute-o no terminal: python rpc_server.py. O servider ficará em espera por conexões de cliantes.
Cliente RPC
O cliente a seguir demonstra como realizar chamadas para o servidor RPC:
from oslo_config import cfg
import oslo_messaging as messaging
# Configuração e transporte
conf = cfg.CONF
transport = messaging.get_transport(conf)
# Definição do alvo para o cliente se conectar
client_target = messaging.Target(topic='sample_topic')
# Para chamadas com versionamento específico, descomente a linha abaixo
# client_target = messaging.Target(topic='sample_topic', version='2.0')
# Criação do cliente RPC
rpc_client = messaging.RPCClient(transport, client_target)
# Realiza uma chamada direta ao método 'sample_method'
print("Chamada direta ao método 'sample_method':")
try:
result_direct = rpc_client.call({}, 'sample_method', input_data="Dados de teste 1")
print(f"Resultado da chamada direta: {result_direct}")
except Exception as e:
print(f"Erro na chamada direta: {e}")
# Prepara um contexto de chamada para métodos com versionamento ou outros preparos
# cctxt = rpc_client.prepare(version='2.0') # Exemplo com versionamento
cctxt = rpc_client.prepare() # Preparo sem versionamento específico
# Realiza uma chamada usando o contexto preparado
print("\nChamada usando cliente preparado:")
try:
result_prepared = cctxt.call({}, 'sample_method', input_data="Dados de teste 2")
print(f"Resultado da chamada preparada: {result_prepared}")
except Exception as e:
print(f"Erro na chamada preparada: {e}")
Salve este código como rpc_client.py e execute-o após iniciar o servidor. A saída do cliente exibirá os resultados retornados pelo servidor.
Notificações (Opcional)
A biblioteca oslo.messaging também suporta um padrão de publicação/assinatura para notificações, que podem ser usadas para eventos assíncronos.
- Para mais detalhes sobre Notificadores, consulte: Documentação de Notificadores
- Para implementar um Ouvinte de Notificações, consulte: Documentação de Ouvinte de Notificações