Juan Pablo's profile..:: Liarjo of Locksley ...PhotosBlogLists Tools Help

Blog


    December 29

    Reporting Services, técnicas de alto desempeño

    Escenario

    Estamos trabajando en un proyecto de plataforma de reportes basada en SSRS [2] el cual tendrá una gran cantidad de usuarios por lo que debemos tomar medidas para asegurar buenos tiempos de respuestas con la infraestructura que tenemos. La idea es evitar tener que hacer Render de los reportes cada vez que los usuarios demandan los distintos informes.

    En este Post voy a exponer opciones de mitigación de problemas de desempeño en SSRS en escenarios de alto desempeño. Mi fuente de información para este post es el libro de potente libro de Rodney Landrum y Walter Voytek [1]

    Cuando se propone una solución de informes basada en un servidor de reportes versus la construcción programática ad hoc de reportes se busca el obtener diferentes beneficios tales como reutilización, control de acceso consistente, desempeño, etc.

    En el aspecto de desempeño hay que entender que en una solución de informes de negocio, no todos los informes tienen una variabilidad de los datos tal que sea necesario construirlo cada vez que un usuario lo requiere. En este tipo de informes es donde se puede aplicar técnicas de mitigación para cuidar el desempeño de la solución de informes.

    Opciones de Mitigación

    Para los informes que tienen datos que no tienen una taza de cambios muy alta podemos aplicar las siguientes técnicas de mitigación de problemas de performance.

    1. Ejecución agendada de Reportes
    2. Servicio de subscripción de reportes
    3. Instantáneas (snapshots)
    4. Caching de Contenido

    Ejecución Agendada de Reportes

    La idea es programar la ejecución de reportes en momentos predeterminados. Es el servidor quien ejecuta la consulta y genera el informe sin necesidad de intervención del usuario. Estos informes pueden ser almacenados en el servido y así mantener una perspectiva histórica de los datos.

    En la siguiente figura se muestra la página de configuración de los reportes agendados.

    Ahora, como el reporte se ejecuta por el servicio (usando SQL Server Agent[3]) sin intervención de humanos , los parámetros del informe deben contener valores por defecto o soportar nulos.

    El beneficio de usar reportes agendados es que cuando un usuario carga el informe, ve una “foto” que está ya calculado y formateado por lo que la respuesta es “instantánea”.

     Agendamiento de Reportes

    Instantáneas (SnapShots)

    Esta alternativa consiste en almacenar una foto estática del informe. Existen dos tipos de SnapShots:

    1. Los que generan una foto del informe en un momento determinado
    2. Los que generan fotos históricas del informe en diferentes momentos

    Los beneficios de performance de utilizar está técnica son que el reporte ya está pre procesado y que no necesita hacer consultas a la base de datos. La siguiente imagen muestra la configuración del SnapShots.

    Configuración de SnapShots

    Caching de Contenido

    Está técnica es utilizada cuando los diferentes usuarios ven informes con datos que dependen de parámetros que ellos ingresan. En este caso, el contenido agendado no aplica porque genere el mismo resultado para todos los usuarios. El manejó de Cache de SSRS permite mantener copias de los reportes para cada informe las cuales se generan la primera vez que el cliente ve el informe. Las subsecuentes veces que se pide el informe y si ciertas condiciones coinciden el informe no se vuelve a generar sino que se usa la copia del Cache.

    Las condiciones en la cuales un usuario recibirá un informe desde el Cache son:

    1. EL usuario subsecuente accede al informe antes que el tiempo de expiración de la copia del Cache se cumpla. Pasado ese tiempo el informe vuelve a calcularse y generar una nueva copia en el Cache.
    2. Si los parámetros del informe que el usuario está accediendo cambian, este reporte se calcula y genera una nueva copia en el Cache.
    3. El informe de la fuente de datos no está configurado para la autenticación de Windows o pregunte al usuario las credenciales de inicio de sesión

    Esta técnica es muy buena para proteger el desempeño de reportes que consumen muchos recursos al hacer el Render. El Trade-Off es que no se pueden usar en informes que tienen datos sensibles en el tiempo, por ejemplo valores de la bolsa en horario de transacciones.Otro tema importante es preocuparse tanto en Cache como SnapShots es el uso de disco. La siguiente imagen es la configuración del Cache.

    Configuracioon del Cache

    Servicio de Subscripción de Reportes

    A diferencia de las otras tres técnicas presentadas en este Post, este servicio permite calcular los informes y enviarlo a los usuarios subscritos. Hacer esto evita que los usuarios vayan el servidor de informes y pedir su informe sino que el servicio se los envía. Las opciones de envío son las siguientes:

    1. Poner una copia en un lugar específico
    2. Envió por mail
    3. En algún sitio compartido en la red
    4. Incluso directo a la impresora

    Usar está técnica tiene el beneficio de poder producir los reportes fuera de horarios punta ayudando así a evitar posibles denegación de servicios por sobrecarga de trabajo. Los informes pueden ser generados en diferentes formatos siendo el formato por defecto el Web Archive, pero podría ser otro como una imagen TIF o un PDF.

    Podemos trabajar con dos tipos de subscripciones:

    Standard Subscriptions: Es una configuración estática para uno o mas usuarios. Los parametros son los mismos para todos.

    Configuracion Standar de reportes subscripcion

    Data-driven subscriptions: La lista de suscripción es dinámica y puede ser resultado de una consulta. Esta es la forma más potente de trabajo, pero solo está disponible en la versión Enterprise de SQL.

    Configuracion para el envio de mail Dat-Driven

    Referencias

    [1] Pro SQL Server 2005 Reporting Services

    [2] SSRS

    [3] SQL Server Agent

    November 04

    Pregunta sobre Servicios Windows en C#

    Como les comenté hace un tiempo (aquí) no puedo permitir que la gente haga comentarios en este BLOG porque los Chinos me llenan de SPAM.

    Escribí hace un tiempo un POST de cómo hacer servicios Windows usando C# (aquí). Recibí la siguiente pregunta a través de un mensaje privado, como es interesante la comparto con ustedes.

    mensaje

    La respuesta a la pregunta es Sí!!!!

    Para hacerlo te recomiendo que el servicio levante en EndPoint de Windows Comunication Foundation y exponga la funcionalidad del servicio Windows como un servicio WCF. Es lo más simple ¿Se entiende? O es necesario un ejemplo?

    Salu2

    July 25

    Metodología para proyectos de Minería de Datos

    El gran parte del éxito de un proyecto de software, en empresas de desarrollo, se basa en su forma de trabajo. Esta metodología que usan les sirve para que los miembros del equipo sepan que deben hacer y cuando. Existen muchas metodologías de todos los sabores y colores, en mi opinión todas suman dependiendo del contexto hay que optar por la más eficaz.

    Ahora, en los proyecto de minería de datos al igual que en los proyectos de cualquier cosa es necesario seguir una forma de trabajo, es decir una metodología. Aquí les comparto la metodología CRISP –DM, que es libre y se hace cargo de definir cómo y cuando las cosas deben ser hechas.

    Al igual que cualquier metodología es un modelo y no un manual de corta palos, ustedes deben adecuarla a la realidad de su propio entorno.

    CRISP-DM

    La metodología CRISP-DM consta de cuatro niveles de abstracción, organizados de forma jerárquica en tareas que van desde el nivel más general hasta los casos más específicos.

    A nivel más general, el proceso está organizado en seis fases, estando cada fase a su vez estructurada en varias tareas generales de segundo nivel. Las tareas generales se proyectan a tareas específicas, donde se describen las acciones que deben ser desarrolladas para situaciones específicas. Así, si en el segundo nivel se tiene la tarea general “limpieza de datos”, en el tercer nivel se dicen las tareas que tienen que desarrollarse para un caso específico, como por ejemplo, “limpieza de datos numéricos”, o “limpieza de datos categóricos”. El cuarto nivel, recoge el conjunto de acciones, decisiones y resultados sobre el proyecto de Data Mining específico.

    La metodología CRISP-DM estructura el ciclo de vida de un proyecto de Data Mining en seis fases, que interactúan entre ellas de forma iterativa durante el desarrollo del proyecto.

    Crisp-dm

     

    La primera fase análisis del problema, incluye la comprensión de los objetivos y requerimientos del proyecto desde una perspectiva empresarial, con el fin de convertirlos en objetivos técnicos y en una planificación.

    La segunda fase de análisis de datos comprende la recolección inicial de datos, en orden a que sea posible establecer un primer contacto con el problema, identificando la calidad de los datos y estableciendo las relaciones más evidentes que permitan establecer las primeras hipótesis.

    Una vez realizado el análisis de datos, la metodología establece que se proceda a la preparación de los datos (tercera fase), de tal forma que puedan ser tratados por las técnicas de modelado. La preparación de datos incluye las tareas generales de selección de datos a los que se va a aplicar la técnica de modelado (variables y muestras), limpieza de los datos, generación de variables adicionales, integración de diferentes orígenes de datos y cambios de formato.

    La fase de preparación de los datos, se encuentra muy relacionada con la fase de modelado (cuarta fase), puesto que en función de la técnica de modelado que vaya a ser utilizada los datos necesitan ser procesados en diferentes formas. Por lo tanto las fases de preparación y modelado interactúan de forma sistemática. En la fase de modelado se seleccionan las técnicas de modelado más apropiadas para el proyecto de Data Mining específico. Las técnicas a utilizar en esta fase se seleccionan en función de los siguientes criterios:

     

    • Ser apropiada al problema.
    • Disponer de datos adecuados.
    • Cumplir los requerimientos del problema.
    • Tiempo necesario para obtener un modelo.
    • Conocimiento de la técnica.

    Antes de proceder al modelado de los datos se debe de establecer un diseño del método de evaluación de los modelos, que permita establecer el grado de bondad de los modelos. Una vez realizadas estas tareas genéricas se procede a la generación y evaluación del modelo. Los parámetros utilizados en la generación del modelo dependen de las características de los datos.

    En la quinta fase, la fase de evaluación, se evalúa el modelo, no desde el punto de vista de los datos, sino del cumplimiento de los criterios de éxito del problema. Se debe revisar el proceso seguido, teniendo en cuenta los resultados obtenidos, para poder repetir algún paso en el que, a la vista del desarrollo posterior del proceso, se hayan podido cometer errores. Si el modelo generado es válido en función de los criterios de éxito establecidos en la primera fase, se procede a la explotación del modelo.

    Normalmente los proyectos de Data Mining no terminan en la implantación del modelo (sexta fase), sino que se deben documentar y presentar los resultados de manera comprensible en orden a lograr un incremento del conocimiento. Además en la fase de explotación se debe de asegurar el mantenimiento de la aplicación y la posible difusión de los resultados.

    image

    Fase 1 Entendimiento del Negocio

    Esta fase se centra en la comprensión de los objetivos del proyecto y los requisitos desde una perspectiva de negocio, a continuación, convertir ese conocimiento en una definición de una solución de minería datos y un plan preliminar para lograr los objetivos del negocio.

    Las tareas de esta fase con las siguientes:

    1. Determinar los objetivos del negocio: comprender completamente desde la perspectiva del negocio lo que el cliente realmente quiere. Además, se deben identificar factores importantes que puedan influir en el desarrollo del proyecto, al principio del mismo. En resumen evitar gastar mucho tiempo respondiendo correctamente a las preguntas de negocio incorrectas.

    2. Evaluar la situación: darse cuenta de la real situación del escenario dónde se realizará el proyecto.

    3. Determine las metas del proyecto BI: en esta actividad se busca expresar los objetivos de negocio del proyecto en términos técnicos.

    4. Elaborar el plan del proyecto: construir el plan para alcanzar los objetivos de minería de datos y los objetivos de negocio. Este plan debe describir las actividades y pasos a seguir durante el resto del proyecto, incluyendo la selección inicial de herramientas y tecnologías.

    Fase 2 Entendimiento de los Datos

    Esta fase se inicia con una primera recopilación de datos y procede con las actividades específicas a fin de familiarizarse con los datos, para identificar problemas de calidad de los datos, primero para descubrir una visión de los datos o para detectar subconjuntos interesantes para formar las hipótesis de información oculta.

    Las tareas de esta fase con las siguientes:

    1. Recopilar los Datos iníciales: obtener los datos relevantes para este proyecto. Puede ser necesario cargar estos datos para poder revisarlos bien y lograr entender en que estado se encuentran.

    2. Descripción de los Datos: describir los datos, sus propiedades y sus medidas. Se elabora un informe de esto.

    3. Revisar los Datos: esta tarea aborda los aspectos de BI del proyecto los cuales pueden abordarse con consultas, visualización y presentación de informes.

    4. Verificar la calidad de datos: examinar la calidad de los datos, buscando validar la completitud y veracidad de los datos.

    Fase 3 Preparación de los datos

    Cubre todas las actividades encaminadas a construir los datos finales a partir de los datos en bruto. Las tareas de preparación de datos probablemente se realizan varias veces, en diferentes ordenes. Sus tareas incluyen la tabla, registro y selección de atributos, así como la transformación y limpieza de datos para herramientas de modelado. Normalmente está fase toma el mayor esfuerzo del proyecto.

    Las tareas de esta fase con las siguientes:

    1. Seleccionar los Datos: Decidir sobre los datos que deben utilizarse para el análisis. Incluir criterios de pertinencia de los datos para los objetivos, la calidad y técnicas tales como las limitaciones de volumen de datos o tipos de datos. Esta tarea Cubre la selección de atributos, así como la selección de registros en una tabla.

    2. Limpieza de los datos: aquí buscamos elevar a calidad de los datos al nivel requerido por las técnicas de BI seleccionadas en el proyecto.

    3. Construcción de los datos: tarea orientada a la construcción o cálculo de los atributos calculados o nuevos registros requeridos por el modelo de gestión y no provisto por los datos brutos u operacionales.

    4. Integración de Datos: tarea orientada a la integración de los datos de gestión generados a los modelos.

    5. Aplicar formatos a los datos.

    Fase 4 Modelamiento

    En esta fase varias técnicas de modelamiento son seleccionadas y aplicadas, y sus parámetros son calibrados buscando los valores óptimos. Típicamente, existen varias técnicas para resolver un mismo problema de minería de datos. Algunas técnicas tienen requerimientos específicos en la forma de los datos. Por esto a menudo hay que volver a la fase de preparación de datos en estos cosos.

    Las tareas de esta fase con las siguientes:

    1. Seleccionar la técnica de modelamiento

    2. Construcción del modelo de pruebas

    3. Implementación del modelo

    4. Evaluación del modelo

    Fase 5 Evaluación

    A estas alturas del proyecto ya se han construido el o los modelos los que aparenta ser correctos, desde la perspectiva del análisis de datos. Antes de proceder a la instalación final del modelo, es importante una evaluación a fondo del modelo y los pasos seguidos para su implementación para estar seguro que cumple con los objetivos de negocio. El objetivo clave es determinar si hay algún asunto de negocios que no se haya tratado con la suficiente profundidad. Al final de esta etapa se debe tener la certeza que los objetivos de negocio fueron alcanzados.

    1. Evaluación de los resultados

    2. Revisión del proceso

    3. Determinar los próximos pasos

    Fase 6 Transferencia

    La creación del modelo generalmente no es el final del proyecto. Incluso si la finalidad del modelo es aumentar el conocimiento de los datos, los conocimientos adquiridos tendrán que ser organizados y presentados de manera que el cliente puede utilizarlo. Dependiendo de los requisitos, la fase de despliegue puede ser tan simple como generar un informe o tan compleja como la aplicación de una repetible proceso de minería de datos. En muchos casos será el cliente, no el analista de datos, que llevará a cabo los pasos de instalación. Sin embargo, incluso si el analista no lleva acabo la trasferencia el esfuerzo es importante para que el cliente pueda comprender por adelantado qué medidas tendrán que ser llevadas a cabo con el fin de realmente hacer uso de los modelos creados

    1. Plan de transferencia

    2. Plan de monitoreo y mantenimiento

    3. Producción del reporte final.

    4. Revisión del Proyecto

    Mas información en las referencias.

    Referncias

    1.- CRoss Industry Standard Process

    2.- Metodologías para la Realización de Proyectos de Data Mining

    February 14

    ¿Cómo hacer un Servicio Windows en C#?

    Los servicios Windows son programas que corren en background independiente del usuario que tenga sesiones activas en un server. Los usamos para múltiples tareas por ejemplo monitorear el estado de un Servicio Web.

    Un cliente me pregunta cómo se puede hacer un servicio que monitoree un servicio Web y su tiempo de respuesta.

    Fácil, hay que hacer un servicio Windows en C# ;)

    Respuesta

    Los pasos para construir un servicio Windows, utilizando C# son los siguientes:

    1. Crear un proyecto del tipo Windows Services.
    2. Implementar la lógica del Servicio.
    3. Agregar los parámetros de instalación del servicio.
    4. Crear un proyecto de Instalación.
    5. Instalar
    6. Extra, ¿cómo hacer Debug?

    Paso 1: Crear un proyecto del tipo Windows Services.

    Visual Studio tiene un tipo de proyecto especial para crear servicios Windows. En el cuadro de dialogo ‘New Project’ hay que seleccionar la opción ‘Windows Services’ como muestra la figura 1.

    New Project

    Figura 1.

    Como resultado de esto se crea una clase llamada Service1 que contiene los siguientes métodos:

    Service1(): constructor de la clase, aquí debemos incluir la configuración del Servicio.

    OnStart(string[] args): Evento cuando el servicio se inicia. Esto ocurre cada vez que el servicio comienza a funcionar.

    OnStop(): Evento cuando el servicio se detiene. Aquí se deben eliminar todos los recursos que el servicio utiliza.

     

    Paso 2: Implementar la lógica del Servicio

    Este servicio debe hacer lo siguiente:

    1. Consumir un Servicio Web cada cierto periodo de tiempo.
    2. Validar que el Servicio Web resposponda (no se caiga).
    3. Validar que el tiempo de respuesta en menor que cierto valor.
    4. Mantener en configuración la URL del Servicio Web, periodo de tiempo en que se repiten las llamadas y el tiempo de respuesta máximo.

    Para consumir un Servicio Web utilizamos la funcionalidad de Visual Studio ‘Add Web Reference’ que se muestra en la figura 2. En este ejemplo utilizaré el servicio gratuito de  WebServiceX.

    Add Web Reference......

    Figura 2.

    Para realizar la tarea repetitiva de llamar al servicio Web cada cierto intervalo de tiempo utilizaremos un objeto del tipo System.Timers.Timer. Este objeto tiene la capacidad de levantar un evento cuando pasa cierto periodo de tiempo desde que se activa. En este caso la construcción del Timer se realzia en el método onStart del Servicio Windows, es decir cuando el servicio de levanta comienza a trabajar el Timer. Esto se muestra en el código 1.

     

     

       1: protected override void OnStart(string[] args)
       2: {
       3:     //Timer para el control del tiempo entre llamadas.
       4:     myTimer = new System.Timers.Timer();
       5:     //Intervalo de tiempo entre llamadas.
       6:     myTimer.Interval = 1500;
       7:     //Evento a ejecutar cuando se cumple el tiempo.
       8:     myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
       9:     //Habilitar el Timer.
      10:     myTimer.Enabled = true;
      11: }

    Código 1.

    En el evento myTimer_Elapsed se hace la llamada al Servicio Web. Pero, para evitar problemas de concurrencia se detiene el Timer antes de hacer la llamada y luego se vuelve a activar. Esto se muestra en el código 2.

     

     
       1: void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
       2: {
       3:     //Detiene el Timer
       4:     myTimer.Enabled = false;
       5:     //llama al Servicio Web
       6:     CallServicioWeb();
       7:     //habilita el Timer nuevamente.
       8:     myTimer.Enabled = true;
       9: }

    Código 2.

    Por último el método CallServicioWeb() hace la llamada y controla el tiempo de respuesta del Servicio. En el código 3 se puede ver la lógica de esto.

     

     
       1: void CallServicioWeb()
       2: {
       3:     //Proxy
       4:     SerivicioWeb.GeoIPService Proxy = new ServicioWindowsMonitor.SerivicioWeb.GeoIPService();
       5:     DateTime Tini;
       6:     TimeSpan Tdif;
       7:     try
       8:     {
       9:         //Tiempo de inicio de la llamada
      10:         Tini = DateTime.Now;
      11:         //llamada al servicio 
      12:         Proxy.GetGeoIP("200.10.12.126");
      13:         //Tiempo de respuesta
      14:         Tdif=Tini.Subtract(DateTime.Now);
      15:         if (Tdif.Seconds < -10)
      16:         {
      17:             Log("Servicio Lento: " + Tdif.Seconds.ToString()+ "[S]");
      18:         }
      19:     }
      20:     catch (Exception X)
      21:     {
      22:  
      23:         Log(X.Message);
      24:     }
      25: }

    Código 3.

    Paso 3: Agregar los parámetros de instalación del servicio.

    Para que el servicio pueda ser controlado por el administrador de servicios de Windows debemos agregar dos componentes a nuestro Servicio Windows:

     

    • serviceProcessInstaller: en este componente se debe fijar el usuario con que se ejecuta el servicio. En este caso utilizamos la cuenta Local Service.
    • serviceInstaller: Este componente tiene la propiedad ServiceName, que define el nombre con que el Servicio aparece en la consola de Servicios. En este caso lo llamaremos ‘Monitor GeoIP’. Además este componente tiene la propiedad StartType que define si el servicio parte de manera automatica, manual o está desabilitado.

    Para instalar estos componentes, en la vista de diseño del Servicio Windows usamos la opción ‘add Instaler’ del botón derecho. Esto se muestra en la figura 2.

    Add Install

    Figura 2.

    Paso 4: Crear un proyecto de Instalación

    Para utilizar el servicio es necesario crear un instalador. Este proyecto instala el software del Servicio Windows en el disco, lo registra y agrega a la consola de servicios del sistema operativo.

    Para crear un proyecto de instalación debemos utilizar el dialogo ‘New Project’ con la opción ‘Setup’ como muestra la figura 3.

    New Project Setup

    Figura 3.

    Una vez creado el proyecto debemos agregar a este proyecto de instalación en la carpeta ‘Application Folder’ el proyecto de salida. Este es nuestro proyecto de Servicio Windows. La figura 4 muestra cómo hacerlo usando el botón derecho.

    Add output project

    Figura 4.

    El siguiente paso es agregar este proyecto de salida a las acciones Install, Commit, RollBack y Uninstall. Para ello en la pestaña ‘Solution Explorer’ seleccionamos el botón ‘Custom Action Editor’. Luego en ese editor, agregamos el proyecto a todas las acciones, como lo muestra la figura 5.

    Add Custom Task

    Figura 5.

    Paso 5: Instalar

    Para instalar el Servicio Windows debemos hacer un Built del instalador y luego con el botón derecho sobre el proyecto de instalación ejecutar la instlación.

    Una vez instalado, siguiendo los pasos del Wizard, podemos ver el servicio en la consola de servicios del sistema operativo. En la figura 6 se puede ver las propiedades del evento que ya está en la consola de servicios!!!!

    Servicio Monitor Geo

    Figura 6.

    Paso 6: Bonus, Hacer Debug del Servicio.

    Para poder hacer debug del servicio podemos hacer un Attach del proceso. Ojo, esto es posible poque lo compilamos en modo Debug. Para hacerlo vamos al menu Debug de Visual Studio, opción Attach. Cuando aparece el dialogo de procesos hay que buscar en la lista el nombe del servicio y apretar el botón attach. En ese momento Visual Studio entra en modo de debug. El dialogo de Attach se muestra en la figura 7.

    Attach Process Debug

    Figura 7.

    Una vez que se está en modo de debug, se puede poner un punto de interupción en el código y hacer debug a gusto.

    Esto es lo básico para desarrollar un Servicio Windows, con esto pueden construir desde un sencillo servicio de monitoreo hasta complejos Host de Windows Comunication Foundation por ejemplo.

    El código de ejemplo de esta demos pueden bajarlo desde Aquí

    Salu2

    February 06

    Biztalk Server, ¿Cómo hacer debug y ver los mensajes?

    BizTalk Server es una excelente herramienta para construir procesos de negocio que requieren de integración de sistemas.

    Desde que se tienen IDE’s de desarrollo potentes, los desarrolladores están acostumbrados cada vez más a hacer debug de sus aplicaciones e ir viendo el estado de los objetos en memoria mientras se ejecuta la aplicación. Un problema en el desarrollo de orquestaciones es poder hacer debug de lo que estamos desarrollando. Por eso la pregunta, ¿Cómo hacer debug y ver los mensajes?

    Respuesta

    BizTalk tiene una herramienta llamada Health and Activity Tracking (HAT) que permite hacer consultas de las actividades que el motor servidor BizTalk está ejecutando.

    Con esta herramienta podemos hacer debug de las orquestaciones y ver el contenido de los mensajes de cada instancia de servicio que se están ejecutando.

    Los pasos para hacer debug son los que se muestran en el siguiente diagrama.

    Pasos para hacer Debug

    El primer paso no es materia de este POST.

     

    Paso 2: Poner la orquestación en modo debug.

    Para esto debemos utilizar la herramienta HAT. Esta herramienta trae consultas pre definidas con la cual podemos ubicar la orquestación que queremos revisar. Usando la consulta Most Recent 100 Service instance podemos ubicar la orquetsación.

    Consulta en el HAT

    Figura 1.

    Una vez ubicada la orquestación que buscamos, debemos instanciar el Orchestration debugger utilizando el botón derecho sobre la orquestación, como lo muestra la figura 2.

    HAT

    Figura 2.

    Por último debemos poner el o los puntos de ruptura en la orquestación para así poder ver su comportamiento en tiempo de ejecución. Esto se hace con el botón derecho sobre la acción, como muestra la figura 3. Luego de esto hay que cerrar el Orchestration Debugger.

    Orchestrator Debugger

    Figura 3. 

    Paso 3: Ejecutar la orquestación

    Debemos iniciar el proceso de negocio que queremos debugear, esto se hace mandando el mensaje a BizTalk que inicia el proceso.

     

    Paso 4: Encontrar la instancia de la orquestación

    Para encontrar la instancia de la orquestación usamos el HAT con una consulta que muestre las orquestaciones que tienen el estado Strated. Cuando pusimos en el paso 2 el punto de ruptura, el motor detiene todas las instancias de esa orquestación en ese punto de ruptura por lo que quedan en estado Started.

    Con la siguiente consulta podemos encontrar las instancias.

     

    SELECT top 100

    [Service/Name], [Service/Type],[ServiceInstance/State],

    dateadd(minute, @UtcOffsetMin, [ServiceInstance/StartTime]) as [StartTime],

    dateadd(minute, @UtcOffsetMin, [ServiceInstance/EndTime]) as [EndTime],

    [ServiceInstance/Duration],[ServiceInstance/ExitCode],[ServiceInstance/ErrorInfo],

    [ServiceInstance/Host], [Service/AssemblyName], [ServiceInstance/InstanceID],

    [ServiceInstance/ActivityID], [Service/ServiceGUID],[Service/ServiceClassGUID]

    FROM dbo.dtav_ServiceFacts sf WITH (READPAST)

    where

    [Service/Type]='Orchestration' and [ServiceInstance/State]='Started'

    ORDER BY sf.[ServiceInstance/StartTime] desc

    Código 1: Consulta SQL

    El resultado de esta consulta son las instancias que están Started en el servidor.

     

    Paso 5: Attach el proceso y ver el mensaje.

    Para poder tomar la instancia y ver el estado de los mensajes debemos ejecutar la consulta y con el botón derecho sobre la orquestación iniciar el Orchestration Debugger. La figura 4 muestra el resultado de la consulta.

    HAT

    Figura 4.

    Ahora en el Orchestration Debugger, debemos hacer Attach del proceso para poder cargar la información de la instancia en el Debugger. La figura 5 muestra cómo hacerlo.

    Orchestartor Debugger

    Figura 5.

    Ahora tenemos toda la información de la instancia a la vista y podemos por ejemplo ver el valor de un mensaje. Este valor podemos verlo en el cuadro de propiedades de las variables o con el botón derecho sobre el mensaje grabarlo en disco.

    Valores de mesajes

    Figura 6.

     

    Paso 6: Sacar del modo Debug la orquestación

    Es muy importante luego de realizar el debug, sacar los puntos de ruptura de la orquestación, sino está seguirá deteniendo todas las instancias de la misma que se ejecuten.

    Para esto, en el mismo Orchestration Debugger se deben borrar los puntos de ruptura y luego cerrarlo. Eso es todo!!!

    Salu2

    November 22

    Salud de mi servidor Windows, la salud no es solo para humanos

    Nuevamente recibo una pregunta interesante, los clientes son una fuente de inspiración inagotable. Qué pena no tener más tiempo para Bloger con más frecuencia.

    Problema

    El equipo de desarrollo he desarrollado una nueva aplicación y requiere saber si está aplicación puede o no ser instalada en un servidor que actualmente aloja otras aplicaciones. ¿Cómo saber si será capaz el servidor de soportar esta nueva aplicación?

    Posible Solución

    El sentido común dice que midiendo los recursos que actualmente usa el servidor se puede determinar la capacidad “ociosa” disponible para que la nueva aplicación se ejecute. Esto es verdad si y solo sí el uso de recursos fuera lineal.

    No voy a entrar en la complejidad de lo que es un sistema lineal, pero en términos simples Un sistema lineal es un sistema que obedece las propiedades de escalado (homogeneidad) y de superposición (aditiva), mientras que un sistema no-lineal es cualquier sistema que no obedece al menos una de estas propiedades.

    Asumiendo que los recursos se administran de manera lineal podemos declarar que los recursos usados hoy en el servidor al poner la nueva aplicación, no variaran sino que seguirán constante. Esto es la propiedad de superposición de los sistemas lineales. Esto no es verdad en el mundo real, pero es un supuesto que permite un análisis simple para obtener resultados aproximados evitando las complejidades de los sistemas no lineales.

    Ahora, después de haber “forzado” la realidad nos queda medir el uso de recursos. Las mediciones más simples y al alcance de todos en la plataforma Windows se hacen utilizando la herramienta Performance Monitor [1].

    Dependiendo del aspecto que se quiera observar son los contadores que debemos utilizar. En el artículo Key Performance Monitor Counters [3] explican que contadores utilizar para responder las siguientes preguntas:

     

    • ¿Cuánto es la disponibilidad del servidor?
    • ¿Cuán ocupado está el servidor?
    • ¿Está funcionando adecuadamente el Hardware?
    • ¿Tienes suficiente RAM? [Muy importante]
    • ¿El disco es lo suficientemente rápido?

    La gracias de este análisis es que no requiere de un entendimiento profundo de lo que el sistema hace, o como está construido (Java, DotNEt, etc..) Pasa a ser una caja negra. Ahora, para los puristas eso es malo porque no te da razones solo describe comportamiento de el sistema como un todo.

    Después de medir, se obtiene la capacidad ociosa del servidor de destino. Podemos representar eso como Recursos Disponibles (Rd).

    Los recursos que la nueva aplicación utiliza deben ser medidos de la misma manera. Para medir estos recursos debemos en el ambiente de Test “cargar la aplicación” para poder medir así los recursos que utiliza. Representaremos eso como Recursos Nueva Aplicación (Rna).

    Entonces, después de “forzar la realidad” podemos decir que:

     

    1.  Rd >> Rna => No tendremos mayores problemas.
    2. Sí Rd > Rna => no podemos decir nada con “responsabilidad”.
    3. Sí Rd <= Rna => No podemos instalar la nueva aplicación en el servidor.

    Solo en el primer caso, esta prueba simplificada nos da una respuesta práctica. En los otros casos hay que utilizar técnicas más sofisticadas, las cuales deben ser realizadas por gente con más experticia que un desarrollador de software como yo  :)

    Un ejemplo del nivel de complejidad de las medidas para los casos no resueltos con este método pragmático se puede ver en este POST [4] específico para medir desempeño de Web Services construidos en ASPNET.

    Referencias

    1.- Performance Monitor.

    2.- Sistemas Lineales.

    3.- Key Performance Monitor Counters.

    4.- Medir el desempeño de Servicios Web plataforma DotNet.

    November 15

    ASPNET Forms authentication ¿Cómo compartir datos cifrados entre aplicaciones?

     

    Escenario

    Para un cliente de la industria Bancaria implementamos autentificación utilizando formularios (Forms authentication) de ASPNET. Este formulario es único para todas las aplicaciones.

    En el contexto de ese proyecto y buscando que sea lo más seguro posible utilizamos las opciones de cifrado de toda la información que se almacena en las cookies. Para ello utilizamos la opción <forms protection="All">.

    Ahora, como el formulario es único para todas las aplicaciones, tuvimos que agregar el atributo <forms EnableCrossAppRedirects ="true"> para que así los clientes una vez autentificados regresaran a la aplicación que querían utilizar.

    Solución

    Para que esto funcione, ya que el formulario cifra los datos, es necesario que las aplicaciones y el formulario de autentificación compartan las llaves de cifrado. Esto nos obliga a generar y declarar explícitamente las llaves a utilizar. Esto se hace de la siguiente forma.

     

    <machineKey validationKey="C50B3C89CB21F4F142.....5C07F6C36DB51F17C529AD3CABE"

    decryptionKey="8A9BE8FD67AF697.....................AF2B72F"

    validation="SHA1" />

    Tabla1

    Este TAG se debe agregar en el archivo de configuración tanto en el formulario de autentificación como en las aplicaciones que deben leer las cookies que generó el formulario.

    Un problema común es cómo generar estas llaves. Como generar estas llaves programáticamente pueden verlo en este ejemplo [2] y desarrollar su generador o utilizar este [3] Free directo del WEB.

    Enjoy!

    Referencias

    [1] Cómo: Proteger la autenticación de formularios en ASP.NET 2.0, http://www.microsoft.com/spanish/msdn/articulos/archivo/201205/voices/paght000012.mspx

    [2] ASP.NET machineKey Generator, http://www.codeproject.com/aspnet/machineKey.asp

    [3] ASP.NET machineKey Generator Software, http://www.developmentnow.com/articles/machinekey_generator.aspx

    October 14

    ESB con WCF, ¿cómo puedo implementar Adaptadores?

    Problema

    Para un proyecto de plataforma móvil estamos haciendo un ESB pequeño que utiliza WCF. La idea es que este ESB permita agregarle nuevos servicios de manera administrativa sin volver a compilar. Estos servicios son expuestos por otros sistemas y no se puede normar los contratos que estos exponen.

    WCF permite llamar servicios a los cuales se le conoce su interfaz mediante el uso de ChannelFactory. Esto serviría pero hay una complicación adicional, no tenemos las interfaces en tiempo de diseño sólo en tiempo de ejecución. En resumen se necesitan en este caso dos cosas:

    1. Llamar servicios en tiempo de ejecución sin volver a compilar el cliente.
    2. Soportar DataContract en las llamadas a los servicios.

     Este es el concepto de adaptador.......

    Solución propuesta, Uso de Reflexión

    Para el primer problema podemos usar reflexión [2]. La reflexión nos permitirá en tiempo de ejecución hacer una instancia del Proxy para el servicio y de los tipos DataContract [3] que este utilice. Esto quiere decir que en tiempo de ejecución cargamos el Assembly [4] que contenga en Proxy y lo invocamos.

    Veamos un ejemplo de un servicio simple en WCF. El código uno muestra el contrato del servicio, esto es lo que describe que es lo que el servicio hace. Luego, el código dos muestra los tipos de datos específicos del contrato del servicio. Por último, el código 3 muestra la implementación del servicio.

     

    [ServiceContract()]

    public interface IService1

    {

        [OperationContract]

        string MyOperation1(string myValue);

        [OperationContract]

        string MyOperation2(DataContract1 dataContractValue);

    }

     

    Código 1: Contrato de servicio.

     

     [DataContract]

    public class DataContract1

    {

        string firstName;

        string lastName;

     

        [DataMember]

        public string FirstName

        {

            get { return firstName; }

            set { firstName = value; }

        }

        [DataMember]

        public string LastName

        {

            get { return lastName; }

            set { lastName = value; }

        }

    }

    Código 2: Datos del Contrato de servicio.

     

     public class service1 : IService1

    {

        public string MyOperation1(string myValue)

        {

            return "Hello: " + myValue;

        }

        public string MyOperation2(DataContract1 dataContractValue)

        {

          return "Hello: " + dataContractValue.FirstName + " " + dataContractValue.LastName;

        }

    }

    Código 3: Implementación del servicio.

    Para que el cliente (ESB) invoque al servicio va a requerir de un Proxy que le permita llamar a los métodos del servicio. Generamos entonces un proxy en un Assembly separado que pueda ser entregado al administrador del ESB para que lo "instale". La instalación no requerirá de compilación del lado del cliente (ESB).

    Una vez que tenemos el Assembly podemos hacer una instancia del Proxy y ejecutar sus métodos. Como ejemplo, primero llamaremos al método MyOperation1 del servicio de ejemplo. Para esto construimos un método de llamado en el cliente como se muestra en el código 4.

     

    /// <summary>

    /// Este método ejecuta el proxy usando reflexion

    /// </summary>

    /// <param name="pathAssembly">Ruta del Assembly del Proxy</param>

    /// <param name="NombreTypoProxy">Tipo del proxy</param>

    /// <param name="NombreOperacion">Nombre del método a Ejecutar</param>

    /// <param name="mParametros">paramtros del método</param>

    public static void EjecutarProxy(string pathAssembly, string NombreTypoProxy,string NombreOperacion, object[] mParametros)

    {

        Console.WriteLine("LLamada a través de un Proxy Externo");

        //1.- Levantar el Assembly que contiene el Proxy.

        Assembly SampleAssembly = Assembly.LoadFile(pathAssembly);

        //2.- Hacen una inctancia de la clase Proxy       

        object myClassObj = SampleAssembly.CreateInstance(NombreTypoProxy);// ("ProxyIntermedio.localhost.Service1Client");

        // 3.- Obtener la información del tipo del Proxy

        Type myTypeObj = myClassObj.GetType();

        // 4.- Obtener información del método a llamar

        MethodInfo myMethodInfo = myTypeObj.GetMethod(NombreOperacion);//("MyOperation1");

        //5.- llamar al servicio, usando el Proxy

        Console.Write("\nLLamando a - " + myTypeObj.FullName + "\n Respuesta: " +

                             myMethodInfo.Invoke(myClassObj, mParametros) + "\n");

        Console.ReadLine();

    }

    Código 4: llamada a través del proxy externo.

    Este ejemplo utiliza un tipo de datos "primitivo" lo cual puede ser muy común pero no necesariamente así es siempre. Para servicios más complejos se usan tipos de datos complejos los cuales se modelan utilizando DataContract. El próximo ejemplo llama al método MyOperation2 que usa un argumento del tipo DataContract1.

    El código 5 muestra cómo podemos llamar a un servicio que tiene como argumento de entrada un tipo de dato complejo haciendo uso de un Proxy externo. El principio es el mismos que en el caos anterior, con la diferencia que ahora debemos instanciar un DataContract y asignarle los valores que correspondan. Para esto usamos las capacidades de Reflexión para instanciar tipos y asignarle valores a sus propiedades como se muestra en el punto 6 del código 5. El código que llama a este método se muestra en el código 6, ahí se puede ver que el parámetro de entrada al método EjecutarProxyTypoComplejo es un diccionario [5] con los valores, el cual será recorrido y asignado dentro del método.

     

    /// <summary>

    /// LLamada utilizando un proxy externo con un método de datos complejo

    /// </summary>

    /// <param name="pathAssembly">Ruta del Assembly del Proxy</param>

    /// <param name="NombreTypoProxy">Tipo del proxy</param>

    /// <param name="NombreTypoData">Nombre tipo del DataContract</param>

    /// <param name="NombreOperacion">Nombre del método a Ejecutar</param>

    /// <param name="mParametros">Diccionario con los valores a asignar al Datacontract</param>

    public static void EjecutarProxyTypoComplejo(string pathAssembly, string NombreTypoProxy,string NombreTypoData,string NombreOperacion, Dictionary<string,string>  mParametros)

    {

        Console.WriteLine("\nLLamada a través de un proxy externo con tipo de dato complejo");

        //1.- Levanatr Assembly

        Assembly SampleAssembly = Assembly.LoadFile(pathAssembly);

        //2.- Crear instancia del Proxy       

        object myClassProxy = SampleAssembly.CreateInstance(NombreTypoProxy);

        //3.- Crear Instancia del DataContract

        object myDataContract = SampleAssembly.CreateInstance(NombreTypoData);

        //4.- Obtener los tipos de datos

        Type myTypeProxy = myClassProxy.GetType();

        Type myTypeData = myDataContract.GetType();

        //5.- Obtener la información del método.

        MethodInfo myMethodInfo = myTypeProxy.GetMethod(NombreOperacion);

        //6.- Asignar los valores al Datacontract1

        PropertyInfo prop;

        foreach (KeyValuePair<string, string> kvp in mParametros)

        {

            prop = myTypeData.GetProperty(kvp.Key);

            prop.SetValue(myDataContract, kvp.Value, null);

        }

        //7.- Objeto para usar como argumento tipado.      

        object[] mParam = new object[] { myDataContract };

        //8.- llamar al servicio

        Console.Write("\nllamando a  - " + myTypeProxy.FullName + " \nRespuesta:  " +

                             myMethodInfo.Invoke(myClassProxy, mParam) + "\n");

        Console.ReadLine();

    }

    Código 5: llamada a través del proxy externo con un tipo de dato complejo.

     

    //..... algun códiogo aqui

    Dictionary<string,string> lala = new Dictionary<string,string>();

    lala.Add("FirstName","Juan Pablo");

    lala.Add("LastName","García González");

    EjecutarProxyTypoComplejo(

        @"..\ProxyIntermedio.dll",

        "ProxyIntermedio.localhost.Service1Client",

        "ProxyIntermedio.localhost.DataContract1",

        "MyOperation2", lala);

    //.... algun código aquií

    Código 6: llamada a través del proxy externo con un tipo de dato complejo.

    Con esta técnica todos los futuros servicios pueden ser enlazados utilizando el Proxy autogenerado para cada servicio.  

     

    Referencias

    [1] Adapter pattern, http://en.wikipedia.org/wiki/Adapter_pattern

    [2] Información general sobre la reflexión, http://msdn2.microsoft.com/es-es/library/f7ykdhsy(VS.80).aspx

    [3]Contratos de Datos, http://www.microsoft.com/spanish/msdn/articulos/archivo/041206/voices/LearnTheABCsOfP.mspx#E3H

    [4] What is a .Net Assembly? , http://www.programmersheaven.com/2/FAQ-DOTNET-DOTNET-Assembly-Explained

    [5] Dictionary Generic Class, http://msdn2.microsoft.com/en-us/library/xfhwa508.aspx

    October 12

    ¿Qué tópicos se deben incluir en un proyecto de SOA?

    Cuando se comienza a desarrollar un proyecto de SOA es necesario detenerse a pensar en todos los aspectos a cubrir para que la adopción de este estilo de arquitectura no se convierta en un problema. Comúnmente se piensa que construir servicios es comenzar con una arquitectura orientada a servicios, pero en rigor afirmar esto es como decir que la arquitectura de una casa de hace construyendo ladrillos.

    Los temas a incluir en el desarrollo de un proyecto de adopción de SOA que considero fundamentales son los siguientes:

    1. Cumplir con los principios de la orientación a Servicios.
    2. Diseño de las capas de Servicios.
    3. Definición del ciclo de vida de los Servicios
    4. Definición de los aspectos operacionales
      1. Soporte de múltiples protocolos estándares.
      2. Despacho garantizado.
      3. Servicios Síncronos y Asíncronos.
      4. Manejo de excepciones.
      5. Seguridad de los Servicios.
      6. Instrumentación.
      7. Contenedor de Servicios
    5. Caso de prueba.

    Cumplir con los principios de la orientación a Servicios

    Los principios de la orientación a servicios son la fundamentación de todo el esfuerzo que se realiza en este tipo de proyectos. Por esta razón se deben cumplir en todo momento con estos principios.

    • Los servicios son reusables.
    • Los servicios comparten contratos no código.
    • Los Servicios tienen bajo acoplamiento.
    • Los servicios tienen Fronteras explicitas.
    • Los Servicios son modulares y permiten la composición.
    • Los Servicios son autónomos.
    • Los servicios deben permitir métodos de descubrimiento.

    Diseño de las capas de Servicios

    En una arquitectura empresarial, es necesario ubicar la capa de servicios entre la capa de negocios y la capa de servicios de aplicación. Lo que se busca lograr con la definición clara de las capas de servicios es poder contestar preguntas fundamentales como:

    • ¿Qué lógica será representada por los servicios?
    • ¿Cómo se relacionaran estos servicios con la lógica de aplicaciones existentes?
    • ¿Cómo los servicios pueden representa de mejor forma los procesos de negocio?
    • ¿Cómo pueden los servicios ser construidos e instalados para promover la agilidad?

    La siguiente figura muestra una idea de las capas y como se busca definirlas.

    Capas

    Definición del ciclo de vida de los Servicios

    Para poder asegurar un resultado predecible en los futuros proyectos de software es necesario definir un proceso de análisis de los servicios que se desean construir.

    El ciclo de vida del proyecto es un conjunto de pasos necesarios que deben ser cumplidos para construir los servicios necesarios de una arquitectura SOA. Los proyectos de implementación de una arquitectura orientada a servicios (SOA), siguen al igual que todos los proyectos de software un ciclo de vida definido.

    Las etapas de este ciclo de vida son:

    • Análisis Orientado a Servicios
    • Diseño Orientado a Servicios
    • Desarrollo de Servicios
    • Prueba de Servicios
    • Instalación de Servicios
    • Operación de Servicios

    Definición de los aspectos de implementación

    Este es el primer punto que se ocupa de los aspectos de implementación. Estos temas son importantes para llevar las definiciones conceptuales de alto nivel a definiciones pragmáticas que los equipos de proyectos puedan utilizar. Por supuesto cada definición de estos aspectos debe cumplir con las orientaciones generales definidas con anterioridad.

    La lista de aspectos a cubrir son:

    • Soporte de múltiples protocolos estándares.
    • Despacho garantizado.
    • Servicios Síncronos y Asíncronos.
    • Manejo de excepciones.
    • Seguridad de los Servicios.
    • Instrumentación.
    • Contenedor de Servicios

    Caso de prueba

    Como estrategia de validación, necesaria en cualquier proyecto, es necesario realizar un caso de prueba. La idea del caso de prueba es validar que las definiciones hechas son posibles de implementar y útiles para la organización.

    Transferencia de Conocimiento

    Por último, uno de los mayores problemas que se enfrentan las organizaciones que enfrentan proyectos de orientación a servicios es que cuando los consultores se retiran debe hacerse cargo de la arquitectura, operarla y seguir extendiéndola.

    Para facilitar estas tareas se debe incluir un plan de transferencia de conocimiento que es más que escribir manuales o hacer una capacitación.

    Estas son las recomendaciones para enfrentar un proyecto de inicio de arquitectura SOA.

    September 25

    Las habilidades de un Jefe de proyectos

    En mi trabajo estamos buscando un jefe de proyectos, por lo que tuvimos que redactar alguna descripción del perfil de este Rol. En ese trabajo me mandaron la siguiente tabla de habilidades que debería tener un jefe de proyecto.

    Me pareció muy completa y precisa por lo que la comparto en este POST. No tengo clara la fuente, por eso no la cito.

    El Project Manager por el alcance de sus funciones, del equipo y recursos que administra, y por las variables y escenarios que se presentan, debería tener en mayor o menor grado algunas de las siguientes habilidades:

     

    Skill

    Breve descripción

    Coping

    Capacidad de tener una actitud madura ante conflictos y al resolver problemas.

    Tolerance of ambiguity

    Capacidad de tomar decisiones sin tener suficiente información. Usualmente son
    situaciones de incertidumbre.

    Decisiveness

    Capacidad para tomar decisiones y aceptar compromisos. Los compromisos siempre son
    asumidos.

    Spoken Communication

    Capacidad para hablar en público y presentar información, tanto en escenarios
    positivos como negativos.

    Assertiveness

    Capacidad de expresar opiniones ya sean a favor o en contra a una posición, siempre
    manteniendo el punto de vista propio.

    Energizing

    Capacidad de crear un buen ambiente y transmitir energía positiva.

    Policy & Procedures

    Capacidad de adaptarse fácilmente a los procedimientos y política de la empresa.

    Alertness

    Capacidad de estar alerta ante los entornos externos, y cómo este afectan al trabajo del
    grupo.

    Analytical Problem Solving

    Capacidad de razonamiento y uso de un proceso lógico analítico para resolver un
    problema, identificar las posibles soluciones y elegir la más adecuada.

    Goal Setting

    Capacidad para establecer metas realistas, objetivos y su definición.

    Written Communication

    Capacidad para comunicarse de forma correcta a través de la escritura. Permite
    transmitir las ideas y conseguir los objetivos planteados.

    Commitment to Risk

    Capacidad de compromiso ante un objetivo, asignación o meta, manteniendo una actitud
    positiva y con motivación.

    Organization & Planning

    Capacidad para organizar tareas, personas en un calendario y realizar el
    correspondiente seguimiento.

    Creativity

    Capacidad para buscar soluciones creativas e innovadoras a problemas que se presenten
    en el proyecto.

    Interaction

    Capacidad de comunicación cálida, transmitiendo seguridad y motivación al equipo de
    trabajo.

    Perceptivity

    Capacidad para interpretar la comunicación verbal y no verbal de las otras personas. De
    esta forma se puede conocer sus necesidades y opiniones.

    Versatility

    Capacidad “camaleónica” de poder cambiar opiniones, ideas, para poder
    conseguir objetivos.

    Reading the system

    Capacidad para entender el funcionamiento interno de una organización, de tal forma que
    se puedan conseguir objetivos específicos. Esto sucede con mayor frecuencia en empresas públicas donde existe burocracia y muchos niveles de aprobación.

    Team Building

    Capacidad para trabajar y formentar equipos de trabajo, creando entornos apropiados con el fin de conseguir un objetivo en común.

    Decision Making & Problem Solving

    Capacidad de tomar decisiones con razonamiento, dejando de un lado el aspecto emocional.

    Leadership

    Capacidad de influencia y hacer que las otras personas te sigan hacia un fin en común.

     Jefe de Proyecto

     

    August 30

    Aplicación Windows Mobile con BackOffice SAP ¿Cómo sincronizar Datos?

    Hola,

    Me llegó la siguiente pregunta, muy interesante por eso la subo aquí a la sección de Q&A del Blog.

    Problemática

    Una empresa quiere desarrollar una aplicación móvil en Windows Mobile que funcione desconectada con datos extraídos de SAP en la mañana (usando la cuna) y por la tarde poniéndolos en el móvil en la cuna subir los datos nuevamente. Para ello utiliza un Web Service que expone el módulo Business Connector.

    ¿Cómo hacer eso? ¿Usar Active Sync?

    “Solucionatica”

    En este caso se me ocurren dos soluciones, la primera 100% implementada en Service-Oriented y la segunda una combinación de Data-Centric y Service-Oriented. Para los que no estén familiarizados con estos conceptos, pueden ver este POST.

     

    Opción 1: Service-Oriented

    Que la aplicación móvil consuma los servicios Web de descarga de datos directamente (cuando está en la cuna) e inserte los valores en la DB. Luego la aplicación trabaja desconectada para al final del día cuando sea puesta en la cuna subir los datos a través de un Servicio Web de Update y solución de conflictos.

     

    Opción 2: Mixta Service-Oriented y Data-Centric

    En esta solución se utilizaría una base de datos intermedia (MSSQL2005) la cual utilizando SSIS cargaría los datos desde SAP a través del Web Services. Luego, utilizando replicación con la PDA transfiere los datos necesarios para móvil. Luego al final del día se sincronizan los datos utilizando las facilidades de MSSQL y su motor de resolución de conflictos. Por último, SSIS pasa los datos ya consolidados desde MSSQL a SAP a través del Web Services de Upload.

    Los Pro y contras de cada solución.

     

    Aspecto

    Service-Oriented

    Mixta

    Esfuerzo de programación.

    Alto, la resolución de conflictos no es simple

    Si MSSQL resuelve los conflictos es trivial.

    Costos Licenciamiento

    Sin costos adicionales.

    Licencia de MSSQL 2005

    Rapidez de descarga

    Está es más rápida, no tiene SSIS intermediando ni el servicio de replicación de MSSQL.

    Tiene una pieza intermedia extra.

    Efectividad en resolución de conflictos en datos

    Puede ser 100% efectiva, todo depende de la lógica programada.

    Tiene las limitaciones del motor de resolución de conflictos de MSSQL, que no es malo pero tiene sus limitaciones.

    Administración

    Solo se requiere instalar la aplicación.

    Además de instalar la aplicación hay que configurar en cada equipo la replicación.

    Conocimientos del equipo

    Web Services.

    Aplicaciones Móviles.

    TSQL

    Web Services

    Aplicaciones móviles

    SSIS y TSQL

    En mi opinión yo tomaría la opción 1 si tengo un equipo de desarrollo con experiencia. Si no es así me iría por la opción mixta, para no tener que programar la resolución de conflictos.

    Salu2

    August 22

    BlackBerry ¿Cómo Cargar un JAR sin usar un Servidor BES?

    Un estudiante que está comenzando a desarrollar en BlackBerry me pregunta cómo puede cargar un programa cliente Java, JAR/JAD por ejemplo, a su teléfono BlackBerry.

    El proceso regular para cargar aplicaciones en el teléfono Blackberry es a través de un Servidor BES (BlackBerry Enterprise Server).

    Ahora, describo los detalles de cómo convertir los ficheros JAR/JAD en ficheros ALX/COD, para poder cargar manualmente las aplicaciones en los terminales BlackBerry, por ejemplo, a través del Desktop Manager.

    INSTRUCCIONES:

    Se requiere que descargues 2 programas y que los instales en el PC/Laptop donde se realizará la conversión de los ficheros. Los programas que se requiere instalar son:

    - Sun Java SDK:

    Lo puedes descargar de la web: http://java.sun.com/j2se/1.4.2/download.html

    *** Asegurate que descargues el SDK y no el JRE

    - RIM Java Development Environment (JDE):

    Lo puedes descargar de la web: http://www.blackberry.net/developers/

    Yo personalmente tengo instalado múltiples versiones del JDE, pero la conversión de estos ficheros la hice con el 4.0.2

    Una vez que ambos programas estén instalados, puedes copiar los ficheros a convertir (los midlets) .JAR y .JAD.

    Para facilidad de uso, se pueden copiar los ficheros mencionados antes, al directorio BIN del Java Development Environment, por ejemplo:

    c:\program files\Research in Motion\Blackberry JDE 4.0.2\bin\

    Para la conversión de los ficheros se utiliza la herramienta RAPC.exe (este ejecutable se encuentra en el subdirectorio BIN de la instalación del programa JDE), a través de la línea de comandos DOS. He resumido el procedimiento y básicamente la línea que debes utilizar en la ventana de DOS para realizar la conversión de los ficheros JAD y JAR en COD y ALX es:

    rapc import="C:\Program Files\Research In Motion\BlackBerry JDE 4.0.2\lib\net_rim_api.jar" codename=Sametime75 -midlet jad=Sametime75.jad Sametime75.jar

    Donde debes reemplazar el nombre asociado a la variable "codename" y los nombres indicados en la entrada "-midlet jad", que en el ejemplo he llamado Sametime75, por el nombre de la aplicación y el nombre de los ficheros a utilizar.

    Recuerda:

    - Los ficheros los tienes que copiar en el directorio BIN del JDE 4.0.2 (el JAR y el JAD)

    - El programa RAPC lo debes ejecutar desde la carpeta BIN también

    Una vez que ejecutas el comando RAPC, se genera el fichero .COD en la carpeta BIN. Para generar el ALX, sólo necesitas el NotePad de Windows y editar la siguiente plantilla que te anexo:

    <loader version="1.0">
        <application id="SAMETIME">
            <name>SAMETIME</name>
            <description>Version 7.5</description>
            <version>7.5</version>
            <vendor>Vendor Name</vendor>
            <copyright>Not needed but can be anything</copyright>
            <fileset Java="1.0">
                <files>
                    Sametime75.cod
                </files>
            </fileset>
        </application>
    </loader>
    

    Nuevamente reemplaza los nombres donde he incluido "Sametime", con el nombre de tu aplicación, y reemplaza las entradas como "description", "version" y "copyright", con la información que quieras agregar. Luego "salva este fichero como tipo ALX", NO como texto (TXT).

    Con esto ya tendrás el fichero .COD y el fichero .ALX.

    Saludos,

    August 14

    Windows Comunication Foundation WCF, ¿Como habilitar un cache?

    Problemática

    En un proyecto se está construyendo un ESB que tiene un despachador. Este despachador recibe las llamadas de las aplicaciones clientes y viendo en el catálogo de servicio resuelve que por cuales "filtros" hace pasar la llamada antes de invocar el servicio de Negocio que implementa la lógica que el cliente espera.

    image

    La idea es que el despachador arma un "Pipe" para cada servicio en el cual incluye los filtros que en el catálogo de servicios fueron configurados para ese servicio. Por ejemplo, un servicio puede tener los filtros de LOG y Medición de tiempos, mientras que otro servicio puede tener configurado LOG y Caché.

    Para aumentar el desempeño hay que evitar que por cada llama a un servicio el despachador vaya a la base de datos del catálogo de servicios para armar el Pipe, si ya lo llamó no necesita ir a leer nuevamente cuales son los filtros que el pipe de ese Servicio contiene.

    Aquí viene la pregunta ¿Cómo hago en WCF para poder mantener en memoria los Pipe de servicios que fueron llamados? Con la idea de evitar volver a leer la configuración.

     

    "Solucionatica"

    Bueno, está preocupación por la optimización de los tiempos de respuesta en el despachador es muy buena porque usando el concepto de Cache se pueden evitar consultas a la base de datos, reemplazándolas por consultas en memoria, lo que haría mucho más rápido el tiempo de respuesta.

    WCF brinda opciones para poder implementar esto. Yo escogí incluir el Cache en el Host como propiedades. La clase Host es la que levanta los EndPoint en WCF y aloja los servicios. Todas las instancias de servicios que se ejecutan tienen acceso al Host, por lo que instalar ahí el cache se hace simple. Ahora, ojo con la concurrencia ya que las ejecuciones de las llamadas al servicio son concurrentes.

    A.- Primero veamos la clase Pipe (Qué simula el Pipe del problema).

    La clase Pipe es el recurso que queremos poder poner el en Cache de nuestro Servicio. Se muestra en el código uno la clase.

    El código 1 muestra el elemento Pipe que será el recurso a almacenar en el Cache.

    /// <summary>

    /// Pipe de ejemplo, elemto a poner el en cache

    /// </summary>

    public class Pipe

    {

    private int _idServicio;

     

    public int idServicio

    {

    get { return _idServicio; }

    set { _idServicio = value; }

    }

    private DateTime fechaCreacion;

     

    public DateTime FechaCreacion

    {

    get { return fechaCreacion; }

    set { fechaCreacion = value; }

    }

     

    public Pipe(int IdServicio)

    {

    this._idServicio = IdServicio;

    }

    }

    Código 1: Clase Pipe, elemento a poner cache

    B.- Clase HostPuls.

    Está clase extiende la clase ServiceHost de WCF para agregarlo propiedades que manejarán el Cache que estamos implementando.

    La propiedad privada _CachePipe es una Lista de elementos del tipo Pipe. Es aquí donde se almacenarán los elementos Pipe que ya se conocen.

    El método AddPipeCache agrega un elemento Pipe nuevo al Cache.

    El método public Pipe BuscarPipe recibe el identificar del servicio y retorna el Pipe que le corresponde.

    El código 2 muestra la clase HostPlus que es el Host extendido.

    /// <summary>

    /// Host de WCF especializado para mantener en Cache elementos

    /// PIPE. Hereda de ServiceHost.

    /// </summary>

    public class HostPlus : ServiceHost

    {

    private int iIdServicioBusquedaCache = 0;

    private int lala = 0;

    public int Lala

    {

    get { return lala; }

    set { lala = value; }

    }

    /// <summary>

    /// Lista de elementos Pipe en Cache.

    /// </summary>

    private List<Pipe> _CachePipe = new List<Pipe>();

    /// <summary>

    /// Agrega de manera segura un elemento al Cache de PIPE's

    /// </summary>

    /// <param name="nuevoPipe"></param>

    public void AddPipeCache(Pipe nuevoPipe)

    {

    lock (this._CachePipe)

    {

    this._CachePipe.Add(nuevoPipe);

    }

    }

    /// <summary>

    /// Valida si el Pipe es del servivio identificado

    /// por la propiedad iIdServicioBusquedaCache;

    /// </summary>

    /// <param name="Pipe">Elemento del Pipe</param>

    /// <returns>Verdadero o falso </returns>

    private bool BuscarPipe(wcfHolaMundo.HostMaster.Pipe Pipe)

    {

    return Pipe.idServicio == iIdServicioBusquedaCache;

    }

    /// <summary>

    /// Implementa la busqueda de un Pipe para el Servicio.

    /// </summary>

    /// <param name="idServicio">Id del servicio</param>

    /// <returns>Pipe que es de ese servicio</returns>

    public Pipe BuscarPipe(int idServicio)

    {

    iIdServicioBusquedaCache = idServicio;

    return this._CachePipe.Find(new Predicate<wcfHolaMundo.HostMaster.Pipe>(this.BuscarPipe));

     

    }

    /// <summary>

    /// Limpia el Cache, lista de Pipe.

    /// </summary>

    /// <returns></returns>

    public bool ClearPipeCache()

    {

    {

    lock (this._CachePipe)

    {

    this._CachePipe.Clear();

    }

    }

    return true;

    }

    /// <summary>

    /// Constructor

    /// </summary>

    public HostPlus()

    : base()

    {

     

    }

    /// <summary>

    /// Constructor

    /// </summary>

    /// <param name="singletonInstance"></param>

    /// <param name="baseAddress"></param>

    public HostPlus(object singletonInstance, params Uri[] baseAddress)

    : base(singletonInstance, baseAddress)

    { }

    /// <summary>

    /// Constructor

    /// </summary>

    /// <param name="serviceType"></param>

    /// <param name="baseAddress"></param>

    public HostPlus(Type serviceType, params Uri[] baseAddress)

    : base(serviceType, baseAddress)

    { }

     

    }

    Código 2: HostPlus

    C.- El método del Servicio que recibe la llamada y valida en el cache.

    El método "LlamarServicio(int idServicio)" es el método del servicio que recibe un identificador del servicio con el cual se busca en el cache. Si no se encuentra lo crea y agrega al cache para las siguientes llamadas.

    ¿Cómo una instancia del servicio tiene acceso al cache en el Host?

    El acceso al Host se hace a través del "OperationContext". Esa clase tiene el método estático Current que permite acceder al contexto de la operación. Este contexto a su vez accede al Host usando este método "operationContext.Host". Ahora se debe hacer un CAST para pasar del tipo host a nuestro Host especializado el cual tiene el Cache implementado.

    Una vez que tenemos nuestro Host podemos buscar en el Cache si el Pipe de ese servicio está almacenado. Para eso usamos myHost.BuscarPipe(idServicio).

    Si se encuentra el Pipe, se responde con los datos de ese Pipe. Si no se encuentra se crea usando new wcfHolaMundo.HostMaster.Pipe(idServicio) y almacenando en el cache myHost.AddPipeCache(elPipe).

    El siguiente código muestra el método completo del servicio.

    /// <summary>

    /// Este Servicio recibe el identificador

    /// de un servicio y retorna un mensaje Nevo o Viejo

    /// si es que existe o no en el Cache.

    /// Si no existe lo crea en el cache.

    /// </summary>

    /// <param name="idServicio">Identificador </param>

    /// <returns>Nevo o Viejo</returns>

    public string LlamarServicio(int idServicio)

    {

    string strREspuesta = "";

    ///Contexto en el que se ejecuta el Servicio

    OperationContext operationContext = OperationContext.Current;

    ///Instancia del Host

    ServiceHost host = (ServiceHost)operationContext.Host;

    ///instanacia del HostPlus, con Cache implementado.

    wcfHolaMundo.HostMaster.HostPlus myHost =

    (wcfHolaMundo.HostMaster.HostPlus)host;

    wcfHolaMundo.HostMaster.Pipe elPipe;

    //Busca en el cache si el Pipe existe para un servicio

    elPipe = myHost.BuscarPipe(idServicio);

    if (elPipe == null)

    {

    ///No existe Pipe para este Servicio.

    ///Se Crea.

    elPipe = new wcfHolaMundo.HostMaster.Pipe(idServicio);

    elPipe.FechaCreacion = DateTime.Now;

    myHost.AddPipeCache(elPipe);

    strREspuesta = "Nuevo";

    }

    else

    {

    ///Existe Pipe para este Servicio

    strREspuesta = "Viejo, creado el " + elPipe.FechaCreacion.ToString();

    }

    Console.WriteLine(idServicio.ToString() + ": " + strREspuesta);

    return strREspuesta ;

    }

    Código 3: Método del Servicio.

    De esta manera se ha implementado un Cache para aumentar el desempeño evitando en lo posible el tener que crear recursos ya conocidos por el servicio.

    El código del Servicio, Host y cliente para probarlo se puede descargar desde aquí.

    July 23

    Proxy Dinámico en WCF

    Para un proyecto de ESB un ingeniero de software me pregunta cómo hacer un Proxy dinámico en WCF. Entonces yo que soy muy estudioso le digo de inmediato “usemos MEX!!!”

    Este Ingeniero me dice ok necesito un ejemplo. Yo le digo, tengo uno te lo mando….. Problema no encuentro el ejemplo así que voy y le pregunto a dios Google “WCF Dynamic Proxy” y me lleva a esta librería que encapsula toda la complejidad del intercambio del metadata y lo deja en una librería bien armada.

    Les sugiero que vean este ejemplo, todas las flores para el autor.

    Ejemplo de Proxy Dinámico

    Salu2

    July 18

    Biztalk Server ¿Cómo filtrar en el mapper?

    Para un proyecto de BizTalk Server 2006 tuvimos que usar el Mapper de manera intensa. Una de las cosas que aprendí implementando unas transformaciones algo que suena my trivial, y en rigor lo es pero cuando uno sabe cómo hacerlo.

    La problemática es la siguiente:

    Si quiero pasar de un esquema A a un esquema B, dónde el mensaje original tiene un Record con múltiples filas y el destino sólo requiere una fila debemos filtrar.

     ¿Cómo puedo filtrar usando el mapper?

    La solucionatica.

    Para esto se deben usar dos Functoids:

     

    • Equal: Use the Equal functoid to return the value “true” if the first input parameter is equal to the second input parameter. This functoid requires two input parameters.
    • Looping: Use the Looping functoid to combine multiple records and/or fields in the source schema into a single record in the destination schema. This functoid needs at least one input parameter. There is no limit to the number of input parameters that the Looping functoid will accept. Only links are allowable as input parameters.

    La idea es que Looping realiza las iteraciones de todos los elementos contenidos el record. Equal se usa para generar una salida lógica (True/False). La salida de la condición lógica se junta con la salida del Looping. Si el valor de la comparación lógica es verdadero, entonces se copia el registro al destino. Si es falso el registro se ignora.

    Está es una simple implementación de un filtro en el Mapper.

    La siguiente imagen muestra el mapa de ejemplo.

    Mapa de trasformación

    July 11

    Ejecutar Procesos DotNet de manera Controlada

    Se me plantea la siguiente necesidad:

    "… tenemos un proceso complejo de trasferencia de datos entre dos sistemas construido en una aplicación de consola dotnet. Como es muy compleja, no podemos tocarla, es decir es un Pragma[1] para nosotros. Necesitamos controlar la ejecución de este proceso, es decir que se ejecute y si hay errores se notifique a los administradores…… ¿Qué podemos hacer?...."

    Bueno, al ser una aplicación dotnet, la cosa se pone simple. Si usted nunca se ha detenido a considerar que significa que dotnet use código administrado, prepárese porque aquí va a disfrutar una de las ventajas de este tipo de código.

    La solución más simple para esto es hacer que una aplicación que llamaremos "Controlador" sea quien ejecute el "Pragama" que llamaremos en este Post "Proceso". La idea es que el Controlador ejecute el Proceso en su mismo AppDomain[2] utilizando las facilidades que el Framewok da para ello. Esto se muestra en el siguiente código. Específicamente se usa el método ExecuteAssembly[3].

     

    static void Main(string[] args)

    {

    string[] strArgumentoControl= new string[1];

     

    Console.WriteLine("Ejecutar?");

    Console.WriteLine("Ingrese Argumento de Control: ");

    strArgumentoControl[0] = Console.ReadLine();

    try

    {

    AppDomain.CurrentDomain.ExecuteAssembly(

    @"..\Proceso\bin\Debug\Proceso.exe",null,strArgumentoControl );

    }

    catch (Exception X)

    {

    Console.WriteLine("Error: " + X.Message);

     

    }

    Console.ReadLine();

    }

    Código 1

    Lo que hace esto es ejecutar en el mismo dominio de aplicación el Proceso, que está implementado en Proceso.exe. El tercer argumento del método los argumentos que se le pasan al programa que se está ejecutando.

    Hasta ahora nada muy impresionante, esto es lo bueno. Si en el Proceso.exe se levanta una excepción (aspecto que dotnet maneja muy bien) está es atrapada por el Try/Catch del Controlador. Esto es porque los dos programan son código administrado y pueden compartir la información de las excepciones.

    Veamos el Proceso de ejemplo, está en el código 2. Dependiendo del argumento que se le pase Proceso levanta diferentes Excepciones o termina de manera exitosa. Fíjense que no se controlan excepciones aquí, la idea es que si el proceso falla por cualquier motivo sea el Controlador quien se haga cargo.

     

    class Program

    {

    static void Main(string[] args)

    {

    Console.WriteLine("Ejecutando Proceso Controlado...............");

    switch (args[0])

    {

    case "1":

    throw new Exception("Error Tipo Uno");

    case "2":

    throw new Exception("Error Tipo Dos");

    case "3":

    throw new Exception("Error Tipo Tres");

    case "4":

    int iCero = 0;

    Double dNada;

    dNada = 100 / iCero;

    break;

    default:

    Console.WriteLine("Todo Bien :)");

    break;

    }

    Console.WriteLine("Terminó Proceso Controlado...............");

    }

    }

    Código 2

     

    Eso es todo, esto puede ser mucho más sofisticado agregando lógica en Controlador para que distinga los tipos de excepciones, notificaciones, reintentos, etc…etc…

    El Código de ejemplo pueden descargarlo desde Aquí

    Referencias

    [1] Pragma, Pragma a diferencia de un sistema, es algo que se usa "por los bordes" Es decir no se comprende su interior.

    [2] AppDomain, http://msdn2.microsoft.com/en-us/library/system.appdomain.aspx

    [3] ExecuteAssembly, http://msdn2.microsoft.com/en-us/library/system.appdomain.executeassembly.aspx

    June 19

    ¿Cómo hacer un gráfico con Barras y líneas en Reporting Services?

    Hoy me preguntaron si se podía hacer en SSRS un gráfico que mostrara dos series de datos en barras y el promedio de las dos en una línea.

    La respuesta es Sí.

    ¿Cómo se hace?

    Es súper fácil, primero agregamos las dos series que estarán en el gráfico de barras. Por ejemplo costos y ventas, como muestra la ilustración 1.

    Ilustración 1

    Luego la idea es agregar una serie que saque el promedio de las dos series de barra y lo muestre como una línea. Para ello en las propiedades del gráfico, vamos a la pestaña Data y agregamos una serie de valores. Esto se muestra en la ilustración 2.

     

    Ilustración 2

    En el dialogo de creación de la serie se debe agregar el valor de la etiqueta a mostrar, por ejemplo "promedio" y el valor. En el valor usamos las capacidades de SSRS para calcular valores con la siguiente fórmula:

    =Avg(Fields!HOras.Costo+Fields!Prom.Precio)

    Por último para que esta serie se muestre como una línea y no una barra, como las otras dos, debemos seleccionar la opción Plot data as line como muestra la ilustración 3.

    Ilustración 3

    El resultado se muestra en la ilustración 4.

    Eso es todo.

     

    Salu2

    Llamar un web servicies programado en java desde un Visual basic 6.0

    Me llegó el siguiente mail:

     

    Hola Juan Pablo:

    Tienes alguna idea de cómo llamar un web servicies programado en java desde un Visual basic 6.0?
    Si puedes ayudarme, te lo agradecería.
    Que te tengas un buen día.

     

    Por supuesto que se puede llamar un Servicio Web desde Visual Basic 6.0. No es tan fácil como se hace en dotNEt pero es posible.

    Ahora que el servicio Web este hecho en Java, PHP, Piton, etc..etc… no tiene importancia ya que el propósito de los servicios Web es independencia de la tecnología que los implementa.

    Puedes ver los siguientes links con ejemplos:

    α.- Calling Web Services from Visual Basic 6, the Easy Way

    β.- Microsoft Office XP Web Services Toolkit 2.0

    γ.- HOW TO: Integrate a SOAP Toolkit Client with an Apache SOAP 2.2 XML Web Service

    δ.- Sending SOAP Requests by Using the SOAP Toolkit 2.0 Client

     

    Salu2

    May 31

    Medir el desempeño de Servicios Web plataforma DotNet.

     

    Un cliente, como siempre, me ha preguntado cómo puede medir el desempeño de los Web Services que piensa Construir utilizando DotNet.

    Le escribí el siguiente mail, para que pueda usarlo como una guía para hacer mediciones.

     

    ¿Cómo funcionan los Web Services?

    La arquitectura de los Web Services [1] está basada en la infraestructura ASP.NET y usa serialización XML [2]. Cuando un el servidor Web procesa una requerimiento HTTP para un Web Services, Internet Information Server (IIS) [3] mapea la extensión (.asmx) a la interfaz de programación de aplicaciones Internet Server (ISAPI) [4] de ASP.NET (Aspnet_Isapi.dll). Está ISAPI entonces envía el requerimiento al proceso de trabajo de ASP.NET, donde entra en el Pipeline de procesamiento de requerimientos, el cual es contralo por el objeto HttpRuntime [5]. Esto se muestra en el diagrama 1.

     

    Diagrama 1: Arquitectura ASP.NET Web Services y flujo de requerimientos

    El requerimiento pasa inicialmente por el objeto HttpApplication [6], seguido por la serie de objetos HttpModule [7] registrados. Los objetos HttpModule son registrados en el archivo de configuración Machine.config o en la sección <httpModules> del Web.config de cada Servicio Web. Los objetos HttpModule son los responsables de manejar los aspectos como autentificación, autorización, Caching y otras tareas trasversales.

    Luego de pasar el requerimiento a través de los módulos HTTP en el Pipeline, el objeto HttpRuntime verifica con el administrador Webservicehandlerfactory [8] que la extensión .asmx esté registrada. Este crea una instancia del administrador HTTP que es responsable de procesar el requerimiento al Web Services. Este administrador (Handle) deriva de WebServicesHandler [9]. El administrador HTTP usa reflexión (Reflection) [10] para trasformar el mensaje SOAP en invocaciones a los métodos del Web Services.

    Medidas de desempeño para Web Services

    Para determinar de manera efectiva el desempeño de Web Services en DotNet es necesario poder medir los siguientes aspectos:

    • Throghput: Medida de la cantidad de requerimientos ejecutados por segundo y cuellos de botella relativos al Throghput, como el número de requerimiento en espera de ser ejecutados y el número de requerimientos que se están rechazando.
    • Cost of throghput: Medida del uso de procesador, memoria, I/O de disco y utilización de red para responder a los requerimientos que se están ejecutando.
    • Request Execution Time: medida del tiempo que toma la ejecución de un método del Web Services en el servidor.
    • Latency: Medida del tiempo que toma la ejecución y llegada de la respuesta al cliente de un requerimiento al Web Services.
    • Cache utilization: Medida de la razón entre Cache Hits y Cache misses. Esto necesita ser visto en un contexto amplio porque el uso de memoria virtual afecta el desempeño del cache.
    • Error and Exception: medida del número de errores y excepciones generadas.
    • Xml Serialization: Mide el costo de la serialización de XML, muy importante en los Servicios Web.

    ¿Cómo medir?

    Como los Web Services son un caso particular de ASP.NET es necesario aclarar primero como medir desempeño en ASP.NET. Para esto es necesario preliminarmente utilizar la herramienta Performance Counter [12].

    El siguiente diagrama 2 muestra el ciclo de vida de los requerimientos en ASP.NET.

     

    Diagrama 2: Ciclo de vida y medidas para un requerimiento ASP.NET

    Throughput

    • ASP.NET Applications\Requests/Sec

      Umbral: depende de la lógica de negocio.

      Significado: es uno de los primeros indicadores que se usan para calcular la capacidad necesaria para el sistema.

    • Web Service\ISAPI Extension Requests/sec

      Umbral: depende de la lógica de negocio.

      Significado: La tasa de requerimientos a la ISAPI que se están procesando simultáneamente. Este contador no es afectado por los Work process que se reinician como si lo es ASP.NET Applications\Requests/Sec.

       

    Cost of Throughput

    El costo del throughput es la medida del uso de procesador, memoria, I/O de disco y utilización de red para responder a los requerimientos que se están ejecutando. Esto no es específico a los Web Servies ni ASP.NET. Pueden verse los indicadores en detalle en el capítulo 15, sección System Resource [11].

     

     

    Request

    • ASP.NET\Requests Current

      Umbral: No tiene un valor específico.

      Significado: Número de requerimientos que está manejando la ISAPI, incluidos encola, ejecutándose y esperando a escribir en el cliente. ASP.NET comienza a rechazar requerimientos cuando el contador excede el número definido en requestQueueLimit.

       

    • ASP.NET Applications\Requests Executing

      Umbral: No tiene un valor específico.

      Significado: Número de requerimientos que se están ejecutando. El objeto HttpRuntime controla este contador, incrementándolo cuando atiende un nuevo requerimiento y disminuyéndolo cuando terminar de procesar el requerimiento.

       

    • ASP.NET Applications\ Requests Timed Out

      Umbral: No tiene un valor específico.

      Significado: Cantidad de requerimientos que dieron TimeOut y no se ejecutaron.

       

    Queues

    • ASP.NET\ Requests Queued

      Umbral: No tiene un valor específico.

      Significado: Cantidad de requerimientos actualmente en colas. Los requerimientos encolados tienen un límite fijado por configuración en el parámetro requestQueueLimit que tiene como límite por defecto 5.000.

       

    • ASP.NET Applications\ Requests In Application

      Umbral: No tiene un valor específico.

      Significado: Cantidad de requerimientos actualmente en cola para cada directorio virtual, que es el equivalente a una aplicación. Estos requerimientos encolados tienen un límite fijado por configuración en el parámetro appRequestQueueLimit , cuando es superado este límite retorna el mensaje "Server Too busy".

       

    • Queue ASP.NET\ Requests Rejected

      Umbral: No tiene un valor específico.

      Significado: representa el número de requerimientos rechazados porque la cola de requerimientos está llena. ASP.NET Work Process comienza a rechazar requerimientos cuando sobrepasa el límite configurado en requestQueueLimit la medida ASP.NET\ Requests Queued.

       

    • ASP.NET\ Requests Wait Time

      Umbral: 1.000 milisegundos, El promedio debe tender a cero segundos de tiempo de espera en la cola de requerimientos.

      Significado: representa el tiempo de espera del último requerimiento en la cola Name Pipe entre IIS y el Work Process ASP.NET. Esta medida no incluye ningún otro tiempo de espera.

       

    Response Time and Latency

    El tiempo de respuesta y la latencia pueden ser medidos desde la perspectiva del cliente o del servidor. Del lado del cliente, se puede medir el tiempo desde que llega el primer y el último byte de la respuesta. La latencia en este caso incluye la latencia de la red (tiempo que agrega la red) y la latencia del servidor (tiempo que toma el servicio en responder al requerimiento). La medida del primer Byte se llama TTFB y la del último TTLB y se pueden capturar con herramientas como ACT [13].

    En el lado del cliente es posible medir el tiempo de ejecución de un requerimiento utilizando el contador ASP.NET\Request Execution Time. El diagrama 3 muestra las principales componentes necesarias para estas medidas.

    Diagrama 3

    • TTFB

      Umbral: Depende del tipo de requerimiento.

      Significado: Tiempo que pasa entre el envío del requerimiento y la recepción del primer Byte de la respuesta.

       

       

    • TTLB

      Umbral: Depende del tipo de requerimiento.

      Significado: Tiempo que pasa entre el envío del requerimiento y la recepción del último Byte de la respuesta.

     

    • ASP.NET\Request Execution Time

      Umbral: Depende del tipo de requerimiento.

      Significado: Tiempo que se tomó la ejecución del último requerimiento procesado.

       

    Cache Utilization

    • ASP.NET Applications\Cache Total Entries

      Umbral: no tiene un valor específico.

      Significado: este contador muestra la cantidad de elementos en el cache, tanto internos como externos. ASP.NET usa el chache para almacenar objetos que son caros de crear por ejemplo objetos de configuración.

       

    • ASP.NET Applications\Cache Total Hit Ratio

      Umbral: Con memoria suficiente normalmente se debe tener sobre el 80%.

      Significado: este contador muestra las llamadas al Cache tanto internas como externas.

       

    Loading

    • .NET CLR Loading\ Current appdomains

      Umbral: el valor debe ser el mismo que el numero de aplicaciones Web más uno.

      Significado: el número de Appdomains cargados en el proceso.

       

    • .NET CLR Loading\ Current Assemblies

      Umbral: No tiene un valor específico.

      Significado: el número de Assemblies cargados en el proceso.

     

    Worker Process Restarts

    • ASP.NET\ Worker Process Restarts

      Umbral: No tiene un valor específico.

      Significado: el número de veces que se recicla al aplicación Web y el Work process.

    Xml Serialization

    Cuando se serializa y se hidrata un objeto, proceso inverso, es posible calcular el costo de estas acciones en términos del uso de memoria y el tamaño de la data. Para esto se puede utilizar el siguiente código de ejemplo [11].

    using System;

    using System.IO;

    using System.Xml;

    using System.Xml.Serialization;

    using System.Text;

    using System.Data;

    //A sample class for serialization

    public class MyClass

    {

    public string name;

    public string surName;

    public MyClass()

    {

    name = "FirstName";

    surName = "LastName";

    }

    }

    class Class1

    {

    private static long startMemory, endMemory, gcMemory, actualMemory,

    overHeadMemory;

    private static double percentOverhead;

    static void Main(string[] args)

    {

    //stream to which the class object shall be serialized

    Stream fs = new FileStream("SomeFile.txt", FileMode.Create);

    MyClass mc = new MyClass(); XmlSerializer xs = new XmlSerializer(typeof(MyClass));

    XmlWriter writer = new XmlTextWriter(fs, new UTF8Encoding());

    // Clean up the GC memory and measure the measuring as the baseline before

    // performing the serialization

    System.GC.Collect();

    System.GC.WaitForPendingFinalizers();

    startMemory = System.GC.GetTotalMemory(false);

    xs.Serialize(writer, mc);

    //Calculate the overhead and the amount of data after serialization

    CalculateOverhead(fs.Position);

    DisplayInfo();

    writer.Close();

    fs.Close();

    Console.ReadLine();

    }

    public static void CalculateOverhead(long streamPosition)

    {

    endMemory = System.GC.GetTotalMemory(false);

    gcMemory = endMemory - startMemory;

    actualMemory = streamPosition;

    overHeadMemory = gcMemory - actualMemory;

    percentOverhead = ((double)(overHeadMemory * 100)) /

    (double)actualMemory;

    }

    public static void DisplayInfo()

    {

    Console.WriteLine("Total amount of data after serialization ->" + actualMemory);

    Console.WriteLine("Total memory used by GC for serialization ->" + gcMemory);

    Console.WriteLine("Overhead memory used serialization ->" + overHeadMemory);

    Console.WriteLine("Percent overhead ->" + percentOverhead);

    }

    }

    Código 1: Serialización

     

    Referencias

    1. Web Serices, http://en.wikipedia.org/wiki/Web_services
    2. Serialización XML, http://msdn2.microsoft.com/es-es/library/90c86ass(VS.80).aspx
    3. Internet Information Services, http://es.wikipedia.org/wiki/IIS
    4. ISAPI, http://en.wikipedia.org/wiki/ISAPI
    5. HttpRuntime (Clase) ,

      http://msdn2.microsoft.com/es-es/library/system.web.httpruntime(VS.80).aspx

    6. HttpApplication ,

      http://msdn2.microsoft.com/es-es/library/system.web.httpapplication(VS.80).aspx

    7. HttpModules, http://msdn2.microsoft.com/en-us/library/zec9k340(VS.71).aspx
    8. WebServiceHandlerFactory Class,

      http://msdn2.microsoft.com/en-us/library/system.web.services.protocols.webservicehandlerfactory.aspx

    9. Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET,

      http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/02/09/httppipelines/

    10. Reflection (computer science), http://en.wikipedia.org/wiki/Reflection_(computer_science)
    11. Improving .NET Application Performance and Scalability,

      http://msdn2.microsoft.com/en-us/library/ms998530.aspx

    12. Working with Performance Counters,

      http://www.microsoft.com/technet/prodtechnol/acs/reskit/acrkch10.mspx

    13. Microsoft Application Center Test,

      http://msdn2.microsoft.com/en-us/library/aa287410(VS.71).aspx

    April 22

    BizTalk Server 2006 en alta disponibilidad

     

    Un equipo de proyectos me mostró una propuesta de instalación de BizTalk para soportar alta disponibilidad y me preguntó si eso funcionaría.

    La instalación de BizTalk era algo como se muestra en la figura 1. Es un balanceador de carga con dos nodos corriendo BizTalk y un cluster MSSQL 2005.

    Ahora, la respuesta como siempre dice Dagum "depende". Voy a tratar de dar algunas luces de esto =) y asumiendo algunas cosas, evitar el depende.

    Bueno, primero aclaremos algunas cosas. BizTalk Server 2006 está hecho por diseño para ser instalado en un ambiente "High Availability" [1].

    La instalación de BizTalk Server en alta disponibilidad implica tener cada componente funcional en una instalación redundante. BizTalk server simplifica enfrentar estos escenarios separando conceptualmente las responsabilidades de almacenamiento de datos de las de procesamiento de estos. Por lo tanto, para tener una instalación de alta disponibilidad se necesitan correr múltiples Host de BizTalk contra un MSSQL en Cluster.

    Fig1. Instalación BizTalk

    Hasta ahora vamos bien. Avancemos un poco. ¿Qué pasa con la recepción de mensajes, orquestaciones y envío de mensajes si cae un Host de BizTalk?

    Aquí hay que entender en concepto de Host y Host Instance de BizTalk Server antes de avanzar.

    Un Host BizTalk es un contenedor lógico creado dentro de un BizTalk Server Group que puede contener objetos de BizTalk como Adapter Handler, recive Location (incluidos sus PipeLine) y orquestaciones. Típicamente se agrupan en un Host los objetos que son del mismo contexto de aplicación [3].

    Una vez que se crean los Host (contenedores lógicos) estos se pueden asignar a diferentes nodos que tengan el servicio BizTalk corriendo, pasando a ser una "Host Instance".

    La figura 2 muestra una instalación con dos nodos, 3 Host y 6 Host Instance que tienen como servidor de datos un cluster MSSQL. Un detalle de este ejemplo puede verse en MSDN [4].

    Fig2. Instalación BizTalk de ejemplo con Host.

    Ahora, qué diferencia hay entre el dibujo que se me presentó (Fig. 1) y la instalación la segunda instalación (Fig 2.). Principalmente dos puntos muy importantes.

    Primero, en la segunda figura se presenta un esquema de Host BizTalk, que es la manera natural de hacer instalaciones en alta disponibilidad. Esto no está claro en el primer diagrama.

    Segundo, en la primera instalación hay un SLB[3]. Si se trabaja con Host de BizTalk no es necesario usar un SLB porque BizTalk Server de manera automática distribuye la carga entre los múltiples nodos que corren una Host Instance. Esto es una muy buena solución! Pero tiene la limitante que si usted utiliza recepción de mensajes HTTP, SOAP o MSMQT va a necesitar un SLB para que los mensajes puedan ingresar a un Host por diferentes Host Instance.

    Por eso, la respuesta por defecto "depende" sigue siendo válida, pero con un poco mas de información la respuesta podría ser categórica y precisa.

    Referencias

    [1] MSDN BizTalk Sever, http://msdn2.microsoft.com/en-us/library/aa560847.aspx

    [2] MSDN BizTalk Server, http://msdn2.microsoft.com/en-us/library/aa577430.aspx

    [3] Wikipedia, http://en.wikipedia.org/wiki/Load_balancing_(computing)

    [4] MSDN ejemplo de instalación, http://msdn2.microsoft.com/en-us/library/aa578057.aspx