Conectar-se e comunicar-se com serviços no Service Fabric

No Service Fabric, um serviço é executado em algum lugar em um cluster do Service Fabric, normalmente distribuído entre várias VMs. Ele pode ser movido de um lugar para outro, seja pelo proprietário do serviço ou automaticamente pelo Service Fabric. Os serviços não estão estaticamente vinculados a uma máquina ou endereço específico.

Um aplicativo do Service Fabric geralmente é composto por muitos serviços diferentes, onde cada serviço executa uma tarefa especializada. Esses serviços podem se comunicar entre si para formar uma função completa, como renderizar diferentes partes de um aplicativo Web. Há também aplicativos cliente que se conectam e se comunicam com serviços. Este documento discute como configurar a comunicação com e entre seus serviços no Service Fabric.

Confira nesta página um vídeo de treinamento que também discute a comunicação de serviço:

Traga o seu próprio protocolo

O Service Fabric ajuda a gerenciar o ciclo de vida de seus serviços, mas não toma decisões sobre o que seus serviços fazem. Isto inclui a comunicação. Quando o serviço é aberto pelo Service Fabric, essa é a oportunidade do serviço configurar um ponto de extremidade para solicitações de entrada, usando qualquer protocolo ou pilha de comunicação desejada. Seu serviço escutará em um endereço IP:port normal usando qualquer esquema de endereçamento, como um URI. Várias instâncias de serviço ou réplicas podem compartilhar um processo de host, caso em que precisarão usar portas diferentes ou usar um mecanismo de compartilhamento de portas, como o driver do kernel http.sys no Windows. Em ambos os casos, cada instância de serviço ou réplica em um processo de host deve ser endereçável exclusivamente.

Pontos de extremidade de serviço

Descoberta e resolução de serviços

Em um sistema distribuído, os serviços podem passar de uma máquina para outra ao longo do tempo. Isso pode acontecer por vários motivos, incluindo balanceamento de recursos, atualizações, failovers ou expansão. Isso significa que os endereços de ponto de extremidade do serviço mudam à medida que o serviço se move para nós com endereços IP diferentes e podem abrir em portas diferentes se o serviço usar uma porta selecionada dinamicamente.

Distribuição de serviços

O Service Fabric fornece um serviço de descoberta e resolução chamado Serviço de Nomenclatura. O Serviço de Nomenclatura mantém uma tabela que mapeia instâncias de serviço nomeadas para os endereços de ponto de extremidade em que elas escutam. Todas as instâncias de serviço nomeadas no Service Fabric têm nomes exclusivos representados como URIs, por exemplo, "fabric:/MyApplication/MyService". O nome do serviço não muda ao longo da vida útil do serviço, são apenas os endereços de ponto de extremidade que podem mudar quando os serviços são movidos. Isso é análogo a sites que têm URLs constantes, mas onde o endereço IP pode mudar. E semelhante ao DNS na Web, que resolve URLs de sites para endereços IP, o Service Fabric tem um registrador que mapeia nomes de serviço para seu endereço de ponto de extremidade.

Diagrama que mostra que o Service Fabric tem um registrador que mapeia nomes de serviço para seu endereço de ponto de extremidade.

A resolução e a conexão com serviços envolvem as seguintes etapas executadas em um loop:

  • Resolver: obtenha o ponto de extremidade que um serviço publicou a partir do Serviço de Nomenclatura.
  • Conectar: conecte-se ao serviço por meio de qualquer protocolo que ele use nesse ponto de extremidade.
  • Repetir: uma tentativa de conexão pode falhar por vários motivos, por exemplo, se o serviço tiver sido movido desde a última vez que o endereço do ponto de extremidade foi resolvido. Nesse caso, as etapas de resolução e conexão anteriores precisam ser repetidas e esse ciclo é repetido até que a conexão seja bem-sucedida.

Ligação a outros serviços

Os serviços que se conectam uns aos outros dentro de um cluster geralmente podem acessar diretamente os pontos de extremidade de outros serviços porque os nós em um cluster estão na mesma rede local. Para facilitar a conexão entre serviços, o Service Fabric fornece serviços adicionais que usam o Serviço de Nomenclatura. Um serviço DNS e um serviço de proxy reverso.

Serviço DNS

Como muitos serviços, especialmente serviços em contêineres, podem ter um nome de URL existente, ser capaz de resolvê-los usando o protocolo DNS padrão (em vez do protocolo Naming Service) é muito conveniente, especialmente em cenários de "lift and shift" de aplicativos. Isso é exatamente o que o serviço DNS faz. Ele permite mapear nomes DNS para um nome de serviço e, portanto, resolver endereços IP de ponto final.

Conforme mostrado no diagrama a seguir, o serviço DNS, em execução no cluster do Service Fabric, mapeia nomes DNS para nomes de serviço que são resolvidos pelo Serviço de Nomenclatura para retornar os endereços de ponto de extremidade aos quais se conectar. O nome DNS para o serviço é fornecido no momento da criação.

Diagrama que mostra como o serviço DNS, quando executado no cluster do Service Fabric, mapeia nomes DNS para nomes de serviço que são resolvidos pelo Serviço de Nomenclatura para retornar os endereços de ponto de extremidade aos quais se conectar.

Para obter mais detalhes sobre como usar o serviço DNS, consulte o artigo Serviço DNS no Azure Service Fabric .

Serviço de proxy reverso

O proxy reverso aborda serviços no cluster que expõe pontos de extremidade HTTP, incluindo HTTPS. O proxy reverso simplifica muito a chamada de outros serviços e seus métodos, tendo um formato de URI específico e lida com as etapas de resolução, conexão e repetição necessárias para que um serviço se comunique com outro usando o Serviço de Nomenclatura. Em outras palavras, ele oculta o Serviço de Nomenclatura de você ao chamar outros serviços, tornando isso tão simples quanto chamar uma URL.

Diagrama que mostra como o proxy reverso aborda serviços no cluster que expõe pontos de extremidade HTTP, incluindo HTTPS.

Para obter mais detalhes sobre como usar o serviço de proxy reverso, consulte o artigo Proxy reverso no Azure Service Fabric .

Conexões de clientes externos

Os serviços que se conectam uns aos outros dentro de um cluster geralmente podem acessar diretamente os pontos de extremidade de outros serviços porque os nós em um cluster estão na mesma rede local. Em alguns ambientes, no entanto, um cluster pode estar atrás de um balanceador de carga que roteia o tráfego de entrada através de um conjunto limitado de portas. Nesses casos, os serviços ainda podem se comunicar entre si e resolver endereços usando o Serviço de Nomenclatura, mas etapas adicionais devem ser tomadas para permitir que clientes externos se conectem aos serviços.

Service Fabric no Azure

Um cluster do Service Fabric no Azure é colocado atrás de um Balanceador de Carga do Azure. Todo o tráfego externo para o cluster deve passar pelo balanceador de carga. O balanceador de carga encaminhará automaticamente o tráfego de entrada em uma determinada porta para um nó aleatório que tenha a mesma porta aberta. O Balanceador de Carga do Azure só sabe sobre portas abertas nos nós, não sabe sobre portas abertas por serviços individuais.

Topologia do Azure Load Balancer e Service Fabric

Por exemplo, para aceitar tráfego externo na porta 80, as seguintes coisas devem ser configuradas:

  1. Escreva um serviço que ouça na porta 80. Configure a porta 80 no ServiceManifest.xml do serviço e abra um ouvinte no serviço, por exemplo, um servidor Web auto-hospedado.

    <Resources>
        <Endpoints>
            <Endpoint Name="WebEndpoint" Protocol="http" Port="80" />
        </Endpoints>
    </Resources>
    
        class HttpCommunicationListener : ICommunicationListener
        {
            ...
    
            public Task<string> OpenAsync(CancellationToken cancellationToken)
            {
                EndpointResourceDescription endpoint =
                    serviceContext.CodePackageActivationContext.GetEndpoint("WebEndpoint");
    
                string uriPrefix = $"{endpoint.Protocol}://+:{endpoint.Port}/myapp/";
    
                this.httpListener = new HttpListener();
                this.httpListener.Prefixes.Add(uriPrefix);
                this.httpListener.Start();
    
                string publishUri = uriPrefix.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);
                return Task.FromResult(publishUri);
            }
    
            ...
        }
    
        class WebService : StatelessService
        {
            ...
    
            protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
            {
                return new[] { new ServiceInstanceListener(context => new HttpCommunicationListener(context))};
            }
    
            ...
        }
    
        class HttpCommunicationlistener implements CommunicationListener {
            ...
    
            @Override
            public CompletableFuture<String> openAsync(CancellationToken arg0) {
                EndpointResourceDescription endpoint =
                    this.serviceContext.getCodePackageActivationContext().getEndpoint("WebEndpoint");
                try {
                    HttpServer server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(endpoint.getPort()), 0);
                    server.start();
    
                    String publishUri = String.format("http://%s:%d/",
                        this.serviceContext.getNodeContext().getIpAddressOrFQDN(), endpoint.getPort());
                    return CompletableFuture.completedFuture(publishUri);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
    
            ...
        }
    
        class WebService extends StatelessService {
            ...
    
            @Override
            protected List<ServiceInstanceListener> createServiceInstanceListeners() {
                <ServiceInstanceListener> listeners = new ArrayList<ServiceInstanceListener>();
                listeners.add(new ServiceInstanceListener((context) -> new HttpCommunicationlistener(context)));
                return listeners;		
            }
    
            ...
        }
    
  2. Crie um Cluster do Service Fabric no Azure e especifique a porta 80 como uma porta de ponto de extremidade personalizada para o tipo de nó que hospedará o serviço. Se você tiver mais de um tipo de nó, poderá configurar uma restrição de posicionamento no serviço para garantir que ele seja executado apenas no tipo de nó que tenha a porta de ponto de extremidade personalizada aberta.

    Abrir uma porta em um tipo de nó

  3. Depois que o cluster tiver sido criado, configure o Balanceador de Carga do Azure no Grupo de Recursos do cluster para encaminhar o tráfego na porta 80. Ao criar um cluster por meio do portal do Azure, isso é configurado automaticamente para cada porta de ponto de extremidade personalizada que foi configurada.

    Captura de tela que destaca o campo Porta de back-end em Regras de balanceamento de carga.

  4. O Balanceador de Carga do Azure usa uma sonda para determinar se o tráfego deve ou não ser enviado para um nó específico. A sonda verifica periodicamente um ponto de extremidade em cada nó para determinar se o nó está respondendo ou não. Se o teste não receber uma resposta após um número configurado de vezes, o balanceador de carga para de enviar tráfego para esse nó. Ao criar um cluster por meio do portal do Azure, uma sonda é configurada automaticamente para cada porta de ponto de extremidade personalizada que foi configurada.

    Encaminhar tráfego no Azure Load Balancer

É importante lembrar que o Balanceador de Carga do Azure e a sonda só sabem sobre os nós, não sobre os serviços em execução nos nós. O Balanceador de Carga do Azure sempre enviará tráfego para nós que respondem à sonda, portanto, é preciso ter cuidado para garantir que os serviços estejam disponíveis nos nós que são capazes de responder à sonda.

Serviços confiáveis: opções de API de comunicação integradas

A estrutura de Serviços Confiáveis vem com várias opções de comunicação pré-criadas. A decisão sobre qual funcionará melhor para você depende da escolha do modelo de programação, da estrutura de comunicação e da linguagem de programação na qual seus serviços estão escritos.

  • Nenhum protocolo específico: Se você não tem uma escolha específica de estrutura de comunicação, mas deseja colocar algo em funcionamento rapidamente, então a opção ideal para você é a comunicação remota de serviços, que permite chamadas de procedimento remoto fortemente tipadas para Serviços Confiáveis e Atores Confiáveis. Esta é a maneira mais fácil e rápida de começar com a comunicação de serviço. A comunicação remota de serviço lida com a resolução de endereços de serviço, conexão, repetição e tratamento de erros. Isso está disponível para aplicativos C# e Java.
  • HTTP: Para comunicação independente de idioma, o HTTP fornece uma escolha padrão do setor com ferramentas e servidores HTTP disponíveis em muitos idiomas diferentes, todos suportados pelo Service Fabric. Os serviços podem usar qualquer pilha HTTP disponível, incluindo ASP.NET API Web para aplicativos C#. Os clientes escritos em C# podem aproveitar as classes andServicePartitionClient, enquanto para ICommunicationClient Java, use as CommunicationClient classes e FabricServicePartitionClient para resolução de serviços, conexões HTTP e loops de repetição.
  • WCF: Se você tiver código existente que usa WCF como sua estrutura de comunicação, então você pode usar o WcfCommunicationListener para o lado do servidor e WcfCommunicationClient classes ServicePartitionClient e para o cliente. No entanto, isso só está disponível para aplicativos C# em clusters baseados no Windows. Para obter mais detalhes, consulte este artigo sobre a implementação baseada em WCF da pilha de comunicação.

Usando protocolos personalizados e outras estruturas de comunicação

Os serviços podem usar qualquer protocolo ou estrutura para comunicação, seja um protocolo binário personalizado sobre soquetes TCP ou streaming de eventos por meio dos Hubs de Eventos do Azure ou do Hub IoT do Azure. O Service Fabric fornece APIs de comunicação nas quais você pode conectar sua pilha de comunicação, enquanto todo o trabalho para descobrir e se conectar é abstraído de você. Consulte este artigo sobre o modelo de comunicação do Serviço Confiável para obter mais detalhes.

Próximos passos

Saiba mais sobre os conceitos e APIs disponíveis no modelo de comunicação de Serviços Confiáveis e, em seguida, comece rapidamente com a comunicação remota de serviços ou aprofunde-se para aprender a escrever um ouvinte de comunicação usando a API da Web com o autohost OWIN.