Cercar en aquest blog

Es mostren els missatges amb l'etiqueta de comentaris SOA. Mostrar tots els missatges
Es mostren els missatges amb l'etiqueta de comentaris SOA. Mostrar tots els missatges

23/2/11

Aproximació al disseny d'un servei de peticions escalable, basat en missatge

Un servei de peticions (assitencials), ha de ser molt flexible. S'ha de poder afegir nous tipus de peticions, les existents, han de poder-se modificar fàcilment, cada una ha de ser tractada correctament, i aquest tractament, també ha de ser flexible, s'ha de poder modificar de manera fàcil.

La clau tècnica de tot això està en:
  •  Els parametres del servei han de ser missatges, concretament un d'entrada i un de sortida.
  •  Cada missatge ha de tenir un fluxe de treball associat en el servei.
  •  El servei ha de ser astut i poc intel.ligent. Ha de saber per cada missatge, quin fluxe l'atent, però mai com ho fa. (Càrrega per reflexió de Workflows).
  •  Els Workflows o fluxes de treball, han de tenir el codi, separat del disseny. Amb Això, es pot aconseguir, que un usuari avançat pugui decidir com un fluxe atent un missatge en cada moment. O sigui, pot modificar fluxes de treball. Decisions de negoci en mans de gestors del negoci.



31/10/10

Distribució del negoci (PART IV)

Bé, en aquest post exposaré com crear un client d' un servei WCF. Fer-ho amb la opció del VS és bastant fàcil. El que faré és exposar com fer una classe genèrica que sigui capaç de generar un client transparent per qualsevol servei, coneixent només les operacions d'aquest (interficie) i els missatges que exposa per interactuar amb ell (contractes de dades).

Primer de tot creerem una llibreria que anomenarem TransparentProxy. I dins d'ella una interfície on definirem les operacions que ha de complir el proxy i una classe que ens implementarà un proxy.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TransparentProxy
{
    interface IProxy<T>
        T Client {get;}
        void Close();
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TransparentProxy
{
    public class Proxy<T>: IProxy<T>
    {
        public T Client
        {
            get { throw new NotImplementedException(); }
        }
        public void Close()
        {
            throw new NotImplementedException();
        }
    }
}

Un cop fet això començarem a implementar el proxy. Per fer-ho em de tenir uns mínims coneixements de WCF.
Bàsicament per conectar-nos a un servei necessitem saber:
  1. La adreça on es troba.
  2. Com és vincualen el client i el servei (binding).
  3. El tipus de seguretat en el transport i el missatge.
  4. I si cal, usuari i clau d'accés. SEMPRE HEM D'UTILTZAR UN MECANISME DE AUTENTIFICACIÓ I AUTORITZACIÓ.
I saber que tot això ho trobem al "assembly" System.ServiceModel .

Realment gran part de tot l'esmentat depén del tipus de vincul que volem implementar, i per tant en una primera versió, es una dada que se li ha de comunicar al proxy.

Així doncs us presento una mínima expressió d'un proxy transparent, molt bàsic, però útil per començar a especialitzar-lo cap els nostres serveis. Jo, per exemple, utilitzo serveis federats amb ADFS 2.0, i m'he creat un proxy transparent capaç de conectar-se a qualsevol dels meus serveis.







using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace TransparentProxy
{
    public class Proxy<T>: IProxy<T>
    {
        ChannelFactory<T> ch;
       
       public Proxy(Binding bind, string addr , string userName, string password )
        {

            ch = new ChannelFactory<T>(bind, new EndpointAddress(addr));
            if ((userName != null) && (password!=null))
            {
                // És un exemple, les credencials poden ser passades
                // d'altres maneres, certificats, tokens, etc.
                // Cal docuementar-se.
                
                ch.Credentials.UserName.UserName = userName;
                ch.Credentials.UserName.Password = password;
            }
        }
        
        public T Client
        {
            get { return ch.CreateChannel(); }
        }


        public void Close()
        {
            ch.Close();
        }
    }
}
 


Exemple d'utilització

WSHttpBinding bind=new WSHttpBinding();
bind.Security.Mode = SecurityMode.Message;
bind.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
bind.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
bind.Security.Message.NegotiateServiceCredential = true;
TransparentProxy.IProxy proxy = new TransparentProxy.Proxy(bind, "http://localhost:53538/WCFGAPService/Service.svc", null, null);
IList res = proxy.Client.LListarMetges();
proxy.Close();
return res;


En el proper post conectarem un client Winforms amb el servei, utilitzant el proxy transparent.


22/9/10

Distribució del negoci (PART III)

Finalment només ens queda distribuir realment el negoci. Fins ara només tenim llibreries. Necessitem d’alguna tecnologia que ens ajudi a fer arribar als clients les funcionalitats que hem implemetat. Podem pensar-ne moltes però serem practics, la intenció sempre és faclitari no complicar. Podem distribuir-lo amb una aplicació ASP.Net, amb un Web Service o amb un WCF Services. La primera no es la que jo vull, ja que els meus clients seran aplicaions Winforms. La segona està moltbé però hi ha capes que no comtempla, com són diferents tipus de trasnport i seguretat. I per tant distribuirem amb un servei WCF, de manera mot fàcil, Si coneixem la tecnologia, ens podem adonar que donar diferents opcions de comunicació es molt fàcil de fer i treballar amb diferents maneres d’autentificació i autorització també. Així com garantir la seguretat tant a nivell de transport com de missatge. Però tot això són carecterístiques pòpies de WCF independents del negoci que distribueixen. Aqui está la gràcia de arquitecturar els sistemes en capes i nivells.
Primer de tot crerem un nou projecte Web WCF. Un cop fet, agreguerem les referencies a les llibreries que implementen el negoci que volem distribuir. Esborrem totes les classes que tenim a la carpeta App_Code. Editem el “Service.svc” (podem canviar-li el nom si volem), i el modifiquem de la següent manera:





Un cop fet això obriem el Web.config i el modifiquem afegint el nostre negoci com a un servei.




I el provem. Funciona!!!. Ara només li falta afegir configuracions de comportament i seguretat. Però abans de tot jo tinc el costum de provar que funciona i després ja el perfeccionarem. El següent pas serà doncs, crear un client i provar.

10/9/10

Distribució del negoci (PART II)

Un cop tenim definit el servei, pasem a la implementació. Per això afegirem una nova llibreria a la solució que anomenarem ServeisDistribuits.Ingresos.ModulPrincipal.dll.

Afagirem una clase que anomenarem Servei.cs i farem que implementi la interficie IModulPrincipal de la llibreria anteriorment creada. En la implementació de les operacions es on hem de delegar les funcions a la capa de Aplicació on hi ha el negoci o orquestrar (secuenciar) operaciosd’aquesta per poder crear la resposta de la operació del servei en questió. Si ho fem així, aconseguim separar totalment la definició de la implementació. Això pot no tenir sentit en petites aplicacions, però quan la cosa és molt gran podem tenir versions diferents implementades de la mateixa definició. Això facilitat molt la escabilitat, flexibilitat, la reutilització i el desacoplament de capes, i treball en equip, facilitant la posibilitatde fer test abans tenir versions finals, només cal una mica de imaginació.



També hem de pensar que aquesta és l libreria que implementa el servei, i per tant haurà d ser capaç de transmetre els missatges d´error (excepcions) i controlar l’ accés dels usuaris “loginats” en la estació client (en un altre post explicaré com fer-ho demanera molt fàcil)



El codi seria més o menys el seguents.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace ServeisDistribuits.Ingresos.ModulPrincipal
{
    public class Servei:IModulPrincipal
    {
        public IList CercarPacient(CriteriCercarPacient criteri)
        {
            // Aqui podem fer una traça personalitzada d'entrada (usuari, PC, Hora, Missatge entrada....)
            
            // Declarem la variable de retorn

            IList llista = new List();
            try
            {
                // Invoquem el negoci (GAP.dll) i 
                // omplim la llista i la retornem Ex: GAP.Search("Pacients",...

                return llista;
            }
            catch (Exception e)
            {
                // Capturem l'error
                // Fem una traça detallada Ex: Tracert(e)
                // i finalment llacem un missatge al client
                throw new FaultException(".... error .....");
            }
        }

        public IList LListarMetges()
        {
             // Aqui podem fer una traça personalitzada d'entrada (usuari, PC, Hora, Missatge entrada....)
            
            // Declarem la variable de retorn

            IList llista = new List();
            try
            {
                // Invoquem el negoci (GAP.dll) i 
                // omplim la llista i la retornem Ex: GAP.Search("Metges",...

                return llista;
            }
            catch (Exception e)
            {
                // Capturem l'error
                // Fem una traça detallada Ex: Tracert(e)
                // i finalment llacem un missatge al client
                throw new FaultException(".... error .....");
            }
        
        }

        public IList LlistarLlits(LlitEstats estat)
        {
            // Aqui podem fer una traça personalitzada d'entrada (usuari, PC, Hora, Missatge entrada....)

            // Declarem la variable de retorn

            IList llista = new List();
            try
            {
                // Invoquem el negoci (GAP.dll) i 
                // omplim la llista i la retornem Ex: GAP.Search("Llits",...

                return llista;
            }
            catch (Exception e)
            {
                // Capturem l'error
                // Fem una traça detallada Ex: Tracert(e)
                // i finalment llacem un missatge al client
                throw new FaultException(".... error .....");
            }
        }

        public ResultatOperacio Ingresar(DadesIngres dades)
        {
            // Aqui podem fer una traça personalitzada d'entrada (usuari, PC, Hora, Missatge entrada....)

            // Declarem la variable de retorn

            ResultatOperacio  resultat = null;
            try
            {
                // Invoquem el negoci (GAP.dll) i 
                // Executem el negoci Ex: GAP.Save(dades
                // i retornem el resultat.

                return resultat;
            }
            catch (Exception e)
            {
                // Capturem l'error
                // Fem una traça detallada Ex: Tracert(e)
                // i finalment llacem un missatge al client
                throw new FaultException(".... error .....");
            }
        }
    }
}

4/9/10

Distribució del negoci (PART I)

Imaginem que tenim desenvolupat tot el negoci de la Gestió Administrativa de Pacients (GAP) en el nostre nou sistema assistencial. Aquesta part del sistema gestiona diferents arees, com poden ser, dades administratives de pacients (adreces, documents identifiatus, relacions parentals, expedients, etc), ingressos, altes, llistes d’espera i citacions. Evidenment, aquestes parts seran gestionades/utilitzades per usuaris/professionals diferents, amb rols diferents, o sigui, amb permisos per fer algunes coses i altres no.
Seguim imaginant, o no, que volem desenvolupar una aplicació que gestioni només la part d’ingresos (el més obvi seria que gestionés ingressos i altes, però serem simplistes). I per tant i seguin amb la meva proposta de disseny, creerem un servei distribuit que encapsuli les operacions (funcions) necessàries per dur a terme aquesta feina.

Seguim sent simplistes, i ens imaginem que tot el negoci el tenil encapsulat en una llibreria que anomenarem GAP.dll. Les funcions que distribuirem sortiran directament d’aqui o orquestrades a partir de funcions d’aqui. Si fem un anàlisi molt simple del que suposa ingressar una persona trobem que hi participen dos actors i un element d’ ubicació:

  1. El metge A ingressa al pacient P1.
  2. On?
  3. Al llit H15B, que no està ocupat.


Per fer això l’usuari haurà de poder realitzar aquesta relació. Per tal de poder fer-ho haurà de poder seleccionar el pacient, el metge i un llit lliure. Un cop fet això fer l’ingrés.
Seguim sent simples. El nostre hospital és molt petit, només té 20 llits i 4 metges. De pacients en tenim més 25. “Per fer una petita demo ja n’hi ha prou.


Un cop fet el petit anàlisi pasem a la implementació (només hem de distribuir una part del negoci implementat).


Primer de tot, creerem una llibreria que anomenarem:
ServeisDistribuits.Ingresos.dll amb el Visual Studio ( jo utilitzo el 2010).
Dins la llibreria creerem una interfície amb totes les operacions. Aquesta interfície defineix el contracte del servei i l’anomenarem IModulPrincipal.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace ServeisDistribuits.Ingresos
{
    [ServiceContract]
    public interface IModulPrincipal
    {
        /// 
        /// Trona una llista de pacients a partir d'un criteri de recerca
        /// 
        /// 
Criteri de recerca/// 
        [OperationContract]
        IList CercarPacient(CriteriCercarPacient criteri);
        /// 
        /// Retorna la llista de pacients actius
        /// 
        /// 
        [OperationContract]
        IList LListarMetges();

        /// 
        /// Retorna un llista de llits que cumpleixen un estat
        /// 
        /// 
/// 
        [OperationContract]
        IList LlistarLlits(LlitEstats estat);
        /// 
        /// Operació (Verb) que fa l'ingrés
        /// 
        /// 
Dades de l'ingrés/// 
        [OperationContract]
        ResultatOperacio Ingresar(DadesIngres dades);


    }
}

Com podem veure les operacions com a màxim tenen un parametre d' entrada (un missatge d'entrada i un missatge de sortida)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
    /// 
    /// Missatge que representa el criteri de recerca de Pacients
    /// 
    [DataContract]
    public class CriteriCercarPacient
    {
        /// 
        /// Part inicial del Cognom1
        /// 
        /// 
        [DataMember]
        public String Cognom1Comenca;
        /// 
        /// Part Inicial del cognom2
        /// 
        /// 
        [DataMember]
        public String Cognom2Comenca;
        /// 
        /// Part inicial del Nom
        /// 
        /// 
        [DataMember]
        public String NomComenca;

    }
}

--------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
    public class DadesIngres
    {
        [DataMember]
        public String IdPacient;
        [DataMember]
        public String IdMetge;
        [DataMember]
        public String IdLlit;
        [DataMember]
        public String Observacions;
    }
}
---------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
    [DataContract]
    public class InformacioLlits
    {
        [DataMember]
        public String Id;
        [DataMember]
        public EstatLlit Estat;

    }

    public enum EstatLlit
    {
        Buit=1,Ocupat=2
    }
}

---------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
    [DataContract]
    public class InformacioMetges
    {
        [DataMember]
        public String Id;
        [DataMember]
        public String NomMetge;

   
    }
}
---------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
    [DataContract]
    public class InformacioPacient
    {
        [DataMember]
        public String Id;
        [DataMember]
        public String NomPacient;
    }
}
---------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ServeisDistribuits.Ingresos
{
    public enum LlitEstats
    {
        Tots=0, Buits=1, Ocupats=2
    }
}
---------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ServeisDistribuits.Ingresos
{
   [DataContract]
    public class ResultatOperacio
    {
       [DataMember] public String Missatge;
    }
}


.... continuarà

26/3/09

Arquitectura

El sistema que aquí es proposa està basat en una arquitectura orientada a serveis (SOA). Aquest tipus d’arquitectures segueixen una serie de premises, les quals les fan que actualment siguin les millors per aplicar en grans sistemes d’ informació.
Com a concepte defineix serveis per donar suport a les necessitats del negoci. Està demostrat que aquest tipus d’arquitectura facilita la escabilitat i reutilització de codi, la modularitat de les solucions i el desenvolupament de components, així com la interoperabilitat entre sistemes, ja siguin aquests de tercers. En un model basat en serveis web fins i tot s’estanderitza tant que facilita la interoperabilitat entre sistemes basats en tecnologies totalment diferents.
Podem definir el serveis com a funcions sense estat, que no tenen dependencia de cap altre servei, això no vol dir que no l'utilitzin, es poden orquestrar (sequenciar amb altres serveis) afegint la lògica necessària i mai portan un UI (user interface). Això si, faciliten una interfície de comunicació al consumidor (sempre i quan desenvolupem aquesta arquitectura amb eines d 'ultima generació, actuals)
Per tal de desenvolupar serveis, el més important es mentalitzar-se en aquesta arquitectura. Desenvolupar serveis comuns que seran secuenciats per clients. Quan es parla de SOA bàsicament parlem de protocols coneguts a Internet, i quan la gent (desenvolupadors) en parla ho fa referint-se a serveis web. SOA no és igual a Serveis Web. El concepte es més ampli. Els protocols més comuns i coneguts són HTTP, XML, SOAP, WSDL, UDDI, però això no vol dir que siguin requisit de l’arquitectura, ni que siguin els únics. Una cosa és la arquitectura SOA i una altre els protocols de comunicació.
Desenvolupar sistemes d'informació amb aquesta arquitectura porta els seus avantatges:
  • Millorar els temps en els canvis de procesos (facils de modificar)
  • Facilitar la adaptació a models de negoci de tercers.
  • Facilitar la colaboració amb procesos de negoci de tercers (altres proveidors)
  • Facilitar el desenvolupament en capes.
  • Facilitar la integració i la interoperabilitat amb tecnologies diferents.

Existeixen diferents tecnologies de desenvolupament, que faciliten, unes més que altres, el disseny SOA. Empreses com IBM, BEA, SUN o Oracle oferten eines de desenvolupament SOA. Ara bé Microsoft també, a partir de Framework 3.0 amb VS2005. Però amb el VS2008 i el Farmework 3.5, crec que podem anar bé, molt bé. De fet s' estan posant les piles, que ja era hora, pel que fa a entorns de desenvolupament competitius. Recordem que fins fa poc tenien VB6 i C++, quan la tecnologia Java (gratuita i amb IDE's gratuits com Eclipse o Netbeans) ja oferia tecnologia JSP, servlets, Struts, etc, ja oferia la posibilitat de crear Web Services (Axis) i utilitzar tecnologia AJAX en entorns "web" amb DWR (Direct Web Remoting) que començaven a tenir bona acceptació. Com a curiositat dir que GMAIL utilitza DWR com a framework AJAX. Bé dit això, repeteixo, VS2008 i Framework 3.5 són una molt bona opció per desenvolupar SOA, sobretot amb el WCF (Windows Comunication Foundation) i WWF (Windows WorkFlow Foundation). I si ens mirem el que vindrà aviat amb el Framework 4.0, no hi ha dubtes.

Un cop tinguem els serveis, aquest s'hauran de catalogar i allotjar. Per allotjar serveis s' utilitza el que anomenem un ESB (Enterprise Service Bus). Resumint podriem dir que es una "Aplicació" o s'allotgen els serveis, i aquesta facilita el descobriment d'aquest i la comunicació amb ells als clients. Podriem dir que és una evolució del EAI, però no, no són ben bé el mateix.

Ara bé, jo desestimo la opció d'un ESB en aquest moments, mirant el futur del .NET i els SO de Microsoft (Win Server 2008 + II7 + Oslo + Dublin + WAS + PowerShell + ...) crec que amb aquesta linia ens ho donaran fet.

Els serveis els podem catalogar en quatre grups:
Serveis de Negoci
Serveis que formen part del nucli de la empresa i el negoci, normalment identificats per usuaris no tecnics i casos d’ús o escenaris d’aquest. Estan molt lligats amb els verbs CRUD (create, read, update, delete). Un posible exemple seria (CrearClient….). Solen estan desenvolupats amb estandards (Web Services). Solen ser consumits per aplicacions que interactuen amb l’usuari, ja que com he dit complimenten els seus escenaris.
Serveis d’ Empresa
Serveis identificats pels membres del departament Sistemes d’Informació. Solen ser producte de la sequenciació de varis serveis (orquestració), o sigui serveis que fan servir altres serveis per donar una resposta. CalcularPressupost, ProcessarCuaPeticions, etc
Serveis d’ Aplicació
Serveis que no formen part del nucli però hi poden acabar. Són serveis especifics de la Aplicació en questió i es solen identificar amb aquesta. Un exemple actual seria GuardarAdreça de les agendes de la Empresa.
Serveis d’ Infraestructura
Serveis de suport a tots nivells. Logging, auditoria, seguretat. Solen ser identificats per desenvolupadors i gent de sistemes. Exemple EnviaMissatgeLog

I per acabar aquesta part només dir que com a possibles consumidors de serveis podem tenir:

  • Aplicacions
  • Serveis (altres serveis)
  • Dipositius: TAC, ECODOPPLERS, ELECTROS, CONTROLS DE PRESENCIA, PDA...., DOMOTICA,......,ALARMES, SENSORS, .....

Veien aquesta diversitat, crec que SOA es una molt bona opció.


13/3/09

Presentació

Aquest blog ha estat creat amb la intenció de escriure informació basada en el coneixement que vaig assolint d' aquesta arquitectura.En un moment, en que em trobo inmers en un gran projecte (de grans dimensions) del qual se m'ha encarregat el disseny de l'arquitectura del sistema i de les aplicacions (o serveis) que el formaran, crec que aquesta es una manera de deixar escrita la meva experiència.
Freemarket.com Marketplace