/** * This file contains the {@link RequestDistributor}, * {@link RequestDistributorGateway} and {@link RequestDistributorServer} * classes, which define a sample for the "Request Distributor" sample JGroups * application described in the "JGroups" report and presentation. * * @author Savas Ali TOKMEN, http://ali.tokmen.com */ package com.tokmen.ali.java.jgroups; import org.jgroups.*; import java.util.Random; import java.util.Vector; /** * This is the main class of the Request Distributor application. * * If {@link RequestDistributor#main(String[])} main is called with * gateway as argument then a gateway is created. Otherwise, * a server is created. * * For people who cannot access and/or read the JGroups report/presentation, * here's how the things basically works: * * - The network is formed by one gateway (French name: passerelle * or point d'entrée au réseau) and a group of servers (French * name: serveur). The aim of the network is to respond to * requests (French name: requête) coming from clients (French * name: client). Of course, the network is kept together using * the JGroups protocol. * - A client always sends its request to the gateway. * - The gateway in turn picks up a random server and sends the client's * request to that server. * - The server then processes the request and responds to the client * directly. * * Since the target for this application is a French university, the report and * presentation are in French, so are the messages outputted by the software * and all comments inside methods. * * It is expected for the report and presentation to become online on the * http://scholar.alishomepage.com/Master/JGroups/ website by the * 22nd of October, 2006. * * @author Savas Ali TOKMEN, http://ali.tokmen.com * @version 2006.10.22 */ public class RequestDistributor { /** * Main method of the class. * * @param args Arguments array. */ public static void main(String[] args) throws Exception { Channel channel = new JChannel( "UDP:PING:FD:STABLE:NAKACK:UNICAST:" + "FRAG:FLUSH:GMS:VIEW_ENFORCER:STATE_TRANSFER:QUEUE"); channel.connect("RequestDistributer"); if( args.length > 0 && args[0].compareTo("gateway") == 0 ) { System.out.println("Mode passerelle"); new RequestDistributorGateway(channel); } else { System.out.println("Mode serveur"); new RequestDistributorServer(channel); } channel.disconnect(); channel.close(); } } /** * This class defines the Request Distributor Gateway. This is the object that * normally receives the client's requests; but for simplicity what we've done * is that the RequestDistributorGateway object directly generates requests. * * @author Savas Ali TOKMEN, http://ali.tokmen.com * @version 2006.10.22 */ class RequestDistributorGateway { Random random; Channel channel; /** * Constructor: saves the channel, creates the random number generator and * loops to generate a request every second. Each time a request is * generated, {@link RequestDistributorGateway#OnRequest(String)} is called * with a different argument (an increasing integer). * * @param channel JGroups channel. */ public RequestDistributorGateway( Channel channel ) { int i = 0; this.channel = channel; random = new Random(); // La passerelle simule aussi les clients while(true) { synchronized(this) { // Attendre une seconde entre chaque requête try { this.wait(1000); } catch (InterruptedException e) {} // Générer une requête System.out.println("Requete recue: "+(i++)); try { OnRequest(Integer.toString(i)); } catch (Exception e) {} } } } /** * Called when a request is received. Will pick a server that should * process the request and redirect the request to it. * * @param request Received request. */ public void OnRequest( String request ) throws Exception { // Obtenir la liste des membres du groupe Vector
servers = channel.getView().getMembers(); if( servers.size() <= 1 ){ // Dans ce cas là, il n'y a aucun serveur! System.out.println("Requete intraitable: aucun serveur present!"); } else { int gatewayPosition = servers.indexOf(channel.getLocalAddress()); int targetServer = gatewayPosition; // Sélectionner le serveur qui doit executer la requête en // vérifiant bien que c'est un serveur et pas le point d'entrée while ( targetServer == gatewayPosition ) { targetServer = random.nextInt(servers.size()); } // Rediriger la requête au serveur, qui lui répondra directement au client System.out.println("Il y a "+(servers.size()-1)+" serveurs, requete "+request+" redigirigee vers: "+servers.get(targetServer)); channel.send(new Message( servers.get(targetServer), null, request )); } } } /** * This class defines a Request Distributor Server. This is the object to which * the gateway redirects requests and that will in turn process the request and * answer the client. * * @author Savas Ali TOKMEN, http://ali.tokmen.com * @version 2006.10.22 */ class RequestDistributorServer { /** * Constructor: loops and waits for JGroups messages to arrive. Each time a * message is received, unpacks it to find out the contained request and * processes it. For this extremely simple application processing is simply * outputting the request to the console. * * @param channel JGroups channel. */ public RequestDistributorServer( Channel channel ){ while( true ) { try { // Attendre pour une requête Object o = channel.receive(0); if( o instanceof Message ) { // Vérifier que c'est une requête o = ((Message) o).getObject(); if( o instanceof String ) { // Traiter la requête System.out.println("Requete traitee: "+o); } else { // Juste pour du debug System.out.println("Requete bizarre: "+o); } } } catch (Exception e) {} } } }