Utilização de RPC em OpenStack com oslo.messaging

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.

Tags: oslo.messaging openstack rpc AMQP Python

Publicado em 6-16 01:30 por Thomas