Comunicação com Worker Roles via Endpoints

Olá pessoal, tudo certo?

Esses últimos meses, participei de alguns projetos na plataforma Azure. Alguns cenários foram muito comuns, como o desenho abaixo, onde temos interfaces Web Roles com ASP.NET MVC e processos implementados em Worker Roles. A comunicação entre esses processos vem sendo feita via filas ou tabelas e blobs para usos gerais, dependendo do projeto.

image

Outro mecanismo disponível para comunicação com Web Roles e Worker Roles é o Endpoint. A atualização de Fevereiro do Training Kit oferece alguns exercícios sobre a comunicação com Worker Roles, veja:

Worker Role Communication
Ref.: https://msdn.microsoft.com/en-us/gg457887 

Podemos criar Endpoints para comunicação via TCP, HTTP e HTTPS. Em seu projeto Worker Role, entre na página de propriedades e na aba Endpoints, você encontrará a lista de Endpoints em uso. Através do botão Add Endpoint, você poderá adicionar suas novas entradas.

image

Veja o exemplo de Worker Role completo abaixo. Esse código utiliza um Endpoint de nome “TelnetServiceEndpoint” para implementar o tratamento de uma conexão Telnet Client. Através desse canal, podemos obter informações sobre o funcionamento do Worker, por exemplo.

    1: using System;
    2: using System.Collections.Generic;
    3: using System.Diagnostics;
    4: using System.Linq;
    5: using System.Net;
    6: using System.Threading;
    7: using Microsoft.WindowsAzure;
    8: using Microsoft.WindowsAzure.Diagnostics;
    9: using Microsoft.WindowsAzure.ServiceRuntime;
   10: using Microsoft.WindowsAzure.StorageClient;
   11:  
   12: using System.IO;
   13: using System.Net.Sockets;
   14:  
   15: namespace HelloWorkerRole
   16: {
   17:     public class WorkerRole : RoleEntryPoint
   18:     {
   19:         private readonly AutoResetEvent _connectionWait = new AutoResetEvent(false);
   20:  
   21:         /// <summary>
   22:         /// 
   23:         /// </summary>
   24:         /// <returns></returns>
   25:         public override bool OnStart()
   26:         {
   27:             ServicePointManager.DefaultConnectionLimit = 12;
   28:             DiagnosticMonitor.Start("DiagnosticsConnectionString");
   29:             RoleEnvironment.Changing += RoleEnvironmentChanging;
   30:             return base.OnStart();
   31:         }
   32:  
   33:  
   34:         /// <summary>
   35:         /// 
   36:         /// </summary>
   37:         public override void Run()
   38:         {
   39:             Trace.WriteLine("Starting Telnet Service...", "Information");
   40:             TcpListener listener;
   41:             try
   42:             {
   43:                 listener = new TcpListener(
   44:                     RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["TelnetServiceEndpoint"].IPEndpoint) { ExclusiveAddressUse = false };
   45:                 listener.Start();
   46:  
   47:                 Trace.WriteLine("Started Telnet Service.", "Information");
   48:             }
   49:             catch (SocketException se)
   50:             {
   51:                 Trace.Write("Telnet Service could not start.", "Error");
   52:                 return;
   53:             }
   54:             while (true)
   55:             {
   56:                 listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
   57:                 _connectionWait.WaitOne();
   58:             }
   59:         }
   60:  
   61:  
   62:         /// <summary>
   63:         /// 
   64:         /// </summary>
   65:         /// <param name="clientId"></param>
   66:         /// <param name="writer"></param>
   67:         private static void WriteRoleInformation(Guid clientId, StreamWriter writer)
   68:         {
   69:             writer.WriteLine("--- Current Client ID, Date & Time ----");
   70:             writer.WriteLine("Current date: " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
   71:             writer.WriteLine("Connection ID: " + clientId);
   72:             writer.WriteLine();
   73:  
   74:             writer.WriteLine("--- Current Role Instance Information ----");
   75:             writer.WriteLine("Role ID: " + RoleEnvironment.CurrentRoleInstance.Id);
   76:             writer.WriteLine("Role Count: " + RoleEnvironment.Roles.Count);
   77:             writer.WriteLine("Deployment ID: " + RoleEnvironment.DeploymentId);
   78:             writer.WriteLine();
   79:  
   80:             writer.WriteLine("--- Instance Endpoints ----");
   81:  
   82:             foreach (KeyValuePair<string, RoleInstanceEndpoint> instanceEndpoint in RoleEnvironment.CurrentRoleInstance.InstanceEndpoints)
   83:             {
   84:                 writer.WriteLine("Instance Endpoint Key: " + instanceEndpoint.Key);
   85:  
   86:                 RoleInstanceEndpoint roleInstanceEndpoint = instanceEndpoint.Value;
   87:  
   88:                 writer.WriteLine("Instance Endpoint IP: " + roleInstanceEndpoint.IPEndpoint);
   89:                 writer.WriteLine("Instance Endpoint Protocol: " + roleInstanceEndpoint.Protocol);
   90:                 writer.WriteLine("Instance Endpoint Type: " + roleInstanceEndpoint);
   91:                 writer.WriteLine();
   92:             }
   93:         }
   94:  
   95:  
   96:         /// <summary>
   97:         /// 
   98:         /// </summary>
   99:         /// <param name="result"></param>
  100:         private void HandleAsyncConnection(IAsyncResult result)
  101:         {
  102:             var listener = (TcpListener)result.AsyncState;
  103:             var client = listener.EndAcceptTcpClient(result);
  104:             _connectionWait.Set();
  105:  
  106:             var clientId = Guid.NewGuid();
  107:             Trace.WriteLine("Connection ID: " + clientId, "Information");
  108:  
  109:             var netStream = client.GetStream();
  110:             var reader = new StreamReader(netStream);
  111:             var writer = new StreamWriter(netStream);
  112:             writer.AutoFlush = true;
  113:  
  114:             var input = string.Empty;
  115:             while (input != "3")
  116:             {
  117:                 writer.WriteLine(" 1) Display Worker Role Information");
  118:                 writer.WriteLine(" 2) Recycle");
  119:                 writer.WriteLine(" 3) Quit");
  120:                 writer.Write("Enter your choice: ");
  121:  
  122:                 input = reader.ReadLine();
  123:                 writer.WriteLine();
  124:  
  125:                 switch (input)
  126:                 {
  127:                     case "1":
  128:                         WriteRoleInformation(clientId, writer);
  129:                         break;
  130:                     case "2":
  131:                         RoleEnvironment.RequestRecycle();
  132:                         break;
  133:                 }
  134:  
  135:                 writer.WriteLine();
  136:             }
  137:  
  138:             client.Close();
  139:         }
  140:  
  141:  
  142:         /// <summary>
  143:         /// 
  144:         /// </summary>
  145:         /// <param name="sender"></param>
  146:         /// <param name="e"></param>
  147:         private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
  148:         {
  149:             if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
  150:             {
  151:                 e.Cancel = true;
  152:             }
  153:         }
  154:  
  155:     }
  156: }

Para o Endpoint TCP, veja a propriedade da Worker Role, abaixo:

image

Retirei o código acima a partir do artigo a seguir:

Gritty Technical Info on Windows Azure Worker Roles
Ref.: https://compositecode.com/2011/01/17/gritty-technical-info-on-windows-azure-worker-roles/

Vale conferir! Boa leitura!

Por enquanto é só! Até o próximo post :)

Waldemir.