public static void SendClientInput(String msg, String id)
        {
            var role = RoleEnvironment.Roles["MessageProcessing"];
            Trace.WriteLine("Number of Instances found: " + role.Instances.Count, "Information");

            /*
             * ALGORITMO LOAD BALANCER
             * instance - La instancia que se seleccionara como resultado final del algoritmo LB
             * idles, lows, normals listas para categorizar los nodos segun utilizacion de CPU y memoria mediante el algoritmo de LB
             * Los nodos categorizados como high no se almacenan porque seran automaticamente descartados por el algoritmo
             * Se utiliza la estructura EntradaLoadBalancer para almacenar informacion relevante para el algoritmo
             * L, H - constantes para determinar el umbral de carga de utilizacion de CPU (definidas arriba)
             * */
            RoleInstance instance = role.Instances.FirstOrDefault<RoleInstance>();
            List<LoadBalancerEntry> nodos = new List<LoadBalancerEntry>();
            List<LoadBalancerEntry> idles = new List<LoadBalancerEntry>();
            List<LoadBalancerEntry> lows = new List<LoadBalancerEntry>();
            List<LoadBalancerEntry> normals = new List<LoadBalancerEntry>();

            //Recoleccion de metricas de utilizacion de CPU y memoria para cada instancia
            if (role.Instances.Count > 0)
            {
                double sumCpu = 0;
                foreach (var i in role.Instances)
                {
                    double cpu = LoadBalancerCommons.obtenerMetricas(i.Id, "MessageProcessing", true);
                    double memory = LoadBalancerCommons.obtenerMetricas(i.Id, "MessageProcessing", false);

                    LoadBalancerEntry entrada = new LoadBalancerEntry();
                    entrada.cpuUsage = cpu;
                    entrada.memoryUsage = memory;
                    entrada.rol = i;
                    nodos.Add(entrada);

                    sumCpu += cpu;
                }

                double avCPUClusterUsage = sumCpu / (role.Instances.Count);
                double lUmbral = LoadBalancerCommons.L * avCPUClusterUsage;
                double hUmbral = LoadBalancerCommons.H * avCPUClusterUsage;

                /* Agrupamos los nodos en categorias dependiendo de la intensidad de uso de CPU y Memoria
                *  Si tienen alto uso de Cpu y memoria simultaneamente son automaticamente descartados por el algoritmo
                */
                foreach (LoadBalancerEntry e in nodos)
                {
                    if (e.cpuUsage <= LoadBalancerCommons.IDLE)
                    {
                        idles.Add(e);
                    }
                    else if (e.cpuUsage <= lUmbral && (!(e.memoryUsage >= LoadBalancerCommons.H_LOADED)))
                    {
                        lows.Add(e);
                    }
                    else if ((!(e.memoryUsage >= LoadBalancerCommons.H_LOADED)) && (!(e.cpuUsage >= hUmbral)))
                    {
                        normals.Add(e);
                    }
                }

                /* ETAPA DE CLASIFICACION
                *  Como los servidores cuentan con Balance de Carga, siempre debe haber al menos uno que no este en la
                *  categoria High, es decir que siempre habra elementos en alguna de las siguientes 3 categorias
                */
                if (idles.Count > 0)
                {
                    instance = idles.First().rol;
                }
                else if (lows.Count > 0)
                {
                    instance = lows.First().rol;
                }
                else if (normals.Count > 0)
                {
                    instance = normals.First().rol;
                }
                Debug.WriteLine("*************************Instancia: "+instance.Id+"************************************");
            }
            //END ALGORITMO LOAD BALANCER

            RoleInstanceEndpoint clientInputServiceHostEndPoint = instance.InstanceEndpoints["ClientInputServiceEndPoint"];

            NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, false);

            EndpointAddress myEndpoint = new EndpointAddress(
                String.Format("net.tcp://{0}/ClientInputService", clientInputServiceHostEndPoint.IPEndpoint)
                );

            try
            {
                ChannelFactory<InterroleCommons.IReceiveMessageFromClient> myChanFac = new ChannelFactory<InterroleCommons.IReceiveMessageFromClient>(binding, myEndpoint);
                InterroleCommons.IReceiveMessageFromClient myClient = myChanFac.CreateChannel();
                myClient.ReceiveClientInputMessage(new InterroleCommons.ClientInputMessage() { idUsuario = id, message = msg });
            }
            catch (Exception ex)
            {
                Trace.WriteLine("An error occured trying to notify the instances: " + ex.Message, "Warning");
            }
        }
        private void CrearMDL(ClientInputMessage e, Int64 subid, Double[] valores, SimulacionParameters parametros,
            Generator generatorMDL)
        {
            try
            {
                MDLParametros mdlParametros = new MDLParametros();
                mdlParametros.iteraciones = parametros.init.iterations;
                mdlParametros.timeStep = parametros.init.timeStep;
                mdlParametros.box = new BoxParametros();
                mdlParametros.box.nombre = parametros.geometria.box.nombre;
                mdlParametros.box.aspectRatio = parametros.geometria.box.aspectRatio;
                LinkedList<String> cornerList = new LinkedList<String>();
                foreach (var corner in parametros.geometria.box.corners)
                {
                    String cornerString = "[" + String.Join(",", corner) + "]";
                    cornerList.AddLast(cornerString);
                }
                mdlParametros.box.corners = String.Join(" , ", cornerList);
                mdlParametros.moleculas = new DefMoleculas();
                mdlParametros.moleculas.defineMoleculas = new LinkedList<MoleculasParametros>();
                mdlParametros.moleculas.nameList = parametros.moleculas.nameList;

                foreach (var molecula in parametros.moleculas.defineMoleculas)
                {
                    MoleculasParametros mol = new MoleculasParametros();
                    mol.nombre = molecula.nombre;
                    mol.cantidad = molecula.cantidad;
                    mol.diffusion2D = molecula.difusion2D;
                    mol.diffusion3D = molecula.difusion3D;
                    mdlParametros.moleculas.defineMoleculas.AddLast(mol);
                }

                mdlParametros.reacciones = new LinkedList<ReacParametros>();
                var numReaccion = 0;
                foreach (var reaccion in parametros.reacciones)
                {
                    ReacParametros reac = new ReacParametros();
                    reac.reaccion = reaccion.reaccion;
                    reac.rate = valores[numReaccion];
                    reac.nombre = reaccion.nombre;
                    mdlParametros.reacciones.AddLast(reac);
                    numReaccion++;
                }
                mdlParametros.hayReacciones = mdlParametros.reacciones.Count > 0;

                string fernetMode = parametros.fernet.mode;

                Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");//("en-US");
                string result = generatorMDL.Render(mdlParametros);

                // Se obtiene una referencia al blob (que no existia previamente)
                CloudBlockBlob blockBlob = container.GetBlockBlobReference("Scene.main.mdl-" + fernetMode + "-" + e.idUsuario + "." + subid);

                // Se guarda el mdl en blob
                blockBlob.UploadText(result);

                //enviar mensaje al JobCreation Role
                var role = RoleEnvironment.Roles["JobCreation"];
                Trace.WriteLine("Number of JobCreation Instances found: " + role.Instances.Count, "Information");

                RoleInstance instance = role.Instances.FirstOrDefault<RoleInstance>();

                /*
             * ALGORITMO LOAD BALANCER
             * instance - La instancia que se seleccionara como resultado final del algoritmo LB
             * idles, lows, normals listas para categorizar los nodos segun utilizacion de CPU y memoria mediante el algoritmo de LB
             * Los nodos categorizados como high no se almacenan porque seran automaticamente descartados por el algoritmo
             * Se utiliza la estructura EntradaLoadBalancer para almacenar informacion relevante para el algoritmo
             * L, H - constantes para determinar el umbral de carga de utilizacion de CPU (definidas arriba)
             * */
                DateTime StartDate = DateTime.Now;

                List<LoadBalancerEntry> nodos = new List<LoadBalancerEntry>();
                List<LoadBalancerEntry> idles = new List<LoadBalancerEntry>();
                List<LoadBalancerEntry> lows = new List<LoadBalancerEntry>();
                List<LoadBalancerEntry> normals = new List<LoadBalancerEntry>();
                Double cpuUsageInstance = 0;

                //Recoleccion de metricas de utilizacion de CPU y memoria para cada instancia
                if (role.Instances.Count > 0)
                {
                    double sumCpu = 0;
                    LoadBalancerCommons lbo = new LoadBalancerCommons();
                    foreach (var i in role.Instances)
                    {
                        double cpu = LoadBalancerCommons.obtenerMetricas(i.Id, "JobCreation", true);
                        double memory = LoadBalancerCommons.obtenerMetricas(i.Id, "JobCreation", false);

                        LoadBalancerEntry entrada = new LoadBalancerEntry();
                        entrada.cpuUsage = cpu;
                        entrada.memoryUsage = memory;
                        entrada.rol = i;
                        nodos.Add(entrada);

                        sumCpu += cpu;
                    }

                    double avCPUClusterUsage = sumCpu / (role.Instances.Count);
                    double lUmbral = LoadBalancerCommons.L * avCPUClusterUsage;
                    double hUmbral = LoadBalancerCommons.H * avCPUClusterUsage;

                    /* Agrupamos los nodos en categorias dependiendo de la intensidad de uso de CPU y Memoria
                    *  Si tienen alto uso de Cpu y memoria simultaneamente son automaticamente descartados por el algoritmo
                    */
                    foreach (LoadBalancerEntry entry in nodos)
                    {
                        if (entry.cpuUsage <= LoadBalancerCommons.IDLE)
                        {
                            idles.Add(entry);
                        }
                        else if (entry.cpuUsage <= lUmbral && (!(entry.memoryUsage >= LoadBalancerCommons.H_LOADED)))
                        {
                            lows.Add(entry);
                        }
                        else if ((!(entry.memoryUsage >= LoadBalancerCommons.H_LOADED)) && (!(entry.cpuUsage >= hUmbral)))
                        {
                            normals.Add(entry);
                        }
                    }

                    /* ETAPA DE CLASIFICACION
                    *  Como los servidores cuentan con Balance de Carga, siempre debe haber al menos uno que no este en la
                    *  categoria High, es decir que siempre habra elementos en alguna de las siguientes 3 categorias
                    */
                    if (idles.Count > 0)
                    {
                        instance = idles.First().rol;
                        cpuUsageInstance = idles.First().cpuUsage;
                    }
                    else if (lows.Count > 0)
                    {
                        instance = lows.First().rol;
                        cpuUsageInstance = lows.First().cpuUsage;
                    }
                    else if (normals.Count > 0)
                    {
                        instance = normals.First().rol;
                        cpuUsageInstance = normals.First().cpuUsage;
                    }
                }
                //END ALGORITMO LOAD BALANCER
                DateTime EndDate = DateTime.Now;
                Int32 resta = (EndDate - StartDate).Milliseconds;

                CloudBlockBlob loadBalancerMetrics = container.GetBlockBlobReference("loadBalancerMetrics");

                if (!loadBalancerMetrics.Exists())
                {
                    loadBalancerMetrics.UploadText(DateTime.Now.ToShortTimeString() + ": Load balancer demoró " + resta + " ms y eligió " + instance.Id + " con " + cpuUsageInstance + "% CPU");
                }
                else {
                    String aux = loadBalancerMetrics.DownloadText();
                    aux = aux + "\n" + DateTime.Now.ToShortDateString() + ": Load balancer demoró " + resta + " ms y eligió " + instance.Id + " con " + cpuUsageInstance + "% CPU";

                    loadBalancerMetrics.UploadText(aux);
                }

                RoleInstanceEndpoint jobSubmissionServiceHostEndPoint = instance.InstanceEndpoints["JobSubmissionServiceEndPoint"];

                NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, false);

                EndpointAddress myEndpoint = new EndpointAddress(
                    String.Format("net.tcp://{0}/JobSubmissionService", jobSubmissionServiceHostEndPoint.IPEndpoint)
                    );

                try
                {
                    ChannelFactory<InterroleCommons.IReceiveJobSubmission> myChanFac = new ChannelFactory<InterroleCommons.IReceiveJobSubmission>(binding, myEndpoint);
                    InterroleCommons.IReceiveJobSubmission myClient = myChanFac.CreateChannel();
                    myClient.ReceiveJobSubmitionMessage(new InterroleCommons.JobSubmissionMessage() { idUsuario = e.idUsuario, nomEntrada = "Scene.main.mdl-" + fernetMode + "-" + e.idUsuario + "." + subid, subIdUsuario = Convert.ToString(subid) });
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("An error occured trying send Job Submission to the instances: " + ex.Message, "Warning");
                }

            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                throw;
            }
        }