Créer une architecture .NET distribuée
Créer des objets distribuée avec .NET Remoting
Présentation de .NET Remoting
Qu'est-ce que le .NET Remoting ?
Le remoting .NET est la dernière technologie en matière d'applications distribuées.
Dans le domaine des applications client serveur, il y a eu une constante évolution.
Parmi les "anciens" concepts on peut citer CORBA, COM+, Java RMI ou plus dernièrement les Web Services.
Qu'est-ce que le .NET Remoting ?
A la différence des Web Services, le .NET remoting n'est pas obligé d'utiliser le protocole SOAP pour communiquer. Il peut utiliser n'importe quel type de protocole. L'avantage du .NET remoting réside dans la flexibilité du transfert (HTTP ou TCP sont proposés d'office par .NET), de l'encodage (SOAP ou en mode binaire qui sont supportés par défaut).
Schéma sur le fonctionnement de .NET remoting
Par contre si l'on recherche avant tout l'interopérabilité, on se tournera plutôt vers les Web Services. L'utilisation principale en remoting sera donc la distribution d'objets .NET. Il n'y a pas qu'une seule façon de faire du remoting aussi le choix final d'implémentation dépendra t-il de vos besoins. Ici nous traiterons des cas simples.
Dans quel cas l'employer ?
Et bien tout simplement que TCP Remoting est bien plus performant que toutes les autres technologies .NET, y compris les WebServices. Son utilisation doit être préférée aux autres méthodes lorsque cela est possible.
Performances des canaux et formats de données .NET Remoting
Dans le cas où les firewall ne posent pas de problème et que la connexion TCP point à point est possible (avec un contexte mono-plateforme) pensez à TCP Remoting.
Dans le cas où les firewalls posent problème et que client et serveur utilisent tout deux la même plate-forme (.NET), préférez IIS Remoting basé sur http. Ainsi, vous aurez la possibilité de profiter des services offerts par IIS concernant la sécurité (Authentification, SSL, HTTPS).
Enfin, dans le cas où client et serveur ne partagent pas le même environnement, il faudra alors envisager de faire appel aux WebServices avec SOAP sur http.
Créer un objet Hello distribué
Un système remoting comporte 3 éléments :
- Un serveur
//Ouvre un canal en mode TCP sur le port '1234'
TcpChannel chnl = new TcpChannel(1234);
ChannelServices.RegisterChannel(chnl, false);
//Publier notre objet EmployeeManager
RemotingConfiguration.RegisterWellKnownServiceType(typeof(EmployeeManager), "EmployeeManager", WellKnownObjectMode.Singleton);
Avec l'objet associé suivant :
public class EmployeeManager:MarshalByRefObject,IRemote.IEmploye
{
EmployeeManager myclass = new EmployeeManager();
//C'est cette classe que l'on distribue sur le reseau
public override object InitializeLifetimeService()
{
//Durée de vie de l'objet : pour "toujours"
return null;
}
public void Augmenter(double dMontant)
{
myclass.Augmenter(dMontant);
}
public string Age()
{
return myclass.Age();
}
}
//Enregistrer le canal TCP port 1234
//HTTP est possible aussi en utilisant System.Runtime.Remoting.Channels.Http
TcpChannel chnl = new TcpChannel();
ChannelServices.RegisterChannel(chnl, false);
//Prendre la référence sur le serveur (tcp://nommachine:port/EmployeeManager.soap)
IRemote.IEmploye mgr = (IRemote.IEmploye)Activator.GetObject(typeof(IRemote.IEmploye),"tcp://localhost:1234/EmployeeManager");
namespace IRemote
{
public interface IEmploye
{
void Augmenter(double dMontant);
string Age();
}
}
c'est dans cette interface que l'on définit les types et les méthodes qui seront délivrées par le serveur.
Sans cette interface, la communication entre le client et le serveur est impossible.
En remoting, on ne peut communiquer que des objets dits "Serialisables". Autrement dit, ceux qui implémentent l'interface ISerializable.
On peut "servir" (dans le sens publier, mettre à la disponibilité des clients) un objet de plusieurs façons:
- Par référence (MarshallByRef): Les objets vivent sur le serveur, et le client utilise une référence à ces objets. On peut comparer ça à un pointeur sur une variable mais sur le réseau.
- Par valeur (MarshallByValue): Le client manipule une copie de l'objet qui est sur le serveur. Clients et serveurs ont chacun leur copie et l'utilisent indépendamment.
Le mode de transmission des données (il y a deux choix possible : Singleton ou SingleCall):
- Singleton : Il n'y a uniquement qu'une seule instance de l'objet au même moment. On peut leur associer une durée de vie (quelques secondes ou éternel). Apres la durée de vie écoulée, le serveur recrée une instance de l'objet à nouveau et la servira aux clients jusqu'à la fin de durée de vie.
- SingleCall : une nouvelle instance de l'objet sera crée à chaque appel et détruite juste après.
Les fichiers de configuration permettent de paramétrer entièrement le système Remoting par l'intermédiaire d'un fichier XML. L'exemple suivant nous illustre la manière de configurer les serveurs, channels, formatters, etc. ... Pour charger le fichier suivant dans un client .NET Remoting, il vous suffit d'utiliser la méthode Configure() décrite ci après :
RemotingConfiguration.Configure ("Remoting.xml");
Avec le fichier XML correspondant :
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="5555">
<serverProviders>
<formatter ref="binary" includeVersions="false"/>
</serverProviders>
</channel>
</channels>
<service>
<wellknown mode="Singleton"
type="Server.CustomerManager, Server"
objectUri="CustomerManager.soap" />
</service>
</application>
</system.runtime.remoting>
</configuration>
Attention : Ajouter une référence à la dll .NET qui s'appelle System.Runtime.Remoting pour le client et le serveur !!
Comparaison avec RMI (Java)
Tableau de Synthèse |
.NET Remoting |
RMI |
Proxy |
Dynamique |
Statique (rmic) ou dynamique |
Squelettes |
Intégré au Framework |
Intégré au Framework |
Objet distribué |
Classes |
Interfaces
Remote |
Configuration |
Fichier
XML |
System
Property |
Annuaire distribué |
Aucun (système interne à base de tables d'objRef) |
RmiRegistry |
Ajout de protocoles |
Channels |
SocketFactoryImpl |
Ajout de formats |
Formatters
|
Serialization |
Activation |
SingleCall,
Singleton ou Client activated |
API coté serveur Activable objects |
CustomProxy |
Custom
RealProxy |
Dynamic Proxy |
Protocoles existants |
HTTP,
TCP, SOAP |
JRMP, IIOP, ORMI (Orion), T3 (WebLogic), ... |
Gestion d'erreur |
Exceptions Remote |
Exceptions Remote |
Le service de nommage fait partie des fondements même d'une application distribuée. Microsoft n'a jamais réellement adhéré à ce concept pour différentes raisons. La première est historique, COM s'est toujours appuyé sur la notion de ProgID et de GUID uniques pour gérer la localisation des objets. Les services de nommage se prêtent assez mal à ce mode de fonctionnement hybride dans lequel un client doit être en mesure de créer un objet serveur dans le processus appelant (CoCreateInstance) de manière totalement transparente.
Par ailleurs, Microsoft a toujours réfuté l'idée même consistant à "imposer" à un client un service spécialisé dont la seule tâche serait de localiser des objets. Cela suppose l'implémentation d'un annuaire de type Active Directory "léger" qu'il est possible d'accéder via l'API du framework gérant les annuaires LDAP, à savoir System.DirectoryServices.
Microsoft n'a pas réinventé la poudre, les mécanismes classiques de distribution via le principe de Proxy ont encore de beaux jours devant eux. La seule différence provient du fait que RMI propose, par défaut, une génération statique de Proxy et que .NET Remoting se base sur un Transparent Proxy (équivalent du Dynamic Proxy de Java). D'ailleurs, dans le monde JAVA, bon nombre de serveurs d'applications EJB fonctionnent déjà avec le mécanisme de Dynamic Proxy (JBoss.org) qui a tendance à remplacer la génération de code.
Concernant les autres caractéristiques de .NET Remoting, nous pouvons remarquer le modèle de développement original basé sur les channels marquant une première ouverture des APIs de Microsoft à des implémentations tierces. A l'heure où j'écris ces quelques lignes, peut-être quelqu'un a t-il déjà pensé à implémenter un Message Formatter pour IIOP au dessus du channel TCP ? ;-) voir la partie suivante sur IIOP.NET