<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : Azure, Aplicaciones Distribuidas</title><link>http://msmvps.com/blogs/lopez/archive/tags/Azure/Aplicaciones+Distribuidas/default.aspx</link><description>Tags: Azure, Aplicaciones Distribuidas</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Ejecutando AjSharp en Azure</title><link>http://msmvps.com/blogs/lopez/archive/2011/06/14/running_2D00_ajsharp_2D00_in_2D00_azure.aspx</link><pubDate>Tue, 14 Jun 2011 10:43:09 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1794678</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1794678</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/06/14/running_2D00_ajsharp_2D00_in_2D00_azure.aspx#comments</comments><description>&lt;p&gt;El code kata de este pasado fin de semana fue algo que estaba pensando desde el último año: ejecutar &lt;a href="http://ajlopez.wordpress.com/category/ajsharp/"&gt;AjSharp&lt;/a&gt; (mis post en &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx"&gt;español de AjSharp&lt;/a&gt;) dentro de un Worker Role de Azure. Pero desde antes que pienso: un intérprete como AjSharp puede servir de lenguaje de scripting en sistemas distribuidos. Esta incursión en Azure es una prueba de concepto interesante.&lt;/p&gt; &lt;p&gt;La idea es: una instancia de worker role recibe un texto via una cola de mensaje. El texto contiene código AjSharp y lo ejecuta. La salida (digamos, los PrintLine) se captura como texto y se envía como mensaje a otra cola.&lt;/p&gt; &lt;p&gt;El resultado del ejercicio está dentro de mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKata project&lt;/a&gt;: tienen que bajarse trunk\Azure\AzureAjSharp Y TAMBIEN trunk\AjLanguage (donde está el proyecto AjSharp). &lt;/p&gt; &lt;p&gt;La solución:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azureajsharp03.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Los proyectos:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AzureAjSharp.WorkerRole&lt;/strong&gt;: un worker role de ejemplo, con estas líneas agregadas:&lt;/p&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting(&amp;quot;&lt;span style="color:#8b0000;"&gt;DataConnectionString&lt;/span&gt;&amp;quot;);
Processor processor = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Processor(account);
processor.Start();
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Azure.AjSharp&lt;/strong&gt;: la librería de clases principal del proyecto. Contiene una clase Processor. Los constructores necesitan una cuenta de cloud y los nombres (opcionales, hay valores “default”): cola de requests, responses y un blob container. La cola de request contiene mensajes con código AjSharp para ejecutar (recuerden que AjSharp puede acceder a clases y objetos .NET: pueden invocar código compilado tranquilamente). La cola de response tiene el texto de salida de esas ejecuciones. El código de arriba processor.Start() inicia la lectura y ejecución de esos mensajes AjSharp.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AzureAjSharp.Console&lt;/strong&gt;: Es el programa que lee líneas de la consola, y cuando ingresamos una línea que contiene sólo “send”, el texto ingresado se convierte en un mensaje Azure que va a la cola de requests. Este programa también va leyendo (en un Thread aparte) los mensajes que le llegan por la cola de responses, imprimiendo el resultado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AzureLibrary&lt;/strong&gt;: Clases auxiliares que usé en otros ejemplos de Azure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AjSharpVS2010, AjLanguageVS2010&lt;/strong&gt;: Implementación de AjSharp .&lt;/p&gt;
&lt;p&gt;Cuando ejecuto el programa de consola, puedo enviar código AjSharp para ejecutar en un worker role, y recibir el resultado:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azureajsharp04.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Vean que uso clases .NET como DirectoryInfo.&lt;/p&gt;
&lt;p&gt;Y hay más: AjSharp soporta el Include(“nombredearchivoaserincluido”); donde el archivo contiene más código AjSharp. Modifiqué el lanzamiento de la máquina AjSharp para que tenga una versión cambiada de Include: ahora busca el contenido en un blob. Eso permite incluir y reusar código que no quepa en un mensaje, desde un blob container&lt;/p&gt;
&lt;p&gt;Un gráfico:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azureajsharp06.jpg" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Entonces, subí algo de código (los archivos originales están en el directorio Examples del proyecto Azure.AjSharp) en el contenedor blob llamado ajsfiles (para esta prueba en mi DevStorage):&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azureajsharp05.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;(Estoy usando &lt;a href="http://azurestorageexplorer.codeplex.com/"&gt;Neudesic Azure Storage Explorer&lt;/a&gt;, pero podría usar también &lt;a href="http://cloudberrylab.com/?page=explorer-azure"&gt;CloudBerry Explorer for Azure Storage&lt;/a&gt;: soporta el manejo de carpetas en árbol).&lt;/p&gt;
&lt;p&gt;Esta es el resultado de la ejecución de código con include de HelloWorld.ajs, y ForOneToTen.ajs:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azureajsharp02.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Próximos pasos:&lt;/p&gt;
&lt;p&gt;- Escribir más código utilitario en AjSharp, para ser incluido en otros programas, como: utilitarios de manejo de File y Directory, download y upload de blobs, envío y recepción de mensajes en cola, mensajes a todos los worker role intances, bajada y carga de assemblies, objetos a compartir entre request y request de AjSharp, etc. El cielo es el límite! ;-)&lt;/p&gt;
&lt;p&gt;Entonces, podemos (nosotros o un programa) enviar tareas dinámicamente y recibir resultados. Algo para tener: Guids para identificar tareas y sus resultados; una interfaz web; resultados almacenados como blobs; cache (y flush) de los archivos incluidos, etc…&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel “Java” Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1794678" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx">AjSharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category></item><item><title>Azure: Una aplicación Fractal</title><link>http://msmvps.com/blogs/lopez/archive/2011/02/16/azure_2D00_fractal_2D00_application.aspx</link><pubDate>Wed, 16 Feb 2011 11:13:02 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1788250</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1788250</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/02/16/azure_2D00_fractal_2D00_application.aspx#comments</comments><description>&lt;p&gt;En enero pasado, reimplementé &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/12/19/fractal-revisitado.aspx"&gt;mi aplicación Fractal&lt;/a&gt;, ahora usando Azure (&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/azure/default.aspx"&gt;mis posts sobre Azure&lt;/a&gt;). La idea es calcular cada sector de una imagen de un fractal, usando el poder de los worker roles, almacenar el resultado en blobs, y consumirlos desde una aplicación WinForm.&lt;/p&gt;  &lt;p&gt;Esta es la solución:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azurefractal01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El código está en mi projecto &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas&lt;/a&gt;, en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureFractak"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureFractak&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Si quieren, tiene directamente el código congelado a ahora en: &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/DotNet/AzureFractal.zip"&gt;AzureFractal.zip&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Los proyectos en la solución:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AzureFractal&lt;/strong&gt;: la definiciones para Azure (modelo de servicio, configuración).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fractal&lt;/strong&gt;: contiene mi código original de mi anterior aplicación fractal. Es un proyecto de librería de clases.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fractal.Azure&lt;/strong&gt;: algunos utilitarios de serialización, un servicio fachada para enviar un mensaje a la cola Azure.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AzureLibrary&lt;/strong&gt;: clases utilitarias que he usado en otros ejemplos Azure. Están evolucionando en cada ejemplo.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;FractalWorkerRole&lt;/strong&gt;: el Worker Role que consumen mensajes de una cola, que indican el sector (un rectángulo) del fractal de Mandelbrot a calcular.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fractal.GUI&lt;/strong&gt;: un cliente WinForm que envía y recibe mensajes a/desde colas usadas en el Worker Role.&lt;/p&gt;  &lt;p&gt;Deberían configurar la solución para tener dos proyectos a lanzar:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azurefractal02.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;La aplicación WinForm envía un mensaje a una cola, con la información del sector a calcular:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Calculate()
{
    Bitmap bitmap = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Bitmap(pcbFractal.Width, 
       pcbFractal.Height);
    pcbFractal.Image = bitmap;
    pcbFractal.Refresh();
    realWidth = realDelta * pcbFractal.Width;
    imgHeight = imgDelta * pcbFractal.Height;
    realMin = realCenter - realWidth / 2;
    imgMin = imgCenter - imgHeight / 2;
    &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; width = pcbFractal.Width;
    &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; height = pcbFractal.Height;
    Guid id = Guid.NewGuid();
    SectorInfo sectorinfo = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SectorInfo()
    {
        Id = id,
        FromX = 0,
        FromY = 0,
        Width = width,
        Height = height,
        RealMinimum = realMin,
        ImgMinimum = imgMin,
        Delta = realDelta,
        MaxIterations = colors.Length,
        MaxValue = 4
    };
    Calculator calculator = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Calculator();
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.AddMessage(
        SectorUtilities.FromSectorInfoToMessage(sectorinfo));
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El Worker Role lee mensajes desde una cola, y la deserializa en SectorInfo:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;)
{
    CloudQueueMessage msg = queue.GetMessage();
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (msg != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
    {
        Trace.WriteLine(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&amp;quot;&lt;span style="color:#8b0000;"&gt;Processing {0}&lt;/span&gt;&amp;quot;, msg.AsString));
        SectorInfo info = SectorUtilities.FromMessageToSectorInfo(msg);&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Si el sector es muy grande, nuevos mensajes son generados:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (info.Width &amp;gt; 100 || info.Height &amp;gt; 100)
{
    Trace.WriteLine(&amp;quot;&lt;span style="color:#8b0000;"&gt;Splitting message...&lt;/span&gt;&amp;quot;);
    &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; x = 0; x &amp;lt; info.Width; x += 100)
        &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; y = 0; y &amp;lt; info.Height; y += 100)
        {
            SectorInfo newinfo = info.Clone();
            newinfo.FromX = x + info.FromX;
            newinfo.FromY = y + info.FromY;
            newinfo.Width = Math.Min(100, info.Width - x);
            newinfo.Height = Math.Min(100, info.Height - y);
            CloudQueueMessage newmsg = 
              SectorUtilities.FromSectorInfoToMessage(newinfo);
            queue.AddMessage(newmsg);
        }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Si el sector tiene un tamaño tratable, es procesado:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;Trace.WriteLine(&amp;quot;&lt;span style="color:#8b0000;"&gt;Processing message...&lt;/span&gt;&amp;quot;);
Sector sector = calculator.CalculateSector(info);
&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; blobname = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&amp;quot;&lt;span style="color:#8b0000;"&gt;{0}.{1}.{2}.{3}.{4}&lt;/span&gt;&amp;quot;, 
info.Id, sector.FromX, sector.FromY, sector.Width, sector.Height);
CloudBlob blob = blobContainer.GetBlobReference(blobname);
MemoryStream stream = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MemoryStream();
BinaryWriter writer =&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; BinaryWriter(stream);
&lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; sector.Values)
    writer.Write(&lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
blob.UploadFromStream(stream);
stream.Close();
CloudQueueMessage outmsg = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; CloudQueueMessage(blobname);
outqueue.AddMessage(outmsg);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Un blob con el resultado es generado, y un mensaje es enviado a otra cola para notificar a la aplicación cliente.&lt;/p&gt;

&lt;p&gt;El WinForm tiene un thread con un ciclo leyendo mensajes desde una segunda cola:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; blobname = msg.AsString;
CloudBlob blob = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.blobContainer.GetBlobReference(blobname);
MemoryStream stream = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MemoryStream();
blob.DownloadToStream(stream);
blob.Delete();
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.inqueue.DeleteMessage(msg);
&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;[] parameters = blobname.Split(&amp;#39;.&amp;#39;);
Guid id = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Guid(parameters[0]);
&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; fromx = Int32.Parse(parameters[1]);
&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; fromy = Int32.Parse(parameters[2]);
&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; width = Int32.Parse(parameters[3]);
&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; height = Int32.Parse(parameters[4]);
&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;[] values = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;[width * height];
stream.Seek(0, SeekOrigin.Begin);
BinaryReader reader = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; BinaryReader(stream);
&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; k = 0; k &amp;lt; values.Length; k++)
    values[k] = reader.ReadInt32();
stream.Close();
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Invoke((Action&amp;lt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;[]&amp;gt;) ((x,y,h,w,v) 
=&amp;gt; 
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.DrawValues(x,y,h,w,v)), fromx, fromy, width, height, values);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Notel el uso de .Invoke para ejecutar el dibujo del sector dentro del thread de UI (User Interface).&lt;/p&gt;

&lt;p&gt;Esta es la aplicación WinForm, luego de hacer click en el botón Calculate. Noten que los sectores están arrivando:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azurefractal03.jpg" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Hay sectores que todavía no llegaron. Podemos arrastrar el mouse y soltarlo para marcar un nuevo sector:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azurefractal04.jpg" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Podemos cambiar los colores, con el botón New Colors:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azurefractal05.jpg" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Esta es una aplicación de ejemplo, una prueba de concepto. Probablemente, tengamos un mejor rendimiento usando una máquina simple. Pero la idea es que podemos dar trabajo a Worker Roles, especialmente si el trabajo puede hacerse en paralelo (imaginen una máquina para render en paralelo de animaciones). Si Uds. usan esta aplicación en Azure, con varias instancias de Worker Role, el rendimiento podría mejorar.&lt;/p&gt;

&lt;p&gt;Próximos pasos: implementar un Web Crawler distribuido, intentar un algoritmo genético distribuido, todo usando la nube Azure.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1788250" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item><item><title>Azure: Una aplicación simple usando Tables</title><link>http://msmvps.com/blogs/lopez/archive/2011/02/09/azure_2D00_a_2D00_simple_2D00_application_2D00_using_2D00_tables.aspx</link><pubDate>Wed, 09 Feb 2011 09:50:08 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1787882</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1787882</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/02/09/azure_2D00_a_2D00_simple_2D00_application_2D00_using_2D00_tables.aspx#comments</comments><description>&lt;p&gt;Continuando con &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx"&gt;mis ejemplos de Azure&lt;/a&gt;, esta vez escribí una simple aplicación web CRUD, usando Tables, con Tables, usando Azure Storage Client.&lt;/p&gt;  &lt;p&gt;Es una aplicación de ASP.NET clásico, con esta vista para CustomerList.aspx:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azure45.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Pueden bajarse la solución desde mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Google project&lt;/a&gt;. El código está en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureCustomers"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureCustomers&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Si quieren pueden bajarse directamente la versión “congelada” desde: &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/DotNet/AzureCustomers.zip"&gt;AzureCustomers.zip&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;La simple entidad Customer:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Customer : TableServiceEntity
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Customer()
        : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(Guid.NewGuid().ToString())
    {
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Customer(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; id)
        : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(id, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Empty)
    {
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Name { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Address { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Notes { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Estoy usando la PartitionKey como clave primaria, llenándola con un Guid. La RowKey es el string vacío. En una aplicación menos simple, podría grabar las facturas de un cliente usando la misma Partition Key, identificando cada factura con un RowKey distinto.&lt;/p&gt;

&lt;p&gt;Un DataContext está a cargo de exponer un IQueryable de Customers:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; DataContext : TableServiceContext
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; CustomerTableName = &amp;quot;&lt;span style="color:#8b0000;"&gt;Customers&lt;/span&gt;&amp;quot;;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; DataContext(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; baseAddress, StorageCredentials credentials)
        : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(baseAddress, credentials)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.IgnoreResourceNotFoundException = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; DataContext(CloudStorageAccount storageAccount)
        : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.IgnoreResourceNotFoundException = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
    }       
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IQueryable&amp;lt;Customer&amp;gt; Customers
    {
        &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.CreateQuery&amp;lt;Customer&amp;gt;(CustomerTableName);
        }
    }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Noten el IgnoreNotFoundException: si está en verdadero, puedo recuperar un cliente inexistente sin levantar una excepción, y retornar un valor null.&lt;/p&gt;

&lt;p&gt;Hay un servicio para acceder y manejar los Customers:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; CustomerServices
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; DataContext context;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; CustomerServices(DataContext context)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context = context;
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Customer GetCustomerById(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; id)
    {
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.Customers.Where(c =&amp;gt; c.PartitionKey == id).SingleOrDefault();
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Customer&amp;gt; GetCustomerList()
    {
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.Customers.ToList().OrderBy(c =&amp;gt; c.Name);
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; AddCustomer(Customer customer)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.AddObject(DataContext.CustomerTableName, customer);
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.SaveChanges();
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; UpdateCustomer(Customer customer)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.AttachTo(DataContext.CustomerTableName, customer, &amp;quot;&lt;span style="color:#8b0000;"&gt;*&lt;/span&gt;&amp;quot;);
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.UpdateObject(customer);
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.SaveChanges();
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DeleteCustomerById(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; id)
    {
        Customer c = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.GetCustomerById(id);
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.DeleteObject(c);
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.context.SaveChanges();
    }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Noten el uso de Attach con ETag (tercer parámetro) de “*” (any). De esta forma, podemos actualizar el cliente adosando el “creado en memoria” al contexto de datos, sin recuperalo desde la base de datos. Esta forma de hacerlo es viable si tengo todos los datos del cliente, y no me importa sobreescribir cambios posibles que se hubieran hecho en el storage. En muchas aplicaciones uno cambia solamente parte del estado, ante una operación (por ejemplo, cambio de domiciolio). Entonces se recupera el objeto, se cambia parte del estado y se lo graba.&lt;/p&gt;

&lt;p&gt;Usando el servico para recuperar los clientes:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;CloudStorageAccount storage = CloudStorageAccount.FromConfigurationSetting(&amp;quot;&lt;span style="color:#8b0000;"&gt;DataConnectionString&lt;/span&gt;&amp;quot;);
CustomerServices services = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; CustomerServices(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; DataContext(storage));
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.grdCustomerList.DataSource = services.GetCustomerList();
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.grdCustomerList.DataBind();&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Nota: ésta es una aplicación de ejemplo, simple y directa. Una aplicación real debería separar el modelo de vista del modelo de negocio, y posiblemente, usar ASP.NET MVC en la presentación. Escribiré este ejemplo usando MVC. En otra serie (fuera de ésta relacionado con Azura), quiero escribir una aplicación ASP.NET MVC usando TDD.&lt;/p&gt;

&lt;p&gt;Próximos pasos en Azure: una aplicación distribuida que calcule un fractar, un web crawler distribuido, un algoritmo genético usando Worker Roles.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1787882" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ALT.NET/default.aspx">ALT.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item><item><title>Programando con Windows Azure en Buenos Aires</title><link>http://msmvps.com/blogs/lopez/archive/2011/02/03/programando-con-windows-azure-en-buenos-aires.aspx</link><pubDate>Thu, 03 Feb 2011 10:03:53 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1787539</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1787539</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/02/03/programando-con-windows-azure-en-buenos-aires.aspx#comments</comments><description>&lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;display:inline;" align="left" src="http://www.ajlopez.com/images/articles2/azure.jpg" alt="" /&gt; Gracias a la gente del MUG (Microsoft User Group) de Argentina, el martes 15 y el jueves 17 de Febrero estaré dando un curso gratuito de programación en Windows Azure. Son dos horas el martes y dos horas más el jueves, de 19 a 21hs.&lt;/p&gt;  &lt;p&gt;Detalles e inscripción (hay que registrarse) en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.mug.org.ar/Eventos/3562.aspx"&gt;Seminario Gratuito – Programando en Windows Azure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Los temas a dar:&lt;/p&gt;  &lt;p&gt;- Cloud Computing en general, IaaS , PaaS, SaaS   &lt;br /&gt;- Windows Azure    &lt;br /&gt;- Conceptos del HyperVisor, Fabric    &lt;br /&gt;- Service Model    &lt;br /&gt;- Web Roles    &lt;br /&gt;- Worker Roles    &lt;br /&gt;- Azure Storage: Blobs, Queues, Tables    &lt;br /&gt;- Patrones    &lt;br /&gt;- Ejemplos&lt;/p&gt;  &lt;p&gt;Voy a mostrar ejemplos, algunos &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx"&gt;ya publicados acá en posts sobre Azure&lt;/a&gt;, y otros nuevos. Azure me parece un tema muy interesante, que permite comenzar a implementar aplicaciones distribuidas, más allá de tener las ventajas del Cloud Computing (escalabilidad, disponibilidad…) Habrán notado que desde hace años aparecen por este blog posts relacionados con aplicaciones distribuidas. Y los que me escucharon en alguna charla (como las de Maratón 2.0) saben que me decanto por explotar el tema de distribución para implementar temas nuevos, como la convergencia de inteligencia artifical y web semántica, y más.&lt;/p&gt;  &lt;p&gt;Espero que los que puedan venir encuentren interesante el seminario. Como siempre, quedará publicado por acá el material presentado.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1787539" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item><item><title>Resultado de la ALT.NET Hispano VAN de Programando en Azure</title><link>http://msmvps.com/blogs/lopez/archive/2011/02/02/resultado-de-la-alt-net-hispano-van-de-programando-en-azure.aspx</link><pubDate>Wed, 02 Feb 2011 11:15:14 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1787493</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1787493</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/02/02/resultado-de-la-alt-net-hispano-van-de-programando-en-azure.aspx#comments</comments><description>&lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;display:inline;" align="left" src="http://www.ajlopez.com/images/articles2/azure43.jpg" alt="" /&gt; Ya había adelantado esta reunión virtual en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/01/07/alt-net-hispano-van-programando-en-azure.aspx"&gt;ALT.NET Hispano VAN Programando en Azure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Gracias a la &lt;a href="http://altnethispano.org/"&gt;gente de la comunidad ALT.NET Hispano&lt;/a&gt;, pude participar el sábado pasado presentando Programando en Windows Azure. Pueden bajarse la presentación desde mi Skydrive en &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Presentations/AzureProgramming201101.pptx"&gt;AzureProgramming201101.pptx&lt;/a&gt;. La presentación se basa en slides traducidos de varias presentaciones &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=413e88f8-5966-4a83-b309-53b7b77edf78&amp;amp;displaylang=en"&gt;del Azure Training Kit&lt;/a&gt; (el lunes 31 de Enero fue publicada una nueva versión). Les recomiendo bajarse ese material, porque ahí encontraran ejemplos (la gente de Microsoft los llama “hands-on labs”), explicados, y con instrucciones para reproducirlos paso a paso.&lt;/p&gt;  &lt;p&gt;La reunión fue grabada, y pueden ver el video en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://altnethispano.org/wiki/van-2011-01-29-windows-azure.ashx"&gt;Programando con Windows Azure – ALT.NET Hispano Wiki&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Estuvimos viendo conceptos generales de Azure, y luego, usando Visual Studio 2010, el Azure SDK:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=7a1089b6-4050-4307-86c4-9dadaa5ed018"&gt;Windows Azure SDK and Windows Azure Tools for Microsoft Visual Studio (November 2010)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Esa versión SDK 1.3 es para VS2010, y me bajé el archivo VSCloudService.exe (no importa si es 32 o 64 bits) que contiene el SDK y las tools para Visual Studio, no hace falta bajarse el SDK aparte, viene dentro de este archivo. Si tienen que usar Visual Studio 2008, tienen que buscar el SDK 1.2, que fue la última versión que tiene soporte para esa IDE. Lamentablemente, no pueden convivir en la misma máquina el SDK 1.2 y el 1.3.&lt;/p&gt;  &lt;p&gt;Y el Azure Storage Explorer, de Neudesic, a bajar desde Codeplex:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://azurestorageexplorer.codeplex.com/"&gt;Azure Storage Explorer&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Durante la charla, me concentré en explicar, para quien es nuevo en Azure, dos grandes temas:&lt;/p&gt;  &lt;p&gt;Azure Compute, con Web Roles y Worker Roles.&lt;/p&gt;  &lt;p&gt;Azure Storage: con Tables, Queues y Blobs.&lt;/p&gt;  &lt;p&gt;Los ejemplos de la charla (con tablas, uso de colas, y blobs) pueden bajarlo del Google code project &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas&lt;/a&gt;, pueden bajarlos desde:&lt;/p&gt;  &lt;p&gt;&lt;tt&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="http://ajcodekatas.googlecode.com/svn/trunk/Azure"&gt;http://ajcodekatas.googlecode.com/svn/trunk/Azure&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/tt&gt;&lt;/p&gt;  &lt;p&gt;Los que no tienen SVN pueden ver la versión “congelada” a estos días:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/DotNet/AjCodeKatasAzure.zip"&gt;AjCodeKatasAzure.zip&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ejemplos reducidos de Azure Training Kit que tratan esos temas (si no quieren bajarse TODO el kit), en &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/DotNet/AzureLabs.zip"&gt;AzureLabs.zip&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Ya escribí en &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx"&gt;anteriores posts&lt;/a&gt; sobre algunos ejemplos presentados. Tengo que publicar sobre el ejemplo de generación de fractal usando un cliente WinForms local y worker roles que hacen el trabajo (incluido en los ejemplos presentados):&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azure44.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Bibliografía usada:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://oreilly.com/catalog/9780596801984"&gt;Programming Windows Azure, Sriram Krisham; O’Reilly&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://www.manning.com/hay/"&gt;Azure in Action, Chris Hay, Brian H. Prince; Manning&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://apress.com/book/view/9781430224693"&gt;Introducing Windows Azure, Henri Li; Apress&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Enlaces que fui usando, los coleccioné en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/azure"&gt;http://delicious.com/ajlopez/azure&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/azure+tutorial"&gt;http://delicious.com/ajlopez/azure+tutorial&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/azure+video"&gt;http://delicious.com/ajlopez/azure+video&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/azure+storage"&gt;http://delicious.com/ajlopez/azure+storage&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Algunos enlaces a destacar:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/windows-azure-storage-abstractions-and-their-scalability-targets.aspx"&gt;http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/windows-azure-storage-abstractions-and-their-scalability-targets.aspx&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/windowsazurestorage/archive/2010/12/30/windows-azure-storage-architecture-overview.aspx"&gt;http://blogs.msdn.com/b/windowsazurestorage/archive/2010/12/30/windows-azure-storage-architecture-overview.aspx&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://www.microsoftpdc.com/2009/SVC08"&gt;http://www.microsoftpdc.com/2009/SVC08&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://code.msdn.microsoft.com/windowsazuresamples"&gt;http://code.msdn.microsoft.com/windowsazuresamples&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/olavt/archive/2009/03/12/using-windows-azure-blob-storage-to-store-aerial-images.aspx"&gt;http://blogs.msdn.com/b/olavt/archive/2009/03/12/using-windows-azure-blob-storage-to-store-aerial-images.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Próximos pasos: escribir sobre el ejemplo de Azure Fractal, y escribir un ejemplo de Web Crawler usando Tables, Queues, Web Role y Worker Roles.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1787493" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ALT.NET/default.aspx">ALT.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item><item><title>ALT.NET Hispano VAN Programando en Azure</title><link>http://msmvps.com/blogs/lopez/archive/2011/01/07/alt-net-hispano-van-programando-en-azure.aspx</link><pubDate>Fri, 07 Jan 2011 11:03:26 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1785887</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1785887</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/01/07/alt-net-hispano-van-programando-en-azure.aspx#comments</comments><description>&lt;p&gt;Gracias a la &lt;a href="http://altnethispano.org"&gt;gente de la comunidad ALT.NET Hispano&lt;/a&gt;, el próximo sábado 29 de Enero, a las 18hs (GMT) (15hs acá en Argentina), participaré de una VAN (desconferencia virtual), tratando el de Programar en Azure.&lt;/p&gt;  &lt;p&gt;Presentaré los temas:&lt;/p&gt;  &lt;p&gt;- Conceptos de Windows Azure y Cloud Computing&lt;/p&gt;  &lt;p&gt;- Web Roles &lt;/p&gt;  &lt;p&gt;- Worker Roles &lt;/p&gt;  &lt;p&gt;- Azure Storage: Blobs, Queues, Tables &lt;/p&gt;  &lt;p&gt;- Patrones &lt;/p&gt;  &lt;p&gt;- Ejemplos &lt;/p&gt;  &lt;p&gt;Tratando de dar una visión de cómo se puede programar y aprovechar la plataforma Azure para nuestras aplicaciones en la nube. Ya estoy publicando código y ejemplos en este blog. Lo que presente quedará en la página de la comunidad y en este blog.&lt;/p&gt;  &lt;p&gt;Mis enlaces sobre el tema:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/azure"&gt;http://delicious.com/ajlopez/azure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para participar, entrar al enlace &lt;a href="http://snipr.com/virtualaltnet"&gt;http://snipr.com/virtualaltnet&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Recuerdo lo que el Microsoft MVP &lt;a href="http://twitter.com/jorgegamba"&gt;@jorgegamba&lt;/a&gt; escribió sobre estas reuniones:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Hay que aclarar que no se requiere ningún tipo de registro, simplemente acudir el día y la hora indicados a la dirección Web &lt;a href="http://snipr.com/virtualaltnet"&gt;http://snipr.com/virtualaltnet&lt;/a&gt;, eso sí, deberán tener instalado el programa cliente de Live Meeting; hay más instrucciones sobre cómo hacer esto y otras indicaciones en la página &lt;a href="http://altnethispano.org/reuniones/descripcion.aspx"&gt;Descripción de Reuniones&lt;/a&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Para los que no puedan asistir, quedará publicado un video en el sitio de la comunidad.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1785887" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ALT.NET/default.aspx">ALT.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item><item><title>Azure: Multithreads en Worker Role, un ejemplo</title><link>http://msmvps.com/blogs/lopez/archive/2010/12/14/azure_2D00_multithreads_2D00_in_2D00_worker_2D00_role_2D00_an_2D00_example.aspx</link><pubDate>Tue, 14 Dec 2010 10:46:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1784294</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1784294</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/12/14/azure_2D00_multithreads_2D00_in_2D00_worker_2D00_role_2D00_an_2D00_example.aspx#comments</comments><description>&lt;p&gt;En &lt;a href="http://msmvps.com/blogs/lopez/archive/2010/12/10/azure-una-aplicaci-243-n-simple.aspx"&gt;mi anterior post&lt;/a&gt;, implementé un simple worker role, consumiendo y produciendo números desde y en una cola. Ahora, una nueva aplicación:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azure40.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El worker role implementa la generación de una secuencia Collatz. Para conocer sobre esta secuencia, problema:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://mathworld.wolfram.com/CollatzProblem.html"&gt;http://mathworld.wolfram.com/CollatzProblem.html&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Collatz_conjecture"&gt;http://en.wikipedia.org/wiki/Collatz_conjecture&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://www.ericr.nl/wondrous/"&gt;http://www.ericr.nl/wondrous/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Pueden bajar la solución desde &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Google project&lt;/a&gt;. El código está en la rama:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureCollatz"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureCollatz&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;La página inicial es simple, sin validaciones:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azure41.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El rango de números es enviada a la cola:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; btnProcess_Click(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; from = Convert.ToInt32(txtFromNumber.Text);
    &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; to = Convert.ToInt32(txtToNumber.Text);
    &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; k=from; k&amp;lt;=to; k++) 
    {
        CloudQueueMessage msg = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; CloudQueueMessage(k.ToString());
        WebRole.Instance.NumbersQueue.AddMessage(msg);
    }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El worker role toma cada mensaje, y calcula la secuencia Collatz del número recibido en cada mensaje:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/azure42.jpg" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Agregué una clase en Azure.Library: un MessageProcessor que consumen mensajes de una cola, en su propio thread:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; MessageProcessor(CloudQueue queue, Func&amp;lt;CloudQueueMessage, &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&amp;gt; process)
{
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue = queue;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.process = process;
}
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Start()
{
    Thread thread = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Thread(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ThreadStart(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Run));
    thread.Start();
}
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Run()
{
    &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;)
    {
        &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
        {
            CloudQueueMessage msg = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.GetMessage();
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ProcessMessage(msg))
                &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.DeleteMessage(msg);
        }
        &lt;span style="color:#0000ff;"&gt;catch&lt;/span&gt; (Exception ex)
        {
            Trace.WriteLine(ex.Message, &amp;quot;&lt;span style="color:#8b0000;"&gt;Error&lt;/span&gt;&amp;quot;);
        }
    }
}
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; ProcessMessage(CloudQueueMessage msg)
{
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (msg != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.process != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.process(msg);
    Trace.WriteLine(&amp;quot;&lt;span style="color:#8b0000;"&gt;Working&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;Information&lt;/span&gt;&amp;quot;);
    Thread.Sleep(10000);
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;;
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El worker role, en vez de atender un mensaje a la vez, lanza un número fijo (12) de MessageProcessor. De esta manera, cada instancia de Azure que tengamos disponible se dedica a procesar varios mensajes, en paralelo. No sería necesario para este simple ejemplo. Pero es una “prueba de concepto” para ir viendo de usar esta idea de múltiples threads. Parte del método Run en el worker role:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;QueueUtilities qutil = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; QueueUtilities(account);
CloudQueue queue = qutil.CreateQueueIfNotExists(&amp;quot;&lt;span style="color:#8b0000;"&gt;numbers&lt;/span&gt;&amp;quot;);
CloudQueueClient qclient = account.CreateCloudQueueClient();
&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; k=0; k&amp;lt;11; k++) 
{
    CloudQueue q = qclient.GetQueueReference(&amp;quot;&lt;span style="color:#8b0000;"&gt;numbers&lt;/span&gt;&amp;quot;);
    MessageProcessor p = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MessageProcessor(q, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ProcessMessage);
    p.Start();
}
MessageProcessor processor = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MessageProcessor(queue, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ProcessMessage);
processor.Run();
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El método ProcessMessage se encarga del trabajo real:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; ProcessMessage(CloudQueueMessage msg)
{
    &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; number = Convert.ToInt32(msg.AsString);
    List&amp;lt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;&amp;gt; numbers = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;&amp;gt;() { number };
    &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (number &amp;gt; 1)
    {
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; ((number % 2) == 0)
        {
            number = number / 2;
            numbers.Add(number);
        }
        &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
        {
            number = number * 3 + 1;
            numbers.Add(number);
        }
    }
    StringBuilder builder = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder();
    builder.Append(&amp;quot;&lt;span style="color:#8b0000;"&gt;Result:&lt;/span&gt;&amp;quot;);
    &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; n &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; numbers)
    {
        builder.Append(&amp;quot;&lt;span style="color:#8b0000;"&gt; &lt;/span&gt;&amp;quot;);
        builder.Append(n);
    }
    Trace.WriteLine(builder.ToString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;Information&lt;/span&gt;&amp;quot;);
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Próximos pasos: más aplicaciones distribuidas (algoritmo genético, web crawler, etc…). También podría mejorar el ejemplo para conseguir ver los resultados en una página web, o lanzar y consultar resultados de forma remota, desde un WinForm, por ejemplo.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1784294" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Azure/default.aspx">Azure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cloud+Computing/default.aspx">Cloud Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Aplicaciones+Distribuidas/default.aspx">Aplicaciones Distribuidas</category></item></channel></rss>