Ligar e comunicar com serviços no Service Fabric

No Service Fabric, um serviço é executado algures num cluster do Service Fabric, normalmente distribuído por várias VMs. Pode ser movido de um local para outro, pelo proprietário do serviço ou automaticamente pelo Service Fabric. Os serviços não estão estaticamente ligados a um computador ou endereço específico.

Uma aplicação do Service Fabric é geralmente composta por muitos serviços diferentes, onde cada serviço executa uma tarefa especializada. Estes serviços podem comunicar entre si para formar uma função completa, como compor diferentes partes de uma aplicação Web. Também existem aplicações cliente que se ligam e comunicam com serviços. Este documento aborda como configurar a comunicação com e entre os seus serviços no Service Fabric.

Veja esta página para ver um vídeo de formação que também aborda a comunicação do serviço:

Traga o seu próprio protocolo

O Service Fabric ajuda a gerir o ciclo de vida dos seus serviços, mas não tomam decisões sobre o que os seus serviços fazem. Isto inclui comunicação. Quando o seu serviço é aberto pelo Service Fabric, é a oportunidade do seu serviço de configurar um ponto final para pedidos recebidos, utilizando qualquer protocolo ou pilha de comunicação que pretenda. O seu serviço escutará num endereço IP:porta normal através de qualquer esquema de endereçamento, como um URI. Várias réplicas ou instâncias de serviço podem partilhar um processo de anfitrião, caso em que terão de utilizar portas diferentes ou utilizar um mecanismo de partilha de portas, como o controlador de kernel http.sys no Windows. Em ambos os casos, cada instância de serviço ou réplica num processo de anfitrião tem de ser endereçável de forma exclusiva.

pontos finais de serviço

Deteção e resolução de serviços

Num sistema distribuído, os serviços podem passar de um computador para outro ao longo do tempo. Isto pode acontecer por vários motivos, incluindo balanceamento de recursos, atualizações, ativações pós-falha ou aumento horizontal. Isto significa que os endereços de ponto final de serviço mudam à medida que o serviço se move para nós com endereços IP diferentes e podem ser abertos em portas diferentes se o serviço utilizar uma porta selecionada dinamicamente.

Distribuição de serviços

O Service Fabric fornece um serviço de deteção e resolução denominado Serviço de Nomenclatura. O Serviço de Nomenclatura mantém uma tabela que mapeia as instâncias de serviço denominadas para os endereços de ponto final que 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 duração do serviço, são apenas os endereços de ponto final que podem ser alterados quando os serviços são movidos. Isto é análogo aos sites que têm URLs constantes, mas onde o endereço IP pode ser alterado. À semelhança do DNS na Web, que resolve os URLs dos sites para endereços IP, o Service Fabric tem uma entidade de registo que mapeia os nomes dos serviços para o respetivo endereço de ponto final.

Diagrama que mostra que o Service Fabric tem uma entidade de registo que mapeia os nomes dos serviços para o respetivo endereço de ponto final.

Resolver e ligar a serviços envolve os seguintes passos executados num ciclo:

  • Resolver: obtenha o ponto final que um serviço publicou a partir do Serviço de Nomenclatura.
  • Ligar: ligue ao serviço através do protocolo que utiliza nesse ponto final.
  • Tentar novamente: uma tentativa de ligaçã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 final foi resolvido. Nesse caso, os passos de resolução e ligação anteriores têm de ser repetidos e este ciclo é repetido até a ligação ser bem-sucedida.

Ligar a outros serviços

Geralmente, os serviços que se ligam entre si dentro de um cluster podem aceder diretamente aos pontos finais de outros serviços porque os nós num cluster estão na mesma rede local. Para facilitar a ligação entre serviços, o Service Fabric fornece serviços adicionais que utilizam o Serviço de Nomenclatura. Um serviço DNS e um serviço de proxy inverso.

Serviço DNS

Uma vez que muitos serviços, especialmente os serviços em contentores, podem ter um nome de URL existente, conseguir resolvê-los com o protocolo DNS padrão (em vez do protocolo do Serviço de Nomenclatura) é muito conveniente, especialmente em cenários de "migração lift-and-shift" da aplicação. Isto é exatamente o que o serviço DNS faz. Permite-lhe mapear nomes DNS para um nome de serviço e, por conseguinte, resolver endereços IP de ponto final.

Conforme mostrado no diagrama seguinte, o serviço DNS, em execução no cluster do Service Fabric, mapeia os nomes DNS para nomes de serviço que, em seguida, são resolvidos pelo Serviço de Nomenclatura para devolver os endereços de ponto final aos quais ligar. O nome DNS do serviço é fornecido no momento da criação.

Diagrama que mostra como o serviço DNS, ao ser executado no cluster do Service Fabric, mapeia os nomes DNS para nomes de serviço que, em seguida, são resolvidos pelo Serviço de Nomenclatura para devolver os endereços de ponto final aos quais ligar.

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

Serviço de proxy inverso

O proxy inverso endereça os serviços no cluster que expõem pontos finais HTTP, incluindo HTTPS. O proxy inverso simplifica consideravelmente a chamada de outros serviços e os respetivos métodos ao ter um formato de URI específico e processa os passos de resolução, ligação e repetição necessários para que um serviço comunique com outro através do Serviço de Nomenclatura. Por outras palavras, oculta o Serviço de Nomenclatura ao chamar outros serviços ao tornar isto tão simples como chamar um URL.

Diagrama que mostra como o proxy inverso endereça os serviços no cluster que expõe pontos finais HTTP, incluindo HTTPS.

Para obter mais detalhes sobre como utilizar o serviço de proxy inverso, veja o artigo Reverse proxy in Azure Service Fabric (Proxy inverso no Azure Service Fabric ).

Ligações de clientes externos

Geralmente, os serviços que se ligam entre si dentro de um cluster podem aceder diretamente aos pontos finais de outros serviços porque os nós num cluster estão na mesma rede local. No entanto, em alguns ambientes, um cluster pode estar atrás de um balanceador de carga que encaminha o tráfego de entrada através de um conjunto limitado de portas. Nestes casos, os serviços ainda podem comunicar entre si e resolver endereços com o Serviço de Nomenclatura, mas têm de ser tomadas medidas adicionais para permitir que os clientes externos se liguem 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 tem de passar pelo balanceador de carga. O balanceador de carga irá reencaminhar automaticamente o tráfego de entrada numa determinada porta para um aleatório que tenha a mesma porta aberta. O Balanceador de Carga do Azure só sabe das portas abertas nos nós, não conhece as portas abertas por serviços individuais.

topologia do Balanceador de Carga do Azure e do Service Fabric

Por exemplo, para aceitar tráfego externo na porta 80, tem de ser configurado o seguinte:

  1. Escreva um serviço que escuta na porta 80. Configure a porta 80 no ServiceManifest.xml do serviço e abra um serviço de escuta no serviço, por exemplo, um servidor Web autoalojado.

    <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 final personalizada para o tipo de nó que irá alojar o serviço. Se tiver mais do que um tipo de nó, pode configurar uma restrição de colocação no serviço para garantir que apenas é executado no tipo de nó que tem a porta de ponto final personalizada aberta.

    Abrir uma porta num tipo de nó

  3. Assim que o cluster tiver sido criado, configure o Balanceador de Carga do Azure no Grupo de Recursos do cluster para reencaminhar o tráfego na porta 80. Ao criar um cluster através do portal do Azure, este é configurado automaticamente para cada porta de ponto final personalizado que foi configurada.

    Captura de ecrã que realça o campo Porta de back-end em Regras de balanceamento de carga.

  4. O Balanceador de Carga do Azure utiliza uma sonda para determinar se deve ou não enviar tráfego para um nó específico. A pesquisa verifica periodicamente um ponto final em cada nó para determinar se o nó está ou não a responder. Se a sonda não receber uma resposta após um número configurado de vezes, o balanceador de carga deixa de enviar tráfego para esse nó. Ao criar um cluster através do portal do Azure, é configurada automaticamente uma sonda para cada porta de ponto final personalizado que foi configurada.

    Reencaminhar tráfego na Balanceador de Carga do Azure

É importante lembrar que o Balanceador de Carga do Azure e a sonda só conhecem os nós e não os serviços em execução nos nós. A Balanceador de Carga do Azure enviará sempre tráfego para os nós que respondem à sonda, pelo que deve ter cuidado para garantir que os serviços estão disponíveis nos nós que conseguem responder à sonda.

Reliable Services: opções da API de comunicação incorporada

A arquitetura reliable Services inclui várias opções de comunicação pré-criadas. A decisão sobre qual irá funcionar melhor depende da escolha do modelo de programação, da arquitetura de comunicação e da linguagem de programação na qual os seus serviços estão escritos.

  • Sem protocolo específico: Se não tiver uma determinada escolha de arquitetura de comunicação, mas quiser começar a trabalhar rapidamente, então a opção ideal para si é a comunicação remota de serviços, o que permite chamadas de procedimento remoto fortemente digitadas para Reliable Services e Reliable Actors. Esta é a forma mais fácil e rápida de começar a utilizar a comunicação do serviço. A comunicação remota do serviço processa a resolução de endereços de serviço, ligação, repetição e processamento de erros. Está disponível para aplicações C# e Java.
  • HTTP: para comunicação entre idiomas e agnósticos, o HTTP fornece uma escolha padrão da indústria com ferramentas e servidores HTTP disponíveis em vários idiomas diferentes, todos suportados pelo Service Fabric. Os serviços podem utilizar qualquer pilha HTTP disponível, incluindo ASP.NET API Web para aplicações C#. Os clientes escritos em C# podem tirar partido das classes eServicePartitionClient, ao passo que, para Java, utilize as CommunicationClient classes e FabricServicePartitionClientpara resolução de serviços, ligações HTTP e repetição de ciclos.ICommunicationClient
  • WCF: se tiver código existente que utiliza o WCF como arquitetura de comunicação, pode utilizar o para o WcfCommunicationListener lado do servidor e WcfCommunicationClientServicePartitionClient as classes para o cliente. No entanto, isto só está disponível para aplicações C# em clusters baseados no Windows. Para obter mais detalhes, veja este artigo sobre a implementação baseada em WCF da pilha de comunicação.

Utilizar protocolos personalizados e outras arquiteturas de comunicação

Os serviços podem utilizar qualquer protocolo ou arquitetura para comunicação, seja um protocolo binário personalizado através de sockets TCP ou eventos de transmissão em fluxo através de Hubs de Eventos do Azure ou Hub IoT do Azure. O Service Fabric fornece APIs de comunicação às quais pode ligar a pilha de comunicação, enquanto todo o trabalho para detetar e ligar é abstrato de si. Veja este artigo sobre o modelo de comunicação Reliable Service para obter mais detalhes.

Passos seguintes

Saiba mais sobre os conceitos e APIs disponíveis no modelo de comunicação Reliable Services e, em seguida, comece rapidamente com a comunicação remota do serviço ou aprenda a escrever um serviço de escuta de comunicação com a API Web com o autoalojamento OWIN.