Ativar a comunicação para instâncias de função no Azure Serviços Cloud (clássico)

Importante

Serviços Cloud (clássico) é agora preterido para novos clientes e será descontinuado a 31 de agosto de 2024 para todos os clientes. As novas implementações devem utilizar o novo modelo de implementação baseado em Resource Manager do Azure Serviços Cloud (suporte alargado).

As funções de serviço cloud comunicam através de ligações internas e externas. As ligações externas são denominadas pontos finais de entrada , enquanto as ligações internas são denominadas pontos finais internos. Este tópico descreve como modificar a definição de serviço para criar pontos finais.

Ponto final de entrada

O ponto final de entrada é utilizado quando pretende expor uma porta no exterior. Especifique o tipo de protocolo e a porta do ponto final que, em seguida, se aplica às portas externas e internas do ponto final. Se quiser, pode especificar uma porta interna diferente para o ponto final com o atributo localPort .

O ponto final de entrada pode utilizar os seguintes protocolos: http, https, tcp, udp.

Para criar um ponto final de entrada, adicione o elemento subordinado InputEndpoint ao elemento Pontos finais de uma função Web ou de trabalho.

<Endpoints>
  <InputEndpoint name="StandardWeb" protocol="http" port="80" localPort="80" />
</Endpoints> 

Ponto final de entrada da instância

Os pontos finais de entrada de instâncias são semelhantes aos pontos finais de entrada, mas permitem mapear portas específicas destinadas ao público para cada instância de função individual através do reencaminhamento de portas no balanceador de carga. Pode especificar uma única porta com acesso público ou um intervalo de portas.

O ponto final de entrada da instância só pode utilizar tcp ou udp como o protocolo.

Para criar um ponto final de entrada de instância, adicione o elemento subordinado InstanceInputEndpoint ao elemento Pontos finais de uma função Web ou de trabalho.

<Endpoints>
  <InstanceInputEndpoint name="Endpoint2" protocol="tcp" localPort="10100">
    <AllocatePublicPortFrom>
      <FixedPortRange max="10109" min="10105" />
    </AllocatePublicPortFrom>
  </InstanceInputEndpoint>
</Endpoints>

Ponto final interno

Os pontos finais internos estão disponíveis para comunicação de instância a instância. A porta é opcional e, se omitida, é atribuída uma porta dinâmica ao ponto final. Pode utilizar um intervalo de portas. Existe um limite de cinco pontos finais internos por função.

O ponto final interno pode utilizar os seguintes protocolos: http, tcp, udp, qualquer.

Para criar um ponto final de entrada interno, adicione o elemento subordinado InternalEndpoint ao elemento Pontos finais de uma função Web ou de trabalho.

<Endpoints>
  <InternalEndpoint name="Endpoint3" protocol="any" port="8999" />
</Endpoints> 

Também pode utilizar um intervalo de portas.

<Endpoints>
  <InternalEndpoint name="Endpoint3" protocol="any">
    <FixedPortRange max="8999" min="8995" />
  </InternalEndpoint>
</Endpoints>

Funções de trabalho vs. Funções Web

Existe uma pequena diferença nos pontos finais ao trabalhar com funções de trabalho e Web. A função Web tem de ter, no mínimo, um único ponto final de entrada com o protocolo HTTP .

<Endpoints>
  <InputEndpoint name="StandardWeb" protocol="http" port="80" localPort="80" />
  <!-- more endpoints may be declared after the first InputEndPoint -->
</Endpoints>

Utilizar o SDK .NET para aceder a um ponto final

A Biblioteca Gerida do Azure fornece métodos para que as instâncias de função comuniquem no runtime. A partir do código em execução numa instância de função, pode obter informações sobre a existência de outras instâncias de função e os respetivos pontos finais, bem como informações sobre a instância de função atual.

Nota

Só pode obter informações sobre instâncias de função em execução no seu serviço cloud e que definem pelo menos um ponto final interno. Não pode obter dados sobre instâncias de função em execução num serviço diferente.

Pode utilizar a propriedade Instâncias para obter instâncias de uma função. Primeiro, utilize a CurrentRoleInstance para devolver uma referência à instância de função atual e, em seguida, utilize a propriedade Função para devolver uma referência à própria função.

Quando se liga a uma instância de função programaticamente através do SDK .NET, é relativamente fácil aceder às informações do ponto final. Por exemplo, depois de já ter ligado a um ambiente de função específico, pode obter a porta de um ponto final específico com este código:

int port = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["StandardWeb"].IPEndpoint.Port;

A propriedade Instâncias devolve uma coleção de objetos RoleInstance . Esta coleção contém sempre a instância atual. Se a função não definir um ponto final interno, a coleção inclui a instância atual, mas nenhuma outra instância. O número de instâncias de função na coleção será sempre 1 no caso de nenhum ponto final interno ser definido para a função. Se a função definir um ponto final interno, as instâncias serão detetáveis no runtime e o número de instâncias na coleção corresponderá ao número de instâncias especificadas para a função no ficheiro de configuração do serviço.

Nota

A Biblioteca Gerida do Azure não fornece um meio de determinar o estado de funcionamento de outras instâncias de função, mas pode implementar essas avaliações de estado de funcionamento se o seu serviço precisar desta funcionalidade. Pode utilizar Diagnóstico do Azure para obter informações sobre a execução de instâncias de função.

Para determinar o número de porta de um ponto final interno numa instância de função, pode utilizar a InstanceEndpoints propriedade para devolver um objeto dicionário que contém nomes de pontos finais e respetivos endereços IP e portas correspondentes. A IPEndpoint propriedade devolve o endereço IP e a porta de um ponto final especificado. A PublicIPEndpoint propriedade devolve a porta para um ponto final com balanceamento de carga. A parte do endereço IP da PublicIPEndpoint propriedade não é utilizada.

Eis um exemplo que itera instâncias de função.

foreach (RoleInstance roleInst in RoleEnvironment.CurrentRoleInstance.Role.Instances)
{
    Trace.WriteLine("Instance ID: " + roleInst.Id);
    foreach (RoleInstanceEndpoint roleInstEndpoint in roleInst.InstanceEndpoints.Values)
    {
        Trace.WriteLine("Instance endpoint IP address and port: " + roleInstEndpoint.IPEndpoint);
    }
}

Eis um exemplo de uma função de trabalho que coloca o ponto final exposto através da definição do serviço e começa a escutar ligações.

Aviso

Este código só funcionará para um serviço implementado. Ao executar no Emulador de Computação do Azure, os elementos de configuração do serviço que criam pontos finais de porta direta (elementos instanceInputEndpoint ) são ignorados.

using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;

namespace WorkerRole1
{
  public class WorkerRole : RoleEntryPoint
  {
    public override void Run()
    {
      try
      {
        // Initialize method-wide variables
        var epName = "Endpoint1";
        var roleInstance = RoleEnvironment.CurrentRoleInstance;

        // Identify direct communication port
        var myPublicEp = roleInstance.InstanceEndpoints[epName].PublicIPEndpoint;
        Trace.TraceInformation("IP:{0}, Port:{1}", myPublicEp.Address, myPublicEp.Port);

        // Identify public endpoint
        var myInternalEp = roleInstance.InstanceEndpoints[epName].IPEndpoint;

        // Create socket listener
        var listener = new Socket(
          myInternalEp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

        // Bind socket listener to internal endpoint and listen
        listener.Bind(myInternalEp);
        listener.Listen(10);
        Trace.TraceInformation("Listening on IP:{0},Port: {1}",
          myInternalEp.Address, myInternalEp.Port);

        while (true)
        {
          // Block the thread and wait for a client request
          Socket handler = listener.Accept();
          Trace.TraceInformation("Client request received.");

          // Define body of socket handler
          var handlerThread = new Thread(
            new ParameterizedThreadStart(h =>
            {
              var socket = h as Socket;
              Trace.TraceInformation("Local:{0} Remote{1}",
                socket.LocalEndPoint, socket.RemoteEndPoint);

              // Shut down and close socket
              socket.Shutdown(SocketShutdown.Both);
              socket.Close();
            }
          ));

          // Start socket handler on new thread
          handlerThread.Start(handler);
        }
      }
      catch (Exception e)
      {
        Trace.TraceError("Caught exception in run. Details: {0}", e);
      }
    }

    public override bool OnStart()
    {
      // Set the maximum number of concurrent connections 
      ServicePointManager.DefaultConnectionLimit = 12;

      // For information on handling configuration changes
      // see the MSDN topic at https://go.microsoft.com/fwlink/?LinkId=166357.
      return base.OnStart();
    }
  }
}

Regras de tráfego de rede para controlar a comunicação de funções

Depois de definir pontos finais internos, pode adicionar regras de tráfego de rede (com base nos pontos finais que criou) para controlar a forma como as instâncias de função podem comunicar entre si. O diagrama seguinte mostra alguns cenários comuns para controlar a comunicação de funções:

Cenários de Regras de Tráfego de Rede Cenários

O seguinte exemplo de código mostra definições de função para as funções apresentadas no diagrama anterior. Cada definição de função inclui, pelo menos, um ponto final interno definido:

<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole1" vmsize="Medium">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="HttpIn" endpointName="HttpIn" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
      <InternalEndpoint name="InternalTCP1" protocol="tcp" />
    </Endpoints>
  </WebRole>
  <WorkerRole name="WorkerRole1">
    <Endpoints>
      <InternalEndpoint name="InternalTCP2" protocol="tcp" />
    </Endpoints>
  </WorkerRole>
  <WorkerRole name="WorkerRole2">
    <Endpoints>
      <InternalEndpoint name="InternalTCP3" protocol="tcp" />
      <InternalEndpoint name="InternalTCP4" protocol="tcp" />
    </Endpoints>
  </WorkerRole>
</ServiceDefinition>

Nota

A restrição da comunicação entre funções pode ocorrer com pontos finais internos de portas fixas e atribuídas automaticamente.

Por predefinição, após a definição de um ponto final interno, a comunicação pode fluir de qualquer função para o ponto final interno de uma função sem quaisquer restrições. Para restringir a comunicação, tem de adicionar um elemento NetworkTrafficRules ao elemento ServiceDefinition no ficheiro de definição de serviço.

Cenário 1

Permitir apenas o tráfego de rede de WebRole1 para WorkerRole1.

<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo>
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP2" roleName="WorkerRole1"/>
      </Destinations>
      <AllowAllTraffic/>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WebRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
</ServiceDefinition>

Cenário 2

Só permite o tráfego de rede de WebRole1 para WorkerRole1 e WorkerRole2.

<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo>
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP2" roleName="WorkerRole1"/>
        <RoleEndpoint endpointName="InternalTCP3" roleName="WorkerRole2"/>
      </Destinations>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WebRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
</ServiceDefinition>

Cenário 3

Só permite o tráfego de rede de WebRole1 para WorkerRole1 e WorkerRole1 para WorkerRole2.

<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo>
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP2" roleName="WorkerRole1"/>
      </Destinations>
      <AllowAllTraffic/>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WebRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo>
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP3" roleName="WorkerRole2"/>
      </Destinations>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WorkerRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
</ServiceDefinition>

Cenário 4

Só permite o tráfego de rede de WebRole1 a WorkerRole1, WebRole1 a WorkerRole2 e WorkerRole1 a WorkerRole2.

<ServiceDefinition name="MyService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo>
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP2" roleName="WorkerRole1"/>
      </Destinations>
      <AllowAllTraffic/>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WebRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo >
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP3" roleName="WorkerRole2"/>
      </Destinations>
      <AllowAllTraffic/>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WorkerRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
  <NetworkTrafficRules>
    <OnlyAllowTrafficTo >
      <Destinations>
        <RoleEndpoint endpointName="InternalTCP4" roleName="WorkerRole2"/>
      </Destinations>
      <AllowAllTraffic/>
      <WhenSource matches="AnyRule">
        <FromRole roleName="WebRole1"/>
      </WhenSource>
    </OnlyAllowTrafficTo>
  </NetworkTrafficRules>
</ServiceDefinition>

Pode encontrar aqui uma referência de esquema XML para os elementos utilizados acima.

Passos seguintes

Leia mais sobre o modelo do Serviço Cloud.