Con la sigla IPC (Inter-Process Communication) si intendono tutte le tecniche che permettono di effettuare comunicazione intra-thread o intra processo.
Queste tecniche sono particolarmente utili in ambienti di integrazione, dove è necessario far comunicare sistemi eterogenei in modo da preservare l'utilizzo di risorse o mitigare eventuali rallentamenti dovuti a congestioni dei sistemi.
Tra queste tecniche, su piattaforma Microsoft, possiamo individuare:
Ognuna di queste tecniche presenta i suoi pro e i suoi contro, ma grazie alla perfetta integrazione con il .net Framework e con WCF, MSMQ è una tecnologia testata, robusta, e rappresenta un'ottima scelta per una implementazione di una comunicazione Inter-Processo.
Vediamo in concreto con uno scenario reale l'impiego di una tecnica IPC. Abbiamo un sistema di terze parti cui è possibile accedere tramite protocollo proprietario attraverso socket, ma le connessioni disponibili per l'accesso a questo sistema sono limitate. Si vuole implementare un'applicazione web che dialoghi con questo sistema, senza che questa applicazione abbia accesso diretto (via socket) al sistema di terze parti onde evitare problematiche di starving della risorsa connessione via socket, disponibile in quantità limitata.
La strategia da impiegare è quella di impiegare un broker, rappresentato in concreto da un servizio di windows, che si occupi si formare la connessione al sistema di terze parti, mentre alla nostra applicazione web non resterà che comunicare con il broker.
Qui entra in gioco la tecnica di comunicazione inter processo. Come prima cosa, vediamo un semplice approccio al problema, lasciando ad un successivo post la soluzione basata sul messaging.
Come sappiamo, un'applicazione web può comunicare con un servizio che abbia sovrascritto il metodo OnCustomCommand, in un modo molto semplice, ovvero mediante l'invocazione di un comando, come possiamo vedere negli snippet seguenti. Per primo, il servizio:
1: namespace CodeSapiens.Services
2: {
3: partial class IPCService : ServiceBase
4: {
5:
6: public IPCService()
7: {
8: InitializeComponent();
9: }
10:
11: protected override void OnCustomCommand(int command)
12: {
13: switch (command)
14: {
15: case 150: //Identificativo del comando
16: //Esecuzione del comando...
17: break;
18: default:
19: break;
20: }
21: }
22: }
23: }
Per finire, il consumer (web application, win application, web service...):
1: _sc = new ServiceController("IPCService");
2: //...
3: public void MyExecuteCommand()
4: {
5: if (_sc.Status == ServiceControllerStatus.Stopped)
6: {
7: _sc.Start();
8: }
9: //Esegue il comando 150
10: _sc.ExecuteCommand(150);
11: }
Questa tecnica, apparentemente banale, è estremamente utile, ma solo nel caso in cui non si debbano passare parametri al servizio, ovvero il comando che viene eseguito sia indipendente da parametri. La tecnica sopradescritta puà essere utilizzata per richiamare un comando da applicazioni web o da web services in modo totalmente trasparente.
Nel prossimo post vedremo come far comunicare in modo espressivamente più "ricco" sistemi indipendenti mediante l'uso di MSMQ.
Nel FW 3.5 è presente una nuova classe per la gestione delle "zone temporali", la classe TimeZoneInfo.
Personalmente ritengo molto utile questa classe, che permette di manipolare efficacemente le date/ore provenienti da diversi server collocati in varie parti del mondo.
Un esempio molto carino può essere ben inquadrato dal seguente scenario: avete un server in California, e questo server deve marcare dei file con una data ben precisa, che deve essere espressa in "tempo italiano" (badate, tempo, non formato!!). Chiaramente, se in un web Service installato su questo server si invoca la DateTime.Now, si ottiene la data/ora espressa nella timezone in cui si trova il server. Ora, volendo riportare tale orario all'orario italiano, andremo incontro ad una serie di criticità:
- Ora legale/solare: essendo la data in un fuso diverso dal nostro, dovremmo conoscere come l'ora legale venga gestita in quella zona
- Intervallo temporale tra il fuso di destinazione e quello estero: dovremmo dare per scontato, o meglio, impostare nel file di configurazione, l'intervallo (in ore) che separa il fuso di destinazione e quello estero; in questo caso il problema nasce se in un secondo tempo si vuole spostare il server in una altra zona (cambio fuso)
Impiegando questa classe, è possibile esprimere gli orari in modo assolutamente automatico, usando l'accortezza di lavorare con la data/ora in formato UTC. In questo piccolo esempio possiamo vedere come la classe possa essere utilizzata per enumerare le timezone del sistema e come possa essere impiegata per convertire la data/ora in formato UTC in una data/ora nel formato della timezone desiderata.
1: namespace TimeZoneTest
2: {
3: class Program
4: {
5: static void Main(string[] args)
6: {
7: foreach (TimeZoneInfo _tzi in TimeZoneInfo.GetSystemTimeZones())
8: {
9: Console.WriteLine(string.Format("{0} {1}", _tzi.StandardName,TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,_tzi)));
10: }
11: Console.WriteLine();
12: Console.WriteLine(string.Format("West Europe Time: {0}",TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"))));
13: Console.WriteLine( string.Format("Pacific Time: {0}",TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"))));
14: Console.ReadLine();
15: }
16: }
17: }
Ovviamente, nel nostro caso, potremmo avere un metodo nella nostra Web Application che converte la data ora del server nella TimeZone desiderata a prescindere da dove questo si trovi, permettendo di fatto lo spostamento dell'applicazione su server collocati in qualunque parte del mondo.