Consumiendo InternalEndPoint–WCF en Azure

Hola a todos.

Después de crear un wcf en Azure y de consumir un EndPoint interno que viaja por tcp, ahora procedemos a consumir dicho EndPoint interno desde una aplicación en un WebRole.

Para revisar el post anterior http://geeks.ms/rduarte/2016/03/13/comunicacin-interna-wcf-en-azure/

Lo primero es agregar una solución web de tipo Web Role, puede ser una aplicación tipo web forms o mvc.

image

Dicha aplicación le colocamos un EndPoint de entrada, para poder acceder a ella.

image

Creamos un botón con la siguiente funcionalidad.

[sourcecode language='csharp'  padlinenumbers='true' htmlscript='false']
protected void Button1_Click(object sender, EventArgs e)
		{
			try
			{
				var factory = new ChannelFactory<WcfWorker.IWorker>(new NetTcpBinding(SecurityMode.None));
				var current = RoleEnvironment.CurrentRoleInstance;
				var channel = factory.CreateChannel(GetRandomEndpoint());
				Label1.Text = channel.Say("Hola");
				
			}
			catch (Exception ex)
			{

				Label1.Text = ex.Message;
			}

			
		}
		private EndpointAddress GetRandomEndpoint()
		{
			var endpoints = RoleEnvironment.Roles["WcfWorker"].Instances.Select(i => i.InstanceEndpoints["InternalRest"].IPEndpoint).ToArray();
			var r = new Random(DateTime.Now.Millisecond);
			return new EndpointAddress(string.Format("net.tcp://{0}/InternalRest", endpoints[r.Next(endpoints.Count() - 1)]));
		}
[/sourcecode]

Para esta parte es importante saber que servicio es el que esta expuesto para uso interno. Revisen CreateServiceHost();

Ahora publicamos y probamos.

image

Bueno, espero que sea de utilidad este post.

Sl2

Romny

Comunicación Interna – WCF en Azure

Hola a todos.

Muchas veces necesitamos hacer aplicaciones orientadas a servicios y además que estas se integren con otros sistemas de servicios como soa.

Para estos casos un simple rest no es factible debido a que se montara en Azure. Básicamente lo que se quiere es exponer un servicio wcf que ira por http pero la comunicación interna deberá ser por tcp por aquello de que tcp nos evita como dos capas del modelo osi.

Requerimientos

    Microsoft Azure SDK for .NET – 2.8.2

    Cuenta de Azure

    Creamos un proyecto Azure WorkerRole

    image

    image

    Después de creado el proyecto, damos en propiedades del role WcfWorker, vamos a extremos y añadimos los siguientes puntos.

    image

    Agregamos las siguientes referencias.

    image

    Agregamos una interface IService

    image

Agregamos una interface IWorker

image

Agregamos una clase Service que implemente las interfaces creadas.

image

Abrimos la clase WorkerRole.cs, creamos variables ServiceHost y añadimos el método CreateServiceHost para alojar su servicio WCF REST.

[sourcecode language='csharp'  padlinenumbers='true']
//Static channel factory for inter-role communication.
		private static ChannelFactory<IWorker> factory;

		//Service host varible.
		private ServiceHost serviceHost;


		private void CreateServiceHost()
		{
			//Url of service.
			Uri httpUri = new Uri(String.Format("http://{0}/{1}", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Rest"].IPEndpoint.ToString(), "Rest"));

			//Assign url to service host.
			serviceHost = new ServiceHost(typeof(Service), httpUri);

			//Adding endpoint for REST service.
			ServiceEndpoint ep = serviceHost.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");

			//Adding behavior for REST service.
			ep.Behaviors.Add(new WebHttpBehavior() { HelpEnabled = true });


			//NetTcpBinding with no security.
			NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);

			//Define an internal endpoint for inter-role traffic.
			RoleInstanceEndpoint internalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["InternalRest"];

			//Add internal endpoint.
			this.serviceHost.AddServiceEndpoint(typeof(IWorker), binding, String.Format("net.tcp://{0}/InternalRest", internalEndPoint.IPEndpoint));

			//Create channel factory for inter-role communication.
			WorkerRole.factory = new ChannelFactory<IWorker>(binding);

			//Open the service host  to start listening for messages.
			serviceHost.Open();

		}
[/sourcecode]

Creamos el método NotifiyAllNodes para notificar en las instancias.

[sourcecode language='csharp' ]
internal static void NotifyAllNodes(string message)
        {
            //Get the role id.
            string roleId = RoleEnvironment.CurrentRoleInstance.Id;


                //Gets a RoleInstance object representing the role instance in which this code is currently executing.
                var current = RoleEnvironment.CurrentRoleInstance;

                //Get all instances except the current.
                var endPoints = current.Role.Instances
                                .Where(instance => instance != current)
                                .Select(instance => instance.InstanceEndpoints["InternalRest"]);
                foreach (var ep in endPoints)
                {
                    //Internal endpoint address.
                    EndpointAddress address = new EndpointAddress(String.Format("net.tcp://{0}/InternalRest", ep.IPEndpoint));

                    //Channel for communication.
                    IWorker client = WorkerRole.factory.CreateChannel(address);

                    //Update all the instances.
                    client.UpdateMessage(message, ep.RoleInstance.Id);
                }
         }
[/sourcecode]

Llamar método CreateServiceHost en método OnStart() .

Procedemos a publicar.

image

Cuando publicamos tenemos una exception.

HTTP could not register URL http://+:80/Rest/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).

La solución a este problema es averiguar el puerto que necesita para abrir y dar permiso al rol de trabajo para abrir el puerto apropiado.

Para esto creamos un proyecto de consola.

image

Vinculamos el ejecutable al proyecto WorkerRole y seleccionamos que se copie siempre.

image

En el archivo de definición agregamos las siguientes líneas.

[sourcecode language='xml' ]
<Startup>
			<Task commandLine="PortDetect.exe" executionContext="elevated" taskType="simple">
			</Task>
		</Startup
[/sourcecode]

Volvemos a publicar, Ahora se puede acceder al servicio rest que se aloja (en el puerto 80) en el WorkerRole y internamente se comunica por tcp.

Realizamos una prueba para ver que todo este bien.

image

Bueno, espero que sea de utilidad este post.

Sl2

Romny