9.3. Hello World example

Let us consider the following cases of client-server applications or Web applications:

  • Video streaming

  • Game serving

  • File downloading

  • Etc.

    A classical approach for providing a scalable solution is to distribute the application workload across a set of distributed servers that run the same application: An edge server or network dispatcher or front-end server is the entry point for the application but does not run the application itself. The other servers located on the same LAN handle the workload and answer the client application or client browser.

Figure 9-6. Cluster model


A grid approach extends the concept of clustering by enabling the deployment of servers not only on the same LAN but on a WAN infrastructure. The edge server becomes a broker server that will start the applications on remote servers to handle the workload. The broker can use different criteria to manage this workload:

Use the server located at the nearest location from the client. Use servers according a certain service level agreement with the customer. Use new servers provided by a resource provider for a limited period of time. Use a server that has a better network bandwidth.

Figure 9-7. Grid model


This extended approach underlines several issues that are managed by the Globus Toolkit 2.2:

  • With GSI, the Globus Toolkit 2.2 provides the secure infrastructure needed for an application to be spread across different locations.

  • With GridFTP, the Globus Toolkit 2.2 provides a subsystem to easily, efficiently, and securely move data necessary for the applications.

  • With GRAM and GASS, the Globus Toolkit 2.2 provides mechanisms to easily and securely start remote applications on distributed resources.

9.3.1. The Hello World application

Let us consider a basic example for such an application. A front-end server waits for client requests. When connected, the client is given back a ticket and an application server IP address of where to connect. The application answers hello world! when the client connects to it. The application is started on the “application servers” by the front-end server.

The executable for the client is HelloClient and takes the front-end server host name as a parameter. The source code is provided in “HelloWorld example” on page 341.

The executable for the server itself is HelloServer. The source code is provided in “HelloWorld example” on page 341.

The executable for the front-end server is HelloFrontEnd and starts HelloServer remotely. The source code is provided in “HelloWorld example” on page 341.

Figure 9-8. Hello World example with dynamic library dependencies issues


9.3.2. Dynamic libraries dependencies

In this example, the application depends on a dynamic library (GNU CommonC++ http://www.gnu.org/software/commonc++/) that is not installed by default on the remote servers. To solve this issue, the front-end server installs at startup, the dynamic library on the remote server by compiling it on this server. This is an interesting solution to avoid runtime issues like libc or libstdc++ dependencies or other library dependencies that Common C++ depends on. This library can also be recompiled on different architectures with only the copy of the source code to store.

We store the source copy of the library on a storage server (m0 in the example). The script Compile is used to compile the library and install it.

Example 9-14. Compile script
##################################
# we need to run this script to load
# all correct environment variables.
# The configure script will failed
# otherwise
##################################
. ~/.bash_profile

tar -zxf commoncpp2-1.0.8.tar.gz
[ -d tmp ] || mkdir tmp
cd commoncpp2-1.0.8
################################################
# We use $HOME instead of ~ here because
# make install will failed to create
# directory otherwise
################################################
./configure --prefix=$HOME/tmp && make install
################################################
#Stay clean
################################################
rm -fr commoncpp2-1.0.8

The dynamic library is installed in ~/tmp/lib on the remote host. We use the LD_LIBRARY_PATH variable under the Linux operating system to specify the location of the dynamic libraries to the HelloServer executable. This way, we are not intrusive to the remote system (we do not have to be root and install a binary on the system) and this library will not affect applications other than ours.

LD_LIBRARY_PATH is set automatically during the GRAM invocation by using an environment declaration in the RSL string:

&(executable=https://m0.itso-maya.com:20000/home/globus/HelloServer)
(environment=(LD_LIBRARY_PATH $(HOME)/tmp/lib) ) (count=1)
(arguments=1804289383 t0)

The CommonC++ library source is stored locally in/tmp in m0. We use the ITSO_GASS_TRANSFER class to transfer the file from one GridFTP server to the remote server. The code for the ITSO_GASS_TRANSFER class is provided in “ITSO_GASS_TRANSFER” on page 306 and is based on the globus-url-copy.c code of the Globus Toolkit 2.2. This class provides the member transfer() between two objects of type GLOBUS_URL. GLOBUS_URL is defined in “ITSO_GASS_TRANSFER” on page 306 and is just a C++ wrapper to the globus_url_t C type. The member setURL() sets up the object by providing a valid URL like gsiftp://m0/tmp/test.

The Transfer() method is a C++ wrapper around the Globus asynchronous call to transfer the file from the first URL to the second. It is non-blocking and the program must call the method Wait() to wait for the completion of the transfer.

GRAM is used to submit the compilation of the GNU CommonC++ library and the application startup. The library is transferred and installed remotely from a remote storage server (m0 in the source code example) to the application node (t0 in the source code example) in the tmp directory created in the home directory of the user under which the Compile script is executed.

A GASS server is started locally on the front-end server and listens on port 20000. It used to copy the script Compile and the executable HelloServer from the front-end server to the application server.

Example 9-15. CommonC++ library copy and compilation - HelloFrontEnd.C
main() {
   // We start here the GASS server that will be used:
   //  - to transfer the Compile script to the application nodes
   //   to perform the library compilation
   //  - to transfer the HelloServer used on the remote hosts to
   //  manage clients requests
   // The GASS server arbitraly listens on port 20000
   StartGASSServer(20000);
   // get the hostname using the globus function
   globus_libc_gethostname(hostname, MAXHOSTNAMELEN);

   // ITSO_GRAM_CLIENT does not start the module
   // lets do it
   if (globus_module_activate(GLOBUS_GRAM_CLIENT_MODULE) != GLOBUS_SUCCESS)
   {
      cerr << " Cannot start GRAM module";
      exit(2);
   };

   string node;

   // we use a fixed address for this simple example but
   // nodes=getNodes(SLA, MDS, Workload, ...) in a more complex example
   // we should get here the list of nodes where the application is
   // supposed to run.
   node = "t0";
   // variable used in all for loops
   int i;

   // Here we want test the existence of the file as there is
   // no such checking in the ITSO_GLOBUS_FTP_CLIENT class
   FILE*    fd = fopen("commoncpp2-1.0.8.tar.gz","r");
        if(fd == NULL)
   {
              printf("Error opening commoncpp2-1.0.8.tar.gz file");
              exit(2);
   }
   else
      {
      //that fine, lets go for FTP
      // we can close fd descriptor because a new one
      // will be opened for each ITSO_GLOBUS_FTP_CLIENT object
      fclose(fd);
      //never forget to activate the Globus module you want to use
      globus_module_activate(GLOBUS_GASS_COPY_MODULE);
      //************************************************************
      // In this section we perform the transfer of the dynamic library
      // to the "application server".
      // We use the ITSO_GLOBUS_FTP_CLIENT class to do the task
      // Note that we use the local directory to perform the task.
      // In a real case example, a storage server would be used
      // instead of a local directory =>
      // globus-url-copy gsiftp://storage_server/commoncpp2-1.0.8.tar.gz
      //       gsiftp://application_server/commoncpp2-1.0.8.tar.gz
      //************************************************************
      GLOBUS_URL source,destination;
      source.setURL("gsiftp://m0/tmp/commoncpp2-1.0.8.tar.gz");

      string dst;
      dst="gsiftp://"+node+"/~/commoncpp2-1.0.8.tar.gz";
      destination.setURL(dst);
      globus_module_activate(GLOBUS_GASS_COPY_MODULE);
      ITSO_GASS_TRANSFER transfer;
      transfer.Transfer(source,destination);
      globus_module_deactivate(GLOBUS_GASS_COPY_MODULE);

      //************************************************************
      // In this section we submit the compilation of the
      // dynamic libray.  The script Compile that must be in the
      // current directory is transferred to the remote host
      // and executed.  The result is the installation
      // of the CommonC++ toolkit in the tmp directory of the
      // user under which the script was executed.
      // (globus in the lab environement of the redbook)
      //************************************************************
      // used to store the RSL commands.
      string rsl_req;

      ITSO_GRAM_JOB job;

      cout << "library compilation on " << node << endl;;
      rsl_req = "&(executable=https://";
      rsl_req +=hostname;
      rsl_req += ":20000";
      rsl_req +=get_current_dir_name();
           rsl_req += "/Compile) (count=1)";
      // submit it to the GRAM
      cout << rsl_req << endl;
      //job.Submit(node,rsl_req);
      //job.Wait();
      //************************************************************

      // ticket=getTicket(time, IP address, SLA, ...) in a
      // real production case
      ticket=random();

      // node=getNodes(SLA, MDS, Workload, Application Type, ...)
      // in a real production case
      node="t0";

9.3.3. Starting the application by the resource provider

The front-end server also submits another job to start HelloServer on the application server. HelloServer listens on port 4097 and uses the ticket to authenticate the connection. In the example, the ticket is fixed at the application startup, but for a real production environment other parameters like time, IP address, public/private keys, and so on, may be taken into account to securely authenticate a connection from a client.

The server is arbitrarily started on node t0. Other parameters like MDS information, service level agreements with the customer, workload, resources provider agreements, and such can be used here to determine where the application should be started.

Example 9-16. Front-end server starts the HelloServer on remote node - HelloFrontEnd.C
      // ticket=getTicket(time, IP address, SLA, ...) in a
      // real production case
      ticket=random();

      // node=getNodes(SLA, MDS, Workload, Application Type, ...)
      // in a real production case
      node="t0";

      ITSO_GRAM_JOB job2;

      cout << "start app server on " << node << endl;;
      rsl_req = "&(executable=https://";
      rsl_req +=hostname;
      rsl_req += ":20000";
      rsl_req +=get_current_dir_name();
      rsl_req += "/HelloServer) (environment=(LD_LIBRARY_PATH $(HOME)/tmp/lib)
) (count=1) (arguments=";
      char tmpstr[20];
      sprintf(tmpstr,"%ld ",ticket);
      rsl_req += tmpstr;
      rsl_req += node;
      rsl_req += ")";
      // submit it to the GRAM
      cout << rsl_req << endl;
      job2.Submit(node,rsl_req);
      job2.Wait();

9.3.4. Compilation

All programs (HelloServer.C, HelloClient.C, and HelloFrontEnd.C) use the class provided by the GNU Common C++ library (thread, sockets management). They are not covered in this publication and are only used to quickly develop the examples. Consequently, the header files located in /usr/local/include/cc++2 and the libraries -lccgnu2 -lpthread -dl must be used during the compilation phase. The library is a prerequisite to run these examples.

  1. First, use globus-make-header to generate a file (globus_header) in which variables are set to appropriate values. globus_header will be included in the Makefile.

    globus-makefile-header --flavor=gcc32 globus_io globus_gss_assist
    globus_ftp_client globus_ftp_control globus_gram_job globus_common
    globus_gram_client globus_gass_server_ez > globus_header
    
  2. Use the Makefile shown in Example 9-17 to compile the program.

Example 9-17. Second example Makefile
include globus_header

all: HelloServer HelloClient HelloFrontEnd

%.o: %.C
   g++ -c $(GLOBUS_CPPFLAGS) $< -o $@

HelloServer: HelloServer.C
   g++ -g -I/usr/local/include/cc++2 -L/usr/local/lib -o $@ $^ -lccgnu2
-lpthread -ldl

HelloClient: HelloClient.C
   g++ -g -I/usr/local/include/cc++2 -L/usr/local/lib -o $@ $^ -lccgnu2
-lpthread -ldl

HelloFrontEnd: HelloFrontEnd.o itso_gram_job.o itso_cb.o itso_gass_copy.o
itso_gass_server.o
   g++ -o $@ -I/usr/local/include/cc++2 -L/usr/local/lib $(GLOBUS_CPPFLAGS)
$(GLOBUS_LDFLAGS) $^ $(GLOBUS_PKG_LIBS) -lccgnu2 -lpthread -ldl

Then use make all to obtain the three executables.

9.3.5. Execution

In this publication example, the storage server is m0, which also acts as the front-end server. The source file for GNU Common C++ classes is stored in /tmp/commoncpp2-1.0.8.tar.gz on m0. t0 is the application server. You must generate a valid proxy with grid-proxy-init before running the test.

On m0, start the Hello front-end server:

[globus@m0 globus]$ ./HelloFrontEnd
we are listening on https://m0.itso-maya.com:20000
library compilation on t0
&(executable=https://m0.itso-maya.com:20000/home/globus/JYCode/Compile)
(count=1)
start app server on t0
&(executable=https://m0.itso-maya.com:20000/home/globus/JYCode/HelloServer)
(environment=(LD_LIBRARY_PATH $(HOME)/tmp/lib) ) (count=1)
(arguments=1804289383 t0)
Contact on the server https://t0.itso-tupi.com:57701/3673/1047501872/
Staging file in on: https://t0.itso-tupi.com:57701/3673/1047501872/
Job Finished on: https://t0.itso-tupi.com:57701/3673/1047501872/
binding for: m0.itso-maya.com:4096

You can now start the client from another node. You do not need to generate a valid proxy.

[john@a0 john]$ ./HelloClient m0
Ticket:1804289383
Hostname:t0
Hello World !

On m0, you should see the connection request. The connection is actually handled by the application server t0.

accepting from: m0.itso-maya.com:54642
creating session client object

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.137.38