<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Life in the cloud</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/luisguerrero/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/luisguerrero/feed.xml</link>
    <description>This blog is about my experience as a SDE in CSE</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:17:22 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>How to secure web communications in a Service Fabric cluster in Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/how-to-secure-web-communications-in-a-service-fabric-cluster-in-azure</link>
      <pubDate>Thu, 12 Apr 2018 10:44:45 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/?p=545</guid>
      <description><![CDATA[I came to this question during a conversion with a customer. They have an ASP.NET Core WebApi inside...]]></description>
      <content:encoded><![CDATA[<p align="justify">I came to this question during a conversion with a customer. They have an ASP.NET Core WebApi inside a Service Fabric cluster and they want the WebApi to be exposed publicly on the cluster. As you may know, the default deployment setup for Service Fabric in Azure is to use a public Load Balancer with a Public IP address. While this is great to connect to the management API and the dashboard UI, is not the preferred way to expose the WebApi. Both the management API and the Service Fabric Explorer are using a certificate as the authentication mechanism. This certificate is store in the Key Vault that user selected during the deployment.<p align="justify">My approach to this problem is to use Application Gateway as the Layer 7 load balancer to expose and consume the WebApi from the public Internet. In the Application Gateway I can install the certificate and server the content from it. The internal communication between the Application Gateway and the Service Fabric don’t need to be secured. I can have SSL-offload for the WebApi.<p align="justify">To achieve this, we can modify the default ARM template for Service Fabric and instead of deploying a public load balancer we can deploy using an internal load balancer. This will prevent any kind of public traffic to hit any Service Fabric endpoint. We can follow this documentation for the <a href="https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-patterns-networking#internal-only-load-balancer">Service Fabric Cluster networking patterns</a>. <p align="justify">Once we have the cluster deploy using the internal load balancer the Service Fabric Explorer URI will be <a href="https://10.0.0.250:19080/">https://10.0.0.250:19080/</a>, the management endpoint is 10.0.0.250:19000.<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2018/04/image217.png"><img width="628" height="444" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/04/image_thumb212.png" border="0"></a></p><h3 align="justify">Application Gateway.</h3><p align="justify">The next step will be to create a new subnet inside the VNET where the Service Fabric cluster is. After the subnet is created, we can deploy the Application Gateway in that newly created subnet. When the Application Gateway is created, in the configuration setting for the Backend pool we need to add the internal IP address for the internal load balancer that the Service Fabric cluster is using.<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image0032.png"><img width="584" height="378" title="clip_image003" alt="clip_image003" src="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image003_thumb2.png" border="0"></a></p><p align="justify">This will enable the Application Gateway to route the HTTP/HTTPS traffic through the internal load balancer. If the scale set associated with the Service Fabric cluster increase or decrease the number of VMs, this configuration will be transparent for the Application Gateway, making things easy. <p align="justify">We have everything ready to expose the WebApi using the Application Gateway. Application Gateway is connected to the internal IP of the Internal Load Balancer, who is connected to Service Fabic Scale Set. Inside the Application Gateway we need to setup the Listener, Rule and HTTP Setting to map the port 443, upload the certificate and we ready to go.<h3 align="justify">Service Fabric management API</h3><p align="justify">The internal load balancer is great because we’re sure that all communication is isolated and secure. But when we would like to deploy a new application to the cluster, or update an existing one, we need communication with the Management API as well with the Service Fabric Explorer. This is a problem right now because only devices in the same VNET are the one who can communicate to the internal load balancer. To solve this connectivity issue, we have two options.<p align="justify">First, deploy a Virtual Machine on the VNET where Service Fabric Cluster is. Install the Visual Studio Agent and deploy from there. We’re going to miss the Service Fabric Explorer as well. But we can connect using remote desktop to that VM and browse from there. <p align="justify">Second option is deploying another load balancer, but in this scenario a public one, and explore both the Management API and the Service Fabric Explorer. <p align="justify">Once the public load balancer is created, go to the backend pools and click on add, give a name and select associated to Virtual machine scale set. Select the Scale Set associated with the Service Fabric cluster.<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image0045.png"><img width="587" height="489" title="clip_image004" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image004_thumb4.png" border="0"></a></p><p align="justify">Then map both the 19000 and 19080 ports to make the management API and the Service Fabric Explorer. <h3 align="justify">Final architecture</h3><p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image0062.jpg"><img width="629" height="428" title="clip_image006" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2018/04/clip_image006_thumb2.jpg" border="0"></a></p><p align="justify">This is final architecture for the proposed solution. With two public IP addresses, one with the Application Gateway to expose using SSL the WebApi and the other one to manage the Service Fabric cluster itself. A final option that it’s a more complicated is to have a VPN Gateway in the VNET and connect your local on-prem network. This could be overly complicated depending on your IT department.<p align="justify">Luis Guerrero.]]></content:encoded>
    </item>
    <item>
      <title>Gráficas de información del nuevo portal de Azure (Ibiza)</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/grficas-de-informacin-del-nuevo-portal-de-azure-ibiza</link>
      <pubDate>Thu, 10 Dec 2015 03:19:54 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/12/10/grficas-de-informacin-del-nuevo-portal-de-azure-ibiza/</guid>
      <description><![CDATA[Cuando se tienen servidores en producción una de las preocupaciones de los administradores IT o...]]></description>
      <content:encoded><![CDATA[<p>Cuando se tienen servidores en producción una de las preocupaciones de los administradores IT o devops es saber lo bien (o mal) que están funcionando sus servidores. La forma más rápida de ver si un servidor está saturado o no, es simplemente mirando al consumo de CPU, o en el caso de la aplicación sea muy intensiva de red, echando un vistazo a los bytes enviados en el adaptador de red. También puede ser la memoria libre que tiene disponible la máquina.</p>  <p>Si la maquina tiene un servidor de aplicaciones como IIS, sería interesante poder mostrar información sobre cuantas peticiones por segundo se están ejecutando, cual es la cola de http de ASP.NET. Si por el contrario se tiene un servidor de SQL Server, información de cuantas peticiones activas tiene, la cantidad de re compilaciones de los planes de ejecución, ect. </p>  <h1>Información al poder</h1>  <p>En todos estos escenarios que antes se han mencionado la información de contadores de rendimiento muestran información de salud del estado de la máquina o del servicio. En ese sentido uno de los problemas que se puede enfrentar un administrador de IT es que tenga que conectarse a todas esas máquinas para extraer esa información haciendo que el proceso sea tedioso. </p>  <p>Aquí es donde entra el portal del Azure (Ibiza) que puede ayudar en esas tareas de monitorización básicas. </p>  <h1>Graficas del portal</h1>  <p>Cuando se provisiona un servidor, ya sea Windows o Linux, el portal permite obtener información de la máquina para después mostrar esa información en el propio portal. </p>  <h2>Linux</h2>  <p>En el siguiente ejemplo una máquina de Linux que tiene instalado un servidor de node.js y utiliza <a href="https://github.com/Unitech/pm2">pm2</a> como servidor de aplicaciones para utilizar todos los cores (8) de la máquina.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/8814.clip_image001_3EEFFBE9.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/8814.clip_5F00_image001_5F00_3EEFFBE9.png"><img title="clip_image001" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image001" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1731.clip_image001_thumb_55B1D423.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1731.clip_5F00_image001_5F00_thumb_5F00_55B1D423.png" width="589" height="894" /></a></p>  <p>Como se puede se puede observar esta máquina es Linux, y tiene 8 Cores y 14 Gb de memoria. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4061.clip_image002_65C0A2DA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4061.clip_5F00_image002_5F00_65C0A2DA.png"><img title="clip_image002" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6064.clip_image002_thumb_1341C29E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6064.clip_5F00_image002_5F00_thumb_5F00_1341C29E.png" width="581" height="215" /></a></p>  <p>Pero aun así se puede obtener información muy variada, incluso cuantos bytes se han enviado o recibido desde el adaptador de red y cuantas lecturas y escrituras se han hecho. <u></u></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/8637.clip_image003_796D8C6E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/8637.clip_5F00_image003_5F00_796D8C6E.png"><img title="clip_image003" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image003" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1881.clip_image003_thumb_09102831.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1881.clip_5F00_image003_5F00_thumb_5F00_09102831.png" width="588" height="882" /></a></p>  <p>Como se puede observar esta máquina es muy intensiva de CPU y red, pero no hace apenas escritas en disco ya que simplemente procesa un html y devuelve el resultado por red. </p>  <h2>Windows Server con SQL Server</h2>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/0245.clip_image004_06D63026.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/0245.clip_5F00_image004_5F00_06D63026.png"><img title="clip_image004" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/8510.clip_image004_thumb_422995E4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/8510.clip_5F00_image004_5F00_thumb_5F00_422995E4.png" width="581" height="215" /></a></p>  <p>La siguiente máquina tiene Windows Server 2012 R2 con 16 discos duros adjuntos y tiene 8 Core y 28 Gb de memoria con un SQL Server instalado. </p>  <p>Además de las gráficas de CPU típicas de una maquinas también se puede obtener información sobre el estado del SQL Server que hay instalado y funcionando:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2766.clip_image005_3693D8A5.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2766.clip_5F00_image005_5F00_3693D8A5.png"><img title="clip_image005" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image005" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4670.clip_image005_thumb_717B0B6E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4670.clip_5F00_image005_5F00_thumb_5F00_717B0B6E.png" width="586" height="895" /></a></p>  <p>Además de graficas de lecturas y escrituras de discos:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1641.clip_image006_734B6135.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1641.clip_5F00_image006_5F00_734B6135.png"><img title="clip_image006" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2161.clip_image006_thumb_20CF11AA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2161.clip_5F00_image006_5F00_thumb_5F00_20CF11AA.png" width="586" height="890" /></a><u></u></p>  <p>Lo interesante de estas gracias es que no solo se puede obtener esa información sino que se puede personalizar la cantidad de información que se desee. A continuación un detalle de los contadores que se pueden obtener para SQL Server:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2330.clip_image008_0DADE4FE.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2330.clip_5F00_image008_5F00_0DADE4FE.jpg"><img title="clip_image008" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/0871.clip_image008_thumb_4FB4543F.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/0871.clip_5F00_image008_5F00_thumb_5F00_4FB4543F.jpg" width="624" height="622" /></a></p>  <h2>SQL Database</h2>  <p>Si por el contrario se tiene una base de datos SQL Azure, en mi caso una base de datos P2 de 250DTUs también se puede obtener información muy útil de la base de datos:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3527.clip_image009_2D5F4F77.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3527.clip_5F00_image009_5F00_2D5F4F77.png"><img title="clip_image009" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image009" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2308.clip_image009_thumb_3AC5627D.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2308.clip_5F00_image009_5F00_thumb_5F00_3AC5627D.png" width="581" height="215" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6445.clip_image010_68468240.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6445.clip_5F00_image010_5F00_68468240.png"><img title="clip_image010" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image010" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1351.clip_image010_thumb_4A67FE3F.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1351.clip_5F00_image010_5F00_thumb_5F00_4A67FE3F.png" width="589" height="880" /></a></p>  <p>Por la información de las gráficas se puede ver que la base de datos está trabajando a toda potencia. </p>  <h2>Cloud Services</h2>  <p>Si se tiene desplegados Cloud Services también se puede aprovechar de esta información pero agregada de todas las máquinas que se tengas desplegadas. En mi caso dos instancias. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3755.clip_image011_6C5360C3.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3755.clip_5F00_image011_5F00_6C5360C3.png"><img title="clip_image011" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image011" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2671.clip_image011_thumb_2E59D005.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2671.clip_5F00_image011_5F00_thumb_5F00_2E59D005.png" width="590" height="890" /></a></p>  <p>En este escenario los workers no son muy intensivos en CPU pero si mucho en red.</p>  <h1>Personalizar el dashboard</h1>  <p>Otra de las características del portal es que puedas mostrar esas piezas de información en el portal para configurar el aspecto a tu gusto y mostrar la información que es relevante para ti. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4846.clip_image013_09C84281.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4846.clip_5F00_image013_5F00_09C84281.jpg"><img title="clip_image013" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image013" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3704.clip_image013_thumb_3DFC6BC7.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3704.clip_5F00_image013_5F00_thumb_5F00_3DFC6BC7.jpg" width="623" height="375" /></a></p>  <p>Con lo que un vistazo se puede acceder a información que es relevante para cada usuario que inicia sesión en el portal.</p>  <h1>¿Cómo se extrae la información de las máquinas?</h1>  <p>Para que esta información esté disponible en el portal, Microsoft instala en las máquinas invitadas un agente que se encarga de recopilar esta información. En el caso de Windows utiliza la infraestructura de contadores de rendimiento para obtener esa información. Cuando se provisiona una máquina virtual Windows se añade una extensión llamada Microsoft.Azure.Diagnostics.IaaSDiagnostics que es la que se encarga de comunicarse con el controlador del Fabric de Azure. Este servicio recopila la información y la almacena en una cuenta de Azure Storage que se ha especificado durante la provisión de la VM.</p>  <p>En el caso de una máquina Linux, los contadores de rendimiento no existen, con lo que hay que utilizar otro mecanismo para obtener la información de rendimiento de la VM. También se instala una extensión que se encarga de recopilar esa información llamada Microsoft.OSTCExtensions.LinuxDiagnostic. Que en última instancia añade un demonio de Linux escrito en Python que se llamad waagent, el cual está disponible el código fuente en GitHub <a href="https://github.com/Azure/WALinuxAgent">https://github.com/Azure/WALinuxAgent</a></p>  <p>Luis Guerrero</p>  <p>Technical Evangelist Microsoft Azure</p>  <p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Creando aplicaciones multi tenant en Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/creando-aplicaciones-multi-tenant-en-azure</link>
      <pubDate>Thu, 08 Oct 2015 04:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/10/08/creando-aplicaciones-multi-tenant-en-azure/</guid>
      <description><![CDATA[Con la explosi&oacute;n de las soluciones del Cloud las aplicaciones se tienen que adecuar a este...]]></description>
      <content:encoded><![CDATA[<p>Con la explosi&oacute;n de las soluciones del Cloud las aplicaciones se tienen que adecuar a este nuevo modelo de desarrollo. En este art&iacute;culo se va a presentar una soluci&oacute;n te&oacute;rica, con un ejemplo en ASP.NET de c&oacute;mo crear una arquitectura multitenancy utilizando los servicios de Azure. Aunque esta soluci&oacute;n tiene un ejemplo con una tecnolog&iacute;a de Microsoft, es perfectamente v&aacute;lido para otros lenguajes como Java, PHP, Node.js, ect pero se har&iacute;a de otra manera.</p>
<h1>Un poco de historia</h1>
<p>Para entender por qu&eacute; son necesarias este tipo de arquitecturas ahora mismo hay que entender que soluciones se creaban antes del Cloud. Estas soluciones no son muy diferentes de las que se generan en el Cloud pero hay que tener en cuenta lo f&aacute;cil y sencillo que es crear servicios y consumirlos en el Cloud para entender este modelo.</p>
<p>Si se piensa en un despliegue t&iacute;pico de una soluci&oacute;n web que utilice un servidor de base de datos ser&iacute;a algo parecido a esto:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4314.clip_image001_34F6BBFB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4314.clip_5F00_image001_5F00_34F6BBFB.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="clip_image001" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3034.clip_image001_thumb_7DB034BF.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3034.clip_5F00_image001_5F00_thumb_5F00_7DB034BF.png" alt="clip_image001" width="640" height="377" border="0" /></a></p>
<h2>Web Frontent</h2>
<p>Una aplicaci&oacute;n ASP.NET donde todos los usuarios acceden a la misma url www.contoso.com de servicio e inician sesi&oacute;n con sus credenciales. Esta aplicaci&oacute;n consume servicios que el servidor de aplicaciones expone donde est&aacute; la l&oacute;gica de negocio del frontal web y finalmente esos datos est&aacute;n almacenados en la base de datos.</p>
<h4>Base de datos</h4>
<p>El esquema de la base de datos no es importante en s&iacute;, pero hay que tener en cuenta como se han dado de alta a los diferentes clientes. Normalmente se tendr&iacute;a una tabla que representa a los clientes dados de alta en el servicio y se hacen relaciones con otras tablas para saber qu&eacute; datos son espec&iacute;ficos de cada cliente. El esquema podr&iacute;a ser algo as&iacute;.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7522.clip_image003_1F2F644F.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7522.clip_5F00_image003_5F00_1F2F644F.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="clip_image003" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1106.clip_image003_thumb_0150E04E.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1106.clip_5F00_image003_5F00_thumb_5F00_0150E04E.jpg" alt="clip_image003" width="250" height="330" border="0" /></a></p>
<p>Como se puede observar en el diagrama, se utiliza un discriminador para filtrar los datos que son espec&iacute;ficos de un cliente. Siempre se realiza la asociaci&oacute;n utilizando la tabla clientes para tener una relaci&oacute;n entre tablas que permita mantener una integridad referencial. Los datos que hay en las tablas son datos de todos los clientes en todo momento.</p>
<h2>Rendimiento</h2>
<p>Con este modelo de desarrollo todos los usuarios finales operan dentro de la misma base de datos, pero en filas diferentes, lo que permite acceder de forma concurrente. Pero al estar todos los usuarios utilizando la misma base de datos el grado de concurrencia de las tablas es bastante grande.</p>
<p>Conforme el n&uacute;mero de usuarios va creciendo la concurrencia en la base de datos aumenta. Pero este crecimiento no es lineal, es decir, que algunos clientes grandes tendr&aacute;n un impacto en el rendimiento de la base de datos m&aacute;s grande que otros clientes m&aacute;s peque&ntilde;os, haciendo que todos tengan la misma experiencia.</p>
<h1>Multi-tenant</h1>
<p>Aqu&iacute; es donde se puede introducir el concepto de multi tenant. La idea es bastante sencilla, en vez de tener una base de datos para todos los clientes, se tiene una base de datos con el mismo esquema para cada cliente.</p>
<h2>Ventajas</h2>
<p>Con este mecanismo en el que se tiene una base de datos por cada cliente, permite que si se est&aacute; usando Azure SQL como base de datos, se pueda escalar cada base de datos de forma independiente entre los clientes consiguiendo as&iacute; distintos niveles de servicio. De esta manera si se tiene un cliente muy grande con muchos usuarios se podr&aacute; elegir una base de datos P4 de 500 DTU y si tiene un cliente peque&ntilde;o una edici&oacute;n S1 de 20 DTU, pero ambas bases de datos tienen el mismo esquema. De esta manera el coste de operaciones relacionadas con el servicio se puede predecir y se puede cambiar en base a las necesidades del cliente, ya que, Azure SQL permite cambiar de nivel hacia arriba y hacia abajo en todo momento.</p>
<p>Adem&aacute;s, se pueden tener escenarios de testeo A/B con los clientes para futuras versiones de la aplicaci&oacute;n, haciendo as&iacute; que los clientes puedan tener diferentes versiones de la aplicaci&oacute;n.</p>
<h2>Inconvenientes</h2>
<p>El modelo multi-tenant no son s&oacute;lo ventajas, sino que tambi&eacute;n plantea ciertos desaf&iacute;os. Uno de los m&aacute;s importantes es la estrategia de actualizaci&oacute;n de los esquemas / datos de las bases de datos. Como es sabido, con bases de datos en producci&oacute;n con clientes accediendo al sistema, hacer modificaciones en el esquema de la base de datos puede ser un proceso doloroso, si eso lo multiplicamos por todas las bases de datos, el problema puede ser enorme.</p>
<p>En ese sentido, herramientas como Entity Framework Code First y su tecnolog&iacute;a de migraciones, hacen posible que cada cambio en el esquema se pueda hacer hacia adelante y hacia atr&aacute;s de forma pseudo automatizada.</p>
<p>En los escenarios de Cloud la clave siempre es la automatizaci&oacute;n, piense por ejemplo cual ser&iacute;a el proceso de provisiona un nuevo cliente, se deber&iacute;a de crear una base datos vac&iacute;a, y en el caso de que se utilice Entity Framework actualizar la base de datos de destino con el esquema y datos necesarios.</p>
<h1>Implementaci&oacute;n</h1>
<p>Para hacer posible que este escenario hay que hacer ciertas modificaciones en el c&oacute;digo fuente para dar cabida a este escenario.</p>
<p>El primer cambio de todos consiste en tener un mecanismo que permita identificar al usuario. Este mecanismo se puede implementar de varias maneras, como por ejemplo a trav&eacute;s de la url. En este ejemplo:<a href="http://cliente1.miservicio.com/">http://cliente1.miservicio.com/</a> o <a href="http://www.miservicio.com/cliente1">http://www.miservicio.com/cliente1</a></p>
<p>En ambas urls, el nombre del cliente forma parte de la url que permite que desde la tecnolog&iacute;a de servidor que elijamos seamos capaces de identificar el cliente. Esto tambi&eacute;n se puede hacer a trav&eacute;s de una cookie que se establezca en el proceso de login del usuario final.</p>
<h2>&iquest;Para qu&eacute; se necesita identificar al cliente?</h2>
<p>En el desarrollo tradicional que se introduc&iacute;a al principio del art&iacute;culo, normalmente la cadena de conexi&oacute;n a la base de datos ser&iacute;a una constante en el c&oacute;digo fuente o el fichero de configuraci&oacute;n. En el caso de ASP.NET el fichero web.config.</p>
<p>Pero en este nuevo escenario la cadena de conexi&oacute;n cambia dependiendo del cliente que este consumiendo el servicio, con lo que tener una &uacute;nica cadena de conexi&oacute;n no es algo que funcione a priori.</p>
<p>Lo que hay que hacer es, en el paso m&aacute;s temprano del ciclo de vida de una petici&oacute;n http identificar al cliente, ir a una base de datos de infraestructura a buscar los datos de conexi&oacute;n del cliente y establecer esa informaci&oacute;n de forma ambiental durante toda esa petici&oacute;n. De esta manera cuando se quiera establecer una conexi&oacute;n con la base de datos, no se lee el valor de configuraci&oacute;n, sino que se obtiene de esta variable ambiental.</p>
<h1>Base de datos de infraestructura</h1>
<p>En el p&aacute;rrafo anterior se especificaba que hay que usar una base de datos de infraestructura. Esta base de datos, que ser&aacute; com&uacute;n a todos los clientes contiene informaci&oacute;n del propio servicio, es decir, que clientes est&aacute;n provisionados y cuantos usuarios tienen asociados al servicio. De esa manera en esa base de datos se encontrar&aacute; una tabla llamada Clients, donde cada una de las filas representa uno de los clientes provisionados. Un posible ejemplo ser&iacute;a este:</p>
<table class="MsoTable15List3Accent6" style="border-collapse: collapse; mso-border-alt: solid #70ad47 .5pt; mso-border-themecolor: accent6; mso-yfti-tbllook: 1184; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; border-style: none;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes; mso-yfti-lastfirstrow: yes;">
<td style="border-top: #70ad47 1pt solid; width: 70.75pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; border-left: #70ad47 1pt solid; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-left-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-left-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 517;"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">Id</span></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.75pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 1;"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">Nombre</span></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 1;"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">Base de datos</span></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 1;"><span class="SpellE"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">Version</span></strong></span><strong></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 1;"><span class="SpellE"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">DateCreated</span></strong></span><strong></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; border-right: #70ad47 1pt solid; width: 70.8pt; background: #70ad47; border-bottom-style: none; padding-bottom: 0cm; padding-top: 0cm; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-background-themecolor: accent6; mso-border-right-themecolor: accent6; mso-border-right-alt: solid #70ad47 .5pt;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 1;"><span class="SpellE"><strong><span style="color: white; mso-themecolor: background1;" lang="ES">LastTimeSchemaUpdated</span></strong></span><strong></strong></p>
</td>
</tr>
<tr style="mso-yfti-irow: 0; mso-yfti-lastrow: yes;">
<td style="border-top: #70ad47 1pt solid; border-right: #70ad47 1pt; width: 70.75pt; background: white; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; padding-left: 5.4pt; border-left: #70ad47 1pt solid; padding-right: 5.4pt; mso-border-themecolor: accent6; mso-border-top-themecolor: accent6; mso-border-left-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-left-alt: solid #70ad47 .5pt; mso-background-themecolor: background1; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 68;"><strong><span lang="ES">3</span></strong></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.75pt; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 64;"><span lang="ES">Cliente1</span></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 64;"><span class="SpellE"><span lang="ES">Connstring</span></span></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 64;"><span lang="ES">21</span></p>
</td>
<td style="border-left-style: none; border-top: #70ad47 1pt solid; width: 70.8pt; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; border-right-style: none; padding-left: 5.4pt; padding-right: 5.4pt; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 64;"><span lang="ES">09/10/2015</span></p>
</td>
<td style="border-top: #70ad47 1pt solid; border-right: #70ad47 1pt solid; width: 70.8pt; border-bottom: #70ad47 1pt solid; padding-bottom: 0cm; padding-top: 0cm; padding-left: 5.4pt; border-left: #70ad47 1pt; padding-right: 5.4pt; mso-border-themecolor: accent6; mso-border-top-themecolor: accent6; mso-border-top-alt: solid #70ad47 .5pt; mso-border-right-themecolor: accent6; mso-border-right-alt: solid #70ad47 .5pt; mso-border-bottom-alt: solid #70ad47 .5pt; mso-border-bottom-themecolor: accent6;" valign="top" width="142">
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-yfti-cnfc: 64;"><span lang="ES">21/09/2015</span></p>
</td>
</tr>
</tbody>
</table>
<p>De esta manera con el mecanismo anterior de identificaci&oacute;n lo que hay que hacer es buscar una fila en la que el nombre cliente coincida con el segmento de la url. Cuando se encuentre el cliente, el siguiente paso es establecer el valor de la cadena de conexi&oacute;n en una variable que se pueda usar durante toda la petici&oacute;n.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2605.clip_image005_310E88CD.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2605.clip_5F00_image005_5F00_310E88CD.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="clip_image005" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2352.clip_image005_thumb_0EB98405.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2352.clip_5F00_image005_5F00_thumb_5F00_0EB98405.jpg" alt="clip_image005" width="851" height="706" border="0" /></a></p>
<h1>Demo en ASP.NET</h1>
<p>Para implementar el ejemplo de multi-tenant en ASP.NET utilizando el patr&oacute;n de urls basads en http://www.miservicio.com/cliente1 (esto se puede cambiar en cualquier momento), se podr&iacute;a hacer de esta manera.</p>
<p>En el ciclo de vida de una petici&oacute;n de ASP.NET hay un evento que se produce cuando empieza la petici&oacute;n que es el momento adecuado para detectar, que cliente es e ir a la base de datos de infraestructura para detectar la cadena de conexi&oacute;n a la base de datos.</p>
<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; font-family: 'Courier New', courier, monospace; width: 97.5%; direction: ltr; text-align: left; margin: 20px 0px 10px; line-height: 12pt; max-height: 200px; background-color: #f4f4f4; border: silver 1px solid; padding: 4px;">
<pre id="codeSnippet" style="font-size: 8pt; overflow: visible; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> OnBeguinRequest(<span style="color: #0000ff;">object</span> sender, EventArgs e)<br />{<br />    HttpContext context = HttpContext.Current;<br />    var clientId = context.Request.Url.Segments.LastOrDefault();<br />    <span style="color: #0000ff;">using</span> (MultitenantDbContext dbContext = <span style="color: #0000ff;">new</span> MultitenantDbContext())<br />    {<br />        var client = dbContext.TentanUsers<br />            .Where(p =&gt; p.Name == clientId)<br />            .Select(p =&gt; p).FirstOrDefault();<br />        <span style="color: #0000ff;">if</span> (client != <span style="color: #0000ff;">null</span>)<br />        {<br />            context.Items[ClientConnnextionStringKey] = client.ConnnectionString;<br />        }<br />        <span style="color: #0000ff;">else</span><br />        {<br />            <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> InvalidOperationException(<span style="color: #006080;">"Client not found"</span>);<br />        }<br />    }<br />}</pre>
</div>
<p>As&iacute; de esta manera, en un &uacute;nico punto se detecta el cliente, se almacena esa informaci&oacute;n en la colecci&oacute;n de elementos de contexto de Http actual de ASP.NET. En otro tipo de lenguajes o runtimes, la forma de hacer esto, puede variar, pero la idea es la misma.</p>
<p>El siguiente paso es utilizar esta cadena de conexi&oacute;n en el punto que sea necesario, por ejemplo en un controlador donde que se quiera acceder a datos para un determinado cliente.</p>
<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; font-family: 'Courier New', courier, monospace; width: 97.5%; direction: ltr; text-align: left; margin: 20px 0px 10px; line-height: 12pt; max-height: 200px; background-color: #f4f4f4; border: silver 1px solid; padding: 4px;">
<pre id="codeSnippet" style="font-size: 8pt; overflow: visible; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">public</span> ActionResult Index()<br />{<br />    <span style="color: #0000ff;">string</span> connextionString = <br />    (<span style="color: #0000ff;">string</span>)<span style="color: #0000ff;">this</span>.HttpContext.Items[MvcApplication.ClientConnnextionStringKey];<br />    <span style="color: #0000ff;">using</span> (ClientDbContext context = <span style="color: #0000ff;">new</span> ClientDbContext(connextionString))<br />    {<br /><br />    }<br />    <span style="color: #0000ff;">return</span> View();<br />}</pre>
</div>
<h1>Conclusiones</h1>
<p>Esta es una primera aproximaci&oacute;n para un escenario multi tenant. A partir de aqu&iacute; se puede evolucionar el concepto, para un despliegue m&aacute;s complejo. Como se coment&oacute; al principio del art&iacute;culo, gracias a la <a href="https://msdn.microsoft.com/en-us/library/azure/ee460799.aspx">API de administraci&oacute;n del portal de Azure</a>, se puede automatizar el proceso de creaci&oacute;n de las base de datos de SQL Azure en el caso de que se tenga que provisionar un nuevo cliente.</p>
<p>Luis Guerrero Guirado.</p>
<p>Technical Evangelist Microsoft Azure.</p>
<p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Entendiendo la estrategia de particionado de Azure Storage Blobs</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/entendiendo-la-estrategia-de-particionado-de-azure-storage-blobs</link>
      <pubDate>Tue, 01 Sep 2015 09:34:03 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/09/01/entendiendo-la-estrategia-de-particionado-de-azure-storage-blobs/</guid>
      <description><![CDATA[Todos los servicios de Azure de una manera o de otra utilizan el concepto de particionado a la hora...]]></description>
      <content:encoded><![CDATA[<p>Todos los servicios de Azure de una manera o de otra utilizan el concepto de <a href="https://en.wikipedia.org/wiki/Partition_(database)">particionado</a> a la hora de operar. Es importante entender cómo operan las estrategias de particionado para que el software y servicios que se construyan por encima de ellos funcionen de la mejor manera. </p>  <h1>Cómo funciona el servicio de Azure Storage Blobs</h1>  <p>Como cualquier otro servicio de Azure Storage utiliza una API REST que permite interactuar con el servicio. La URL define el recurso al que se quiere acceder.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6153.clip_image002_30C40644.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6153.clip_5F00_image002_5F00_30C40644.jpg"><img title="clip_image002" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2816.clip_image002_thumb_204B9549.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2816.clip_5F00_image002_5F00_thumb_5F00_204B9549.jpg" width="602" height="336" /></a></p>  <p>Como se puede observar en la imagen hay tres tipos de artefactos. La cuenta, el contendor y el nombre del fichero. Estos tres artefactos serán los que tengan la responsabilidad de orquestar correctamente el acceso al servicio, y en el caso de este artículo, el particionado. </p>  <h1>¿Por qué es importante el particionado?</h1>  <p>Cuando se construye un servicio en la nube, uno de los aspectos importantes es la escalabilidad y el rendimiento del mismo. Cuando se tiene un servicio que acepta millones de peticiones cada hora, hay que tener en cuenta como el servicio va a responder bajo esa demanda de operación. </p>  <p>En ese sentido, la misma lógica impera cuando se diseña un servicio para on-premises. Imagina por un momento que todas peticiones de tu aplicación web están siendo servidas por la misma máquina, en vez de tener un sistema que distribuya las peticionas a través de unos recursos preexistentes de máquinas que contengan tu mismo recurso. Ese mismo concepto es el que hay detrás del particionado, es involucrar a diferentes servidores físicos para que ejecuten la operación que el usuario ha solicitado. Conforme más servidores, menos será la latencia y mayor la capacidad de respuesta del servicio. </p>  <h1>El esquema de las direcciones de Storage Blob</h1>  <p>En formato de las urls de Azure Storage Blob se puede resumir en dos opciones principalmente.</p>  <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">   <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">https://myaccount.blob.core.windows.net/mycontainer/myblob.jpg</pre>

  <br /></div>

<p>En esta primera opción el nombre del contenedor de mycontiner y el nombre del blob es myblob.jpg. Los nombres de los contenedores no pueden contener caracteres en mayúscula, así que solo puede ser en minúscula.</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">https://myaccount.blob.core.windows.net/mycontainer/1/2/3/file.txt </pre>

  <br /></div>

<p>En este ejemplo el nombre del contenedor es igual mycontainer, pero el nombre del fichero es 1/2/3/file.txt. Es decir, el nombre del blob contiene también las barras simulando un sistema de archivo.</p>

<h2>¿Cómo son las particiones calculadas?</h2>

<p>Si se lee la documentación oficinal de producto, <a href="http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/windows-azure-storage-abstractions-and-their-scalability-targets.aspx">http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/windows-azure-storage-abstractions-and-their-scalability-targets.aspx</a>, se comenta que la partición para lo blobs se calcula en base al nombre del contenedor + nombre del blob. Es decir, que, para nuestro ejemplo anterior, sería mycontainer + myblob.jpg. </p>

<p>Así que peticiones que tengan diferentes llaves de partición serán distribuidas a través de diferentes servidores. El único inconveniente es que pierde la capacidad de hacer transacciones atómicas entre múltiples blobs. </p>

<p>Entendiendo esto, ahora surge la siguiente pregunta, que es clave para entender el algoritmo de particionado. </p>

<h2>¿Cómo tengo que nombrar mis blobs para maximizar el uso de particiones?</h2>

<p>La estrategia de nombre debería de ser algo como esto:</p>

<p>a/b/c/d/e/f/{n}/file.txt</p>

<p>Siendo {n} el elemento que se va incrementando en el tiempo y que permite a los servidores de partición de Azure Storage almacenar correctamente los blobs de tu cuenta de almacenamiento. El orden de {n} es lexicográfico, con lo que te interesa que vaya incrementándose en base de los caracteres, también tiene como consecuencia que se no se calcula en base a un hash. Por cambiar un valor no vas a tener una partición completamente diferente, sino que posiblemente será la misma.</p>

<p>En el siguiente ejemplo se muestra un posible esquema y cómo utilizarlo. </p>

<p>Si para generar esa secuencia de elemento de {n} se utiliza la fecha para ir incrementando el nombre de los blobs, se tendría algo como esto:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br />30 de agosto del 2015<br />mycontainer/1/2/20150830/(Guid.NewGuid()).txt &lt;- Todas las transacciones <br />de Storage irían aquí, a un servidor de particiones<br />31 de agosto del 2015<br />mycontainer/1/2/20150830/(Guid.NewGuid()).txt &lt;- este path ya no es usado <br />por el servidor de particiones<br />mycontainer/1/2/20150831/(Guid.NewGuid()).txt &lt;- Todas las transacciones <br />de Storage irían aquí, a un servidor de particiones<br />1 de septiembre del 2015<br />mycontainer/1/2/20150830/(Guid.NewGuid()).txt &lt;- este path ya no es usado <br />por el servidor de particiones<br />mycontainer/1/2/20150831/(Guid.NewGuid()).txt &lt;- este path ya no es usado <br />por el servidor de particiones<br />mycontainer/1/2/20150701/(Guid.NewGuid()).txt &lt;- Todas las transacciones <br />de Storage irían aquí, a un servidor de particiones</pre>

  <br /></div>

<p>Las peticiones se distribuirían de la manera antes expuesta, y aunque se ha utilizado un valor incremental para el nombre del blob, es se te ha hecho de manera que los servidores de particionado no lo utilizan y al final utiliza todos el mismo servidor. Con lo que si se tuviera que haber leído esos tres ficheros en el mismo día, el mismo servidor respondería y el rendimiento del servicio se vería afectado.</p>

<p>Sin embargo, si se utiliza este otro mecanismo para nombrar a los blobs:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br />mycontainer/1/2/1/(Guid.NewGuid).txt<br />mycontainer/1/2/2/(Guid.NewGuid).txt<br />mycontainer/1/2/3/(Guid.NewGuid).txt<br />mycontainer/1/2/4/(Guid.NewGuid).txt</pre>

  <br /></div>

<p>Incluso poniendo un prefijo previo al nombre del fichero:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br />mycontainer/1/2/1/Storage(Guid.NewGuid).txt<br />mycontainer/1/2/2/Storage(Guid.NewGuid).txt<br />mycontainer/1/2/3/Storage(Guid.NewGuid).txt<br />mycontainer/1/2/4/Storage(Guid.NewGuid).txt</pre>

  <br /></div>

<p>Se conseguiría que, para acceder a esos cuatro ficheros, que hasta 4 servidores se involucrasen en las respuestas haciendo que los tiempos de repuesta fuera mucho menores. </p>

<p>También se puede utilizar una estrategia con la fecha del día, pero en vez de poner solamente el año, el mes y el día, se debería de utilizar el valor en ticks de la fecha, pero para asegurarte de que se hace una distribución sobre un 10% del total, se le da la vuelta al valor del string que representa los ticks, y se tendría algo como esto:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br />Valor en Ticks de la hora: 635767287458393685<br />Valor del revés:           586393854782767536<br />Valor en Ticks de la hora: 635767287468351710<br />Valor del revés:           017153864782767536</pre>

  <br /></div>

<p>Se puede observar que la parte de la izquierda de los valores del revés, son los caracteres de la derecha de la fecha, que son los valores que más oportunidad tienen de cambiar conforme avanza el tiempo. </p>

<p>De esta manera se tiene una evolución de que todos los ficheros que se agreguen tendrán una distribución del 10% sobre los demás.</p>

<h1>Conclusión</h1>

<p>Elegir una buena estrategia de particionado lo es todo para conseguir el mejor resultado del servicio. Dependiendo del tipo de aplicación que se esté desarrollando eso puede ser crítico o no, así que merece la pena dedicarle un poco de tiempo para entender cómo afectará eso al servicio. </p>

<p>Luis Guerrero.</p>

<p>Technical Evangelist Microsoft Azure</p>

<p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Curiosidades sobre la versión de Ubuntu de Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/curiosidades-sobre-la-versin-de-ubuntu-de-azure</link>
      <pubDate>Tue, 19 May 2015 06:06:31 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/05/19/curiosidades-sobre-la-versin-de-ubuntu-de-azure/</guid>
      <description><![CDATA[Hoy mientras estaba instalando un paquete en una instancia de una máquina virtual que tengo en...]]></description>
      <content:encoded><![CDATA[<p>Hoy mientras estaba instalando un paquete en una instancia de una máquina virtual que tengo en Azure, me ha llamado la atención el hecho de que el gestor de paquetes de <a href="http://en.wikipedia.org/wiki/Advanced_Packaging_Tool">apt-get</a> estaba descargándose los paquetes de esta url </p>  <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">   <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">http://azure.archive.ubuntu.com/ubuntu/ vivid-updates/main </pre>

  <br /></div>

<p>Esta url no es la estándar que se suele utilizar en la distribución de Ubuntu ya que la estándar es: </p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">http://archive.ubuntu.com/ubuntu/ vivid-updates/main</pre>

  <br /></div>

<p>Microsoft ha personalizado la imagen de Ubuntu para que se descargue las imágenes de ese servidor que tienen un tramo de Azure. Si se hace un petición con nslookup para esa dirección DNS.</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">C:\Users\&gt;nslookup azure.archive.ubuntu.com<br /><br />Server:<br />Address:<br /><br />Non-authoritative answer:<br />    Name: ubu-n-eur.cloudapp.net<br />    Address: 168.63.58.192<br />    Aliases: azure.archive.ubuntu.com<br />             ubuntu-archive.trafficmanager.net</pre>

  <br /></div>

<p>Al final de todo aparece que uno de los alias de esta dirección DNS es ubuntu-archive.trafficmanager.net esta dirección forma parte del servicio de Traffic Manager, que permite distribuir el trafico dependiendo de varias opciones. </p>

<p><a href="http://azure.microsoft.com/en-us/services/traffic-manager/">http://azure.microsoft.com/en-us/services/traffic-manager/</a></p>

<p>Así la gente que utiliza las maquinas virutales de Ubuntu internamente en Azure, tienen en el datacenter local donde se conectan una copia de los archivos de Ubuntu, ahorrando tráfico de Internet y recursos. </p>





<p>Luis Guerrero.</p>

<p>Technical Evangelist Microsoft Azure.</p>

<p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Cómo empezar a trabajar con Vorlon.js y ¿Qué hay detrás de este nombre tan extraño?</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/cmo-empezar-a-trabajar-con-vorlon-js-y-qu-hay-detrs-de-este-nombre-tan-extrao</link>
      <pubDate>Tue, 19 May 2015 04:11:24 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/05/19/cmo-empezar-a-trabajar-con-vorlon-js-y-qu-hay-detrs-de-este-nombre-tan-extrao/</guid>
      <description><![CDATA[Vorlon.js es una librería Open Source, con licencia MIT, desarrollador por Microsoft, independiente...]]></description>
      <content:encoded><![CDATA[<p>Vorlon.js es una librería Open Source, con licencia MIT, desarrollador por Microsoft, independiente de la plataforma que te permite depurar y testear remotamente JavaScript. Está basado en node.js y socket.io.</p>  <p>Esto es lo que aparecen como descripción en el <a href="https://github.com/MicrosoftDX/Vorlonjs/">GitHub</a> oficial de proyecto donde se puede encontrar el proyecto de código fuente. Pero Vorlon.js es mucho más y en este artículo se va a mostrar cómo empezar a trabajar y crear plugins para proyectos concretos. </p>  <h1>Instalación</h1>  <p>Vorlon.js es una librería disponible en <a href="https://www.npmjs.com/">npm</a> (el gestor de paquetes de node.js) y como tal la forma de instalarse es a través de este gestor de paquetes.</p>  <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">   <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">$ npm i -g vorlon</pre>

  <br /></div>

<p>Una vez que se ha instalado Vorlon.JS a nivel global el siguiente paso es ejecutarlo para poder acceder al dashboard de Vorlon.JS.</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">$ vorlon<br />The Vorlon server <span style="color: #0000ff">is</span> running</pre>

  <br /></div>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3755.clip_image002_4337FDA5.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3755.clip_5F00_image002_5F00_4337FDA5.jpg"><img title="clip_image002" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7485.clip_image002_thumb_3568485B.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7485.clip_5F00_image002_5F00_thumb_5F00_3568485B.jpg" width="602" height="371" /></a></p>

<p>Esta es una captura del dashboard de Volor.JS ejecutándose en local. Al estar basado en node.js y en socket.io se puede ejecutar en cualquier entorno independientemente del tipo de sistema operativo. </p>

<h1>Depurando una aplicación web</h1>

<p>El siguiente paso con Vorlon.JS ya que el dashboard se está ejecutando es depurar una aplicación web, para hacer eso Vorlon.JS utiliza socket.io para crear un canal persistente entre la aplicación web de destino y el servidor de Vorlon.JS. </p>

<p>Así que la manera para inyectar el código es añadiendo una referencia de la librería de Vorlon.JS en la web que se quiera depurar. En el contexto de esta demo que ese está haciendo, el servidor se está ejecutando en <a href="http://localhost:1337/">http://localhost:1337/</a> por lo que la librería está en</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">http://localhost:1337/vorlon.js</pre>

  <br /></div>

<p>Esta es la dirección que se tiene que agregar en la aplicación web para empezar a depurarla. En este ejemplo voy a crear una nueva aplicación de ASP.NET MVC desde Visual Studio 2015 para hacer la prueba de cómo depurar una aplicación web.</p>

<p>Antes de continuar con la demo, comentar que al ser Vorlon.JS una aplicación hecha en node.js este servidor se puede ejecutar en cualquier máquina, local o incluso de nube. Por ejemplo, se puede tener desplegado en Azure utilizando una máquina virtual de Ubuntu, en la que se ejecuta el servidor. Así todo el equipo puede utilizar esa máquina para poder depurar.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3125.clip_image004_4262286C.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3125.clip_5F00_image004_5F00_4262286C.jpg"><img title="clip_image004" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7532.clip_image004_thumb_40283061.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7532.clip_5F00_image004_5F00_thumb_5F00_40283061.jpg" width="601" height="470" /></a></p>

<h4>Depurando la primera web</h4>

<p>En este caso lo que hay que hacer es en el fichero del proyecto de ASP.NET localizado en Views/Shared/_Layout.cshtml es incluir esta referencia para que se pueda depurar esta aplicación en concreto.</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">&lt;script type=<span style="color: #006080">&quot;text/javascript&quot;</span> <br />src=<span style="color: #006080">&quot;http://vorlonjs-server.cloudapp.net/vorlon.js&quot;</span> &gt;<br />&lt;/script&gt;</pre>

  <br /></div>

<p>A partir de ese instante en la consonla de Vorlon.JS aparecerá identificado el cliente y se podrán acceder a características concretas. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6327.clip_image006_4D221072.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6327.clip_5F00_image006_5F00_4D221072.jpg"><img title="clip_image006" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7318.clip_image006_thumb_389F51A5.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7318.clip_5F00_image006_5F00_thumb_5F00_389F51A5.jpg" width="601" height="366" /></a></p>

<h1>Características de Vorlon.JS</h1>

<p>Estas son las características que Vorlon.JS ofrece actualmente:</p>

<h2>DOM Explorer</h2>

<p>Un explorador del árbol de objetos del navegador, permitiendo que se pueda mostrar todo los nodos que actualmente están en la aplicación, es decir, que si se produce un cambio en los nodos, se añaden o se modifican, esos cambios aparecerán en la consola igualmente. </p>

<p>Si se selecciona un elemento, se puede mostrar información sobre los pares de nombre valor de los estilos que se están aplicando actualmente. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2475.clip_image008_613DBDAC.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2475.clip_5F00_image008_5F00_613DBDAC.jpg"><img title="clip_image008" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7608.clip_image008_thumb_70E0596E.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7608.clip_5F00_image008_5F00_thumb_5F00_70E0596E.jpg" width="601" height="366" /></a></p>

<p>Además, en el menú de la derecha se pueden añadir nuevas propiedades para en el caso de querer aplicar una nueva propiedad se puede hacer desde ahí, y ese cambio se aplicará directamente sobre ese elemento de la aplicación que se está depurando. </p>

<p>Cuando se selecciona un elemento del nodo en el dashboard de Vorlon.JS este elemento se destaca en la Web de origen para tener claro que se está seleccionando. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4428.clip_image010_327A95BB.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4428.clip_5F00_image010_5F00_327A95BB.jpg"><img title="clip_image010" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image010" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7585.clip_image010_thumb_700A8435.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7585.clip_5F00_image010_5F00_thumb_5F00_700A8435.jpg" width="602" height="503" /></a></p>

<h2>Modernizr</h2>

<p>La siguiente pestaña se trata de Modernizr, una librería de JavaScript que permite comprobar características concretas que soporta el navegador. En vez que detectar si el navegador es Internet Explorer, Microsoft Edge, Google Chrome o Mozilla Firefox, lo que se hace es preguntar sobre una característica en concreto, como por ejemplo si soporta la etiqueta canvas de HTML5. </p>

<p>Pues bien, esta pestaña inyecta en la web, Modernirz con todas las opciones y analiza que características dispone en navegador donde se está ejecutando esta aplicación. Esto puede ser muy útil, si se está desarrollando aplicaciones web para dispositivos móviles y se desea saber las características del navegador donde se está ejecutando la aplicación. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/7028.clip_image012_18A8F03D.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/7028.clip_5F00_image012_5F00_18A8F03D.jpg"><img title="clip_image012" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/3733.clip_image012_thumb_284B8BFF.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/3733.clip_5F00_image012_5F00_thumb_5F00_284B8BFF.jpg" width="601" height="366" /></a></p>

<h2>Object Explorer</h2>

<p>La ultima pestaña puede ser una de las más útiles de todo Vorlon.JS porque permite mostrar todos los objetos de JavaScript que se encuentra a nivel de window. Esto resulta tremendamente útil, si se está desarrollando una aplicación web en la que JavaScrip tiene una presencia muy fuerte y alguno de los objetos no se ha inicializado correctamente y se desea ver el estado. Por ejemplo, si está haciendo una operación y sé que quiere saber cuál es el estado del objeto una vez ejecutada esta operación, se puede utilizar la parte del filtrado para buscar ese objeto por el nombre y así ver el valor de los campos de ese objeto. </p>

<p>También permite saber que funciones tienen los objetos del navegador, </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2768.clip_image013_65DB7A79.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2768.clip_5F00_image013_5F00_65DB7A79.png"><img title="clip_image013" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image013" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1641.clip_image013_thumb_4EAFFFFB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1641.clip_5F00_image013_5F00_thumb_5F00_4EAFFFFB.png" width="283" height="487" /></a></p>

<p>Por ejemplo, en esta captura de pantalla se está mostrando los métodos que contiene el objeto console disponible para Internet Explorer 11 en Windows 10, así los desarrolladores podrían saber que funciones dispone un navegador, de un dispositivo móvil. </p>

<h1>Vorlon.js en dispositivos móviles</h1>

<p>Como se ha comentado en varias ocasiones una de las cosas más interesantes de Vorlon.JS es poder utilizarlo para depurar aplicaciones web en dispositivos móviles, por eso se ha utilizado un Nokia Lumia 1520 ejecutando Windows 10 Mobile (Build 10080) con Project Spartan para mostrar como se puede depurar una aplicación web que está desplegada en Azure <a href="http://vorlonjsdemo.azurewebsites.net/">http://vorlonjsdemo.azurewebsites.net/</a></p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6355.clip_image015_508055C2.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6355.clip_5F00_image015_5F00_508055C2.jpg"><img title="clip_image015" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image015" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6708.clip_image015_thumb_0E10443D.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6708.clip_5F00_image015_5F00_thumb_5F00_0E10443D.jpg" width="602" height="338" /></a></p>

<p>Esta imagen muestra el navegador, con la selección del detalle recuadrado en rojo donde se muestra lo que está ahora mismo seleccionado en el DOM Explorer de Vorlon.JS.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/6232.clip_image017_08C15D8C.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/6232.clip_5F00_image017_5F00_08C15D8C.jpg"><img title="clip_image017" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image017" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/8233.clip_image017_thumb_46514C06.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/8233.clip_5F00_image017_5F00_thumb_5F00_46514C06.jpg" width="601" height="411" /></a></p>

<h1>Vorlon.JS es un proyecto Open Source</h1>

<p>Uno de los atractivos de Vorlon.JS, además de ser Open Source, es la posibilidad de crear plugins para extender la funcionalidad que se ofrece de base. De hecho está construido de tal manera que las tres características que se han visto en el artículo con plugins del cual se dispone el código fuente. <a href="http://www.vorlonjs.com/plugins/">http://www.vorlonjs.com/plugins/</a></p>

<p>Todo el código fuente de Vorlon.JS está hecho en TypeScript (<a href="http://www.typescriptlang.org/">http://www.typescriptlang.org/</a>) lo que permite que para hacer un plugin utilizando orientación a objetos, en este ejemplo se ha creado una clase en TypeScript que hereda de Plugin, así se tiene un mecanismo consistente para poder crean plugins con un contrato de operaciones bien definido, que al final de todo generará JavaScript. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/0434.clip_image018_28069510.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/0434.clip_5F00_image018_5F00_28069510.png"><img title="clip_image018" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="clip_image018" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/1854.clip_image018_thumb_6CB5C002.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/1854.clip_5F00_image018_5F00_thumb_5F00_6CB5C002.png" width="446" height="350" /></a></p>

<p><a href="https://github.com/MicrosoftDX/Vorlonjs/blob/master/Plugins/Vorlon/plugins/objectExplorer/vorlon.objectExplorer.ts">https://github.com/MicrosoftDX/Vorlonjs/blob/master/Plugins/Vorlon/plugins/objectExplorer/vorlon.objectExplorer.ts</a></p>

<h1>Próximos pasos</h1>

<p>Vista la flexibilidad y potencia que tiene Vorlon.JS empezar a utilizarlo es muy fácil y cómodo, se ejecuta en cualquier plataforma, se puede desplegar en cualquier Cloud (aunque en este articulo se haya mostrado Azure) y permite depurar cualquier dispositivo, aplicación y navegador. </p>

<p>Solamente existe algo parecido con el <a href="https://developer.chrome.com/devtools/docs/remote-debugging">Remote Debuggin de Android en Google Chrome</a>, pero solo funciona para el navegador de Chrome (no para el navegador del sistema de Android), y requiere tener Android 4.4+, si tienes iOS o Windows Phone no puedes depurar tus aplicaciones.</p>

<p>Si estás creando aplicaciones basadas en Cordova o PhoneGap definitivamente esta librería es un aliado para ti. </p>

<p>&#160;</p>

<p>Luis Guerrero.</p>

<p>Technical Evangelist Microsoft Azure.</p>

<p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Cómo no escribir código concurrente en .NET</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/cmo-no-escribir-cdigo-concurrente-en-net</link>
      <pubDate>Wed, 28 Jan 2015 04:06:30 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2015/01/28/cmo-no-escribir-cdigo-concurrente-en-net/</guid>
      <description><![CDATA[En muchas ocasiones el código que se escribe en .NET se tiene que tener en cuenta que puede ser...]]></description>
      <content:encoded><![CDATA[<p>En muchas ocasiones el código que se escribe en .NET se tiene que tener en cuenta que puede ser llamado de manera concurrente, es decir, desde varios hilos del sistema operativo. En ese caso hay que hace que el código sea lo más óptimo posible para no generar muchas esperas y bloqueos innecesarios del código. </p>  <h1>Lo más sencillo</h1>  <p>La forma de empezar a bloquear código para asegurarse de que el código sólo es ejecutado por un único Thread es envolver ese código con la palabra reservada lock (en C#), un ejemplo de ese código se puede encontrar a continuación.</p>  <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">   <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> LockExample<br />{<br />    <span style="color: #0000ff">private</span> <span style="color: #0000ff">object</span> syncLock = <span style="color: #0000ff">new</span> <span style="color: #0000ff">object</span>();<br />    <br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> MethodWithLock()<br />    {<br />        <span style="color: #0000ff">lock</span>(syncLock)<br />        {<br />            <span style="color: #008000">// código</span><br />        }<br />    }<br />}</pre>

  <br /></div>

<p></p>

<p>De este tipo de bloqueo se pueden encontrar variantes, pero que en esencia son lo mismo. Utilizando el atributo <a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute(v=vs.110).aspx">MethodImpl</a> con el valor de <a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions(v=vs.110).aspx">MehtodImplOptions.Synchronized</a> se consigue el mismo resultado que es bloquear todo el cuerpo de la función utilizando la palabra reservada lock. La diferencia es que cuando el método es de instancia se utiliza el objeto this para señalar el bloqueo, mientras que cuando el método es estático se utiliza el typeof de la clase para hacer el bloqueo.</p>

<h2>MethodImpl para métodos de instancia</h2>

<p>Este código que utiliza MethodImpl,</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">[MethodImpl(MethodImplOptions.Synchronized)]<br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> MethodWithLock()<br />{<br />}</pre>

  <br /></div>

<p>Es exactamente igual a:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> MethodWithLock()<br />{<br />    <span style="color: #0000ff">lock</span>(<span style="color: #0000ff">this</span>)<br />    {<br />    }<br />}</pre>

  <br /></div>

<p></p>

<h2>MethodImpl para método estáticos</h2>

<p>Para los método estáticos utilizar MethodImpl </p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> LockExample<br />{<br />    [MethodImpl(MethodImplOptions.Synchronized)]<br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> MethodWithLock()<br />    {<br />    }<br />}</pre>

  <br /></div>

<p>Es igual a escribir el siguiente código:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> LockExample<br />{<br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> MethodWithLock()<br />    {<br />        <span style="color: #0000ff">lock</span> (<span style="color: #0000ff">typeof</span>(LockExample))<br />        {<br />        }<br />    }<br />}</pre>

  <br /></div>

<p></p>

<p>Como se ha comentado anteriormente este tipo de bloqueos no son recomendables en ningún caso, porque aumenta la granularidad del bloqueo y no se tiene un control sobre las operaciones de lectura o escritura de las variables que se desea acceder. Además, en caso de excepción no está claro si el bloqueo se libera o se queda para siempre.</p>

<p>Queda también comentar que en caso concreto del bloqueo para los métodos estáticos además se puede incurrir en un comportamiento muy peculiar del CLR que se llama Marshal-by-bleed.</p>

<h3>Marshal-by-bleed</h3>

<p>.NET Framwork soporta marshalling de objetos entre dominios de aplicación llamado marshal-by-bleed. Esto significa que cuando se tienen varios dominios de aplicación dentro del mismo proceso de .NET entre estos dominios de aplicación, si no se ha especificado de <a href="http://msdn.microsoft.com/en-us/library/system.loaderoptimization(v=vs.110).aspx">LoaderOptimization</a>, los ensamblados firmados con un nombre fuerte (<a href="http://msdn.microsoft.com/en-us/library/wd40t7ad(v=vs.110).aspx">strong name</a>) serán compartidos entre los dominios de aplicación. Pues bien, eso puede llevar a que la referencia en memoria de objetos estáticos referenciados desde un GCRoot pueda ser el mismo entre varios dominios de aplicación. En efecto prácticos, la llamada a typeof(String) puede ser la misma referencia entre dominios de aplicación. Sabiendo esto si el código de más arriba la clase que se utiliza como bloqueo en el atributo <a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute(v=vs.110).aspx">MethodImpl</a> es una clase que forma parte de un ensamblado firmado con un nombre fuerte, el hecho de utilizar ese objeto puede hacer que el mismo código ejecutado en otro dominio de aplicación diferente (dentro del mismo proceso) bloquee el otro dominio de aplicación. Así de esta manera se están produciendo bloqueos a través de dominios de aplicación, una situación que es bastante complicada de detectar en aplicaciones en producción.</p>

<p>Para más información Unai Zorilla escribió un artículo en 2009 con un ejemplo sobre esto (<a href="http://geeks.ms/blogs/unai/archive/2009/02/08/marshall-by-bleed-explained.aspx">http://geeks.ms/blogs/unai/archive/2009/02/08/marshall-by-bleed-explained.aspx</a>) también Joe Duffy escribió sobre esto en 2006 (<a href="http://joeduffyblog.com/2006/08/21/dont-lock-on-marshalbybleed-objects/">http://joeduffyblog.com/2006/08/21/dont-lock-on-marshalbybleed-objects/</a>) </p>

<h1>Mejorando el código concurrente</h1>

<p>Como se ha visto en los anteriores ejemplos, este tipo de código no es la mejor solución para controlar el acceso a métodos o variables. Otra opción es utiliza la clase <a href="http://msdn.microsoft.com/en-us/library/system.threading.monitor(v=vs.110).aspx">Monitor</a>, que permite entre otras cosas poner un timeout para que en caso de que el bloqueo dure demasiado tiempo, tener un mecanismo para poder abortarlo. </p>

<p>Otra opción para aumentar la granularidad de los bloqueos es utilizar una clase que permita tener diferentes patrones de acceso a recursos compartidos. Uno de los más utilizados es un escritor varios lectores, que se basa en la idea de tener una único thread escribiendo un varios leyendo a la vez. Para hacer eso dentro de .NET Framework hay una clase llamada <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx">ReaderWriterLockSlim</a> que permite justamente crear este patrón.</p>

<p>En el siguiente código se protege el acceso a una variable entera para que se pueda leer desde muchos threads pero sólo se pueda escribir desde uno.</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <pre id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MultipleReadsOneWriter<br />{<br />    <span style="color: #0000ff">private</span> <span style="color: #0000ff">volatile</span> <span style="color: #0000ff">int</span> <span style="color: #0000ff">value</span>;<br />    <span style="color: #0000ff">private</span> ReaderWriterLockSlim rwls;<br />    <br />    <span style="color: #0000ff">public</span> MultipleReadsOneWriter()<br />    {<br />        rwls = <span style="color: #0000ff">new</span> ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);<br />    }<br />    <br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> ReadValue()<br />    {<br />        <span style="color: #0000ff">int</span> result = <span style="color: #0000ff">default</span>(<span style="color: #0000ff">int</span>);<br />        rwls.EnterReadLock();<br />        <span style="color: #0000ff">try</span><br />        {<br />            result = <span style="color: #0000ff">value</span>;<br />        }<br />        <span style="color: #0000ff">finally</span><br />        {<br />            rwls.ExitReadLock();<br />        }<br />        <span style="color: #0000ff">return</span> result;<br />    }<br />    <br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> WriteValue(<span style="color: #0000ff">int</span> number)<br />    {<br />        rwls.EnterWriteLock();<br />        <span style="color: #0000ff">try</span><br />        {<br />            <span style="color: #0000ff">value</span> = number;<br />        }<br />        <span style="color: #0000ff">finally</span><br />        {<br />            rwls.ExitWriteLock();<br />        }<br />    }<br /><br />    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> WriteValueIfEqual(<span style="color: #0000ff">int</span> compare, <span style="color: #0000ff">int</span> number)<br />    {<br />        rwls.EnterUpgradeableReadLock();<br />        <span style="color: #0000ff">try</span><br />        {<br />            <span style="color: #0000ff">int</span> current = <span style="color: #0000ff">value</span>;<br />            <span style="color: #0000ff">if</span> (current == compare)<br />            {<br />                rwls.EnterWriteLock();<br />                <span style="color: #0000ff">try</span><br />                {<br />                    <span style="color: #0000ff">value</span> = number;<br />                }<br />                <span style="color: #0000ff">finally</span><br />                {<br />                    rwls.ExitWriteLock();<br />                }<br />            }<br />        }<br />        <span style="color: #0000ff">finally</span><br />        {<br />            rwls.ExitUpgradeableReadLock();<br />        }<br />    }<br />}</pre>

  <br /></div>

<p>Algunos detalles interesantes sobres este código. La clase <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx">ReaderWriterLockSlim</a> tiene métodos para poder bloquear para sólo lectura, sólo escritura y también para una lectura que tiene posibilidad de actualizarse a una escritura. De esta manera se controla mucho mejor las lecturas y escritura de una variable. </p>

<p>Otro detalle interesante de código es que cualquier interacción sobre las llamadas de la clase <a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx">ReaderWriterLockSlim</a> está envuelta entre un try/finally que permite asegurarse que <b>siempre </b>se vaya a llamar a la funciona de salida de la operación actual. Esto es muy importante porque evita que se tengan bloqueos huérfanos que nunca se liberen. </p>

<p>Luis Guerrero.</p>

<p>Technical Evangelist Microsoft Azure.</p>

<p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Infografía Open Source Developer</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/infografa-open-source-developer</link>
      <pubDate>Wed, 22 Oct 2014 02:02:25 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2014/10/22/infografa-open-source-developer/</guid>
      <description><![CDATA[]]></description>
      <content:encoded><![CDATA[<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/slides/3704.WhatIsAzure-v2%203.pdf" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-slides/3704.WhatIsAzure_2D00_v2-3.pdf" target="_blank"><img title="Slide1" style="border: 0px currentcolor; display: inline;" border="0" alt="Slide1" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2477.Slide1_413CA29A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2477.Slide1_5F00_413CA29A.png" width="720" height="960" /></a></p>]]></content:encoded>
    </item>
    <item>
      <title>Eventos de Microsoft Azure en Septiembre</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/eventos-de-microsoft-azure-en-septiembre</link>
      <pubDate>Fri, 05 Sep 2014 03:08:06 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2014/09/05/eventos-de-microsoft-azure-en-septiembre/</guid>
      <description><![CDATA[Este mes de septiembre volvemos desde Microsoft España cargados de eventos de Azure, así que si...]]></description>
      <content:encoded><![CDATA[<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/2744.clip_image002_6258BBAA.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/2744.clip_5F00_image002_5F00_6258BBAA.jpg"><img title="clip_image002" style="border: 0px currentcolor; display: inline;" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/4747.clip_image002_thumb_04441E2F.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/4747.clip_5F00_image002_5F00_thumb_5F00_04441E2F.jpg" width="624" height="145" /></a></p>  <p>Este mes de septiembre volvemos desde Microsoft España cargados de eventos de Azure, así que si quieres publicar tu web en Azure o aprender cómo se despliega una máquina virtual es tú momento:</p>  <ul>   <li>Madrid 9 de septiembre: Laboratorios técnicos de Azure <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592549&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592549&amp;Culture=es-ES</a></li>    <li>Barcelona 16 de septiembre: Azure Dev_Camp: <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592609&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592609&amp;Culture=es-ES</a></li>    <li>Madrid 17 de septiembre: Azure Dev_Camp: <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592607&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592607&amp;Culture=es-ES</a></li>    <li>Sevilla 23 de septiembre: Azure Dev_Camp: <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592610&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592610&amp;Culture=es-ES</a></li>    <li>Valencia 25 de septiembre: Azure Dev_Camp: <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592611&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592611&amp;Culture=es-ES</a></li>    <li>Madrid 29 de septiembre: Laboratorios técnicos de Azure: <a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592550&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592550&amp;Culture=es-ES</a></li> </ul>  <h1>Bonus Point!</h1>  <p>Curso de Introducción al desarrollo de videojuegos con Unity3D en Barcelona el 18 de septiembre 15:00 a 20:00 </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/40/66/metablogapi/4606.Unity_Pri_46C51E6D.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-40-66-metablogapi/4606.Unity_5F00_Pri_5F00_46C51E6D.png"><img title="clip_image003" style="border: 0px currentcolor; display: inline;" border="0" alt="clip_image003" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/5417.clip_image003_2D4EBD2B.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/5417.clip_5F00_image003_5F00_2D4EBD2B.png" width="240" height="100" /></a></p>  <p><a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592606&amp;Culture=es-ES">https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032592606&amp;Culture=es-ES</a></p>  <p>Nos vemos en la nube!</p>  <p>Luis Guerrero.</p>  <p><a href="https://twitter.com/guerrerotook">@guerrerotook</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Conociendo Visual Studio Online</title>
      <link>https://docs.microsoft.com/archive/blogs/luisguerrero/conociendo-visual-studio-online</link>
      <pubDate>Fri, 05 Sep 2014 01:29:00 GMT</pubDate>
      <dc:creator><![CDATA[Luis Guerrero (DX)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/luisguerrero/2014/09/05/conociendo-visual-studio-online/</guid>
      <description><![CDATA[Si eres un desarrollador individual o un equipo de desarrollo, necesitas tener una herramienta para...]]></description>
      <content:encoded><![CDATA[<p>Si eres un desarrollador individual o un equipo de desarrollo, necesitas tener una herramienta para gestionar el ciclo de vida del de desarrollo de tu software (ALM), donde puedas tener centralizado en un &uacute;nico lugar:</p>
<ul>
<li>Gesti&oacute;n de artefactos de trabajo basados en una <a href="http://www.visualstudio.com/explore/agile-software-development-vs" target="_blank">metodolog&iacute;a</a> &aacute;gil.</li>
<ul>
<li>Product Backlog &iacute;tems</li>
<li>Work &iacute;tems</li>
<li>User stories</li>
<li>Bugs</li>
<li>Features</li>
<li>Impediment</li>
</ul>
<li>Un repositorio de c&oacute;digo fuente basado en <a href="http://www.visualstudio.com/en-us/explore/team-collaboration-vs" target="_blank">Git o en Team Foundation Control Servcice</a></li>
<li>Un sistema de compilaci&oacute;n de c&oacute;digo fuente</li>
<li>La capacidad de realizar integraci&oacute;n contin&uacute;a con tu plataforma de nube, como Microsoft Azure.</li>
<li><a href="http://www.visualstudio.com/en-us/explore/application-insights-vs" target="_blank">Monitorizaci&oacute;n</a> de tu aplicaci&oacute;n por parte del servidor (.NET y Java) por parte de cliente con una anal&iacute;tica basada en Javascript.</li>
</ul>
<p>Todo eso lo puedes tener con Visual Studio Online y en este webcast puedes echar un vistazo general a todas estas caracter&iacute;sticas.</p>
<p><a href="https://www.youtube.com/watch?v=XINjcywJKXc"><img style="border: 0px currentcolor; display: inline;" title="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/61/80/metablogapi/8666.clip_image002_11FE1C41.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-61-80-metablogapi/8666.clip_5F00_image002_5F00_11FE1C41.jpg" alt="clip_image002" width="623" height="366" border="0" /></a></p>
<p><iframe src="https://www.youtube.com/embed/XINjcywJKXc" frameborder="0" width="560" height="315"></iframe></p>
<p>Si est&aacute;s interesado en m&aacute;s informaci&oacute;n no dudes en poner un comentario o ponerte en contacto directamente conmigo.</p>
<p>Saludos. Luis.</p>]]></content:encoded>
    </item>
  </channel>
</rss>