locked
SOA meets HPC - an FAQ RRS feed

  • General discussion

  • Part 1

     

    1. What is SOA?

     

    SOA stands for Service Oriented Architecture.  Quoting from:

     

    http://msdn2.microsoft.com/en-us/architecture/aa948857.aspx

     

    The goal for a SOA is a world wide mesh of collaborating services, which are published and available for invocation on the Service Bus. Adopting SOA is essential to deliver the business agility and IT flexibility promised by Web Services. These benefits are delivered not by just viewing service architecture from a technology perspective and the adoption of Web Service protocols, but require the creation of a Service Oriented Environment that is based on the following key principals:

    • Service is the important concept. Web Services are the set of protocols by which Services can be published, discovered and used in a technology neutral, standard form.
    • SOA is not just an architecture of services seen from a technology perspective, but the policies, practices, and frameworks by which we ensure the right services are provided and consumed.
    • With SOA it is critical to implement processes that ensure that there are at least two different and separate processes—for provider and consumer.
    • Rather than leaving developers to discover individual services and put them into context, the Business Service Bus is instead their starting point that guides them to a coherent set that has been assembled for their domain.

    2. How does the SOA paradigm emerge?

     

    Taking from a Microsoft's  WCF intro deck:  

     

    "For years, software development has focused on how to best reuse the code that we write.  Ultimately, people and businesses want long-term return on their short-term investments in code.  How do we do this?
    We’ve seen 3 waves of advancement in this movement in recent decades:
    1980s and Object-Orientation:  Object-oriented development promised the idea of building reusable abstractions (called classes) that we could then inherit from in order to reuse the base class functionality.  This shift from simple procedural-based code brought with it a lot of benefits including polymorphism (the ability to dynamically bind types at runtime), abstractions that included both state and behavior, and encapsulation (controlling which parts of the code the external world can access).  However, Object-Orientation by itself didn’t facilitate the dynamic evolution of software at runtime.  Once an application was built, it was static.  There wasn’t an easy way to infuse new code into an application.
    1990s and Components:  Component-based development helped us overcome this challenge.  It forced the developer to think about the external facing interface of the application.  This enabled us to build systems that dynamically load and bind to new functionality at runtime (an application discovers new components after it has been built) and introduced the notion of an application as a growing/evolving organism.  To facilitate dynamic loading, we saw a big emphasis on runtime metadata.  In the past, you couldn’t easily discern application capabilities since there was very little/rudimentary metadata information stored as part of the application.  Whereas C and C++ programs from 1980s were these relatively opaque collections of code, component-based applications of the 1990s enabled runtime inspection of code to determine what a particular component supported. This introduced the notion of self-describing systems.  But while this metaphor worked really well on a single machine (using method invocation on an object reference), we hit scaling problems when we tried to stretch it out and apply it as the substrate for distributed software integration (across machines, etc).
    2000s and Service-Orientation – With Service-Orientation, we retain the benefits of self-describing applications, explicit encapsulation, and dynamic loading of functionality.  What changes is the metaphor with which we accomplish it.  Instead of using method invocation on an object reference, we shift the conversation to that of message passing – a proven metaphor for scalable distributed software integration.  In addition, to support dynamic loading of service-based functionality, we use schema to describes the structure of messages, behavioral contract to define acceptable message exchange patterns, and policy to define service semantics."
     
    3. What is WCF?
     

    Windows Communication Foundation (WCF) is Microsoft’s unified programming model for building service-oriented applications. It enables developers to build secure, reliable, transacted solutions that integrate across platforms and interoperate with existing investments.  For details on WCF, visit:

     

    http://msdn2.microsoft.com/en-us/library/ms735119.aspx

     

    4. What is SOA doing in HPC?

     

    With the increasing number and size of the problems being tackled on ever larger clusters, developers, users, and administrators are facing increasing challenges in meeting time-to-result goals. Applications must be quickly developed, run efficiently on the cluster, and be effectively managed so that application performance, reliability, and resource utilization are optimized.

     

    For Service-Oriented Architecture (SOA), Windows® HPC Server 2008 delivers a scalable, reliable, and secure interactive application platform. Using SOA, solution developers and architects can rapidly develop new cluster-enabled interactive applications and easily modify existing applications; the developer experience of build/debug/deploy is streamlined, the speed of processing is accelerated, and the management of the applications and systems is simplified in Windows HPC Server 2008.

     

    5. What specific HPC problems can I solve using SOA?

     

    High-performance computing applications submitted to compute clusters are typically classified as either message intensive or embarrassingly parallel. An embarrassingly parallel problem is one that can be easily divided into a very large number of parallel tasks, with no dependency or communication among those parallel tasks.

    To solve embarrassingly parallel problems without having to write the low-level code, developers need to encapsulate the core calculations as a software module. A Service-Oriented Architecture (SOA) programming model enables this encapsulation, and effectively hides the details for data serialization and distributed computing.

    Windows HPC Server includes support for embarrassingly parallel applications that use the SOA programming model; these applications use compute clusters interactively to provide near real-time calculation of complex algorithms. Table 1 shows some example applications and the related tasks.

    • Changed type Josh Barnard Thursday, March 26, 2009 12:39 AM
    Thursday, February 28, 2008 11:13 PM

All replies

  • Part 2

     

    6. What are the examples of these HPC SOA applications?

     

    Example Application

    Example Task

    Units of Work

    Monte Carlo problems that simulate the behavior of various mathematical or physical systems. Monte Carlo methods are used in physics, physical chemistry, economics, and related fields.

    Predicting the price of a financial instrument.

    The pricing of each security.

    BLAST searches.

    Gene matching.

    Individual matching of genes.

    Genetic algorithms.

    Evolutionary computational meta-heuristics.

    Computational steps.

    Ray Tracing.

    Computational physics and rendering.

    Each pixel to be rendered.

    Digital Content Creation.

    Rendering frames.

    Each frame to be rendered.

    Microsoft Office Excel add-in calculations.

    Calling add-in functions.

    Each add-in function call.

     

    Monte Carlo problems simulate the behavior of various mathematical or physical systems, and are used in physics, physical chemistry, economics, and related fields. The Monte Carlo method is a computational algorithm that relies on repeated random sampling. Because of the reliance on repeated computation and random or pseudo-random numbers, Monte Carlo methods are well suited for HPC. Monte Carlo methods tend to be used when it is infeasible or impossible to compute an exact result with a deterministic algorithm.

    The Monte Carlo method is widely used by financial analysts who want to construct stochastic or probabilistic financial models (as opposed to the traditional static and deterministic models). Many financial corporations use the Monte Carlo methods  for making investment decisions or valuing mergers and acquisitions; for example, financial corporations may need to formulate trading strategy against historical market data, complete risk analysis via Monte Carlo simulation in near real time, and price new derivative instruments.

    BLAST (Basic Local Alignment Search Tool) is a computer program that identifies homologous genes (genes in different species that share similar structures and functions) in different organisms. BLAST helps identify areas of homology. For example, there may be a gene in mice related to liking (or not liking) to consume alcohol; using BLAST, it is possible to check the human genome in search of a homologous gene. Because of the many iterations required, BLAST is well suited for SOA and HPC.

     

    7. What's so different of the SOA HPC offering from Windows HPC Server 2008?

     

    Benefits of Windows HPC Server 2008 for SOA Applications

    Tasks

    User Needs

    Windows HPC Server 2008 Features

    Build

    Solve embarrassingly parallel problems without having to write the low-level code.

    An integrated development environment (IDE) tool that lets developers develop, deploy, and debug applications on a cluster.

    A service-oriented programming model based on WCF that effectively hides the details for data serialization and distributed computing.

    Microsoft® Visual Studio® 2008 provides the tools to debug services and clients.

    Deploy

    Deploy line of business (LOB) applications easily and reliably.

    Windows HPC Server makes it possible for administrators to deploy services to multiple nodes from a single point of control.

    Run

    Shorter application runtimes.

    User applications must run securely.

    A system that decides where to run the tasks of the application and dynamically adjusts cluster resource allocation to the processing priorities of the workload.

    Low latency round-trip.

    Windows HPC Server provides end-to-end Kerberos with WCF transport-level security.

    Dynamic allocation of resources to the service instances.

    Manage

    Monitor application performance from a single point of control.

    Runtime monitoring of performance counters, including the number and status of outstanding service calls, and resource usage.

    Monitor and report service usage.

    Service resource usage reports.

     

    Thursday, February 28, 2008 11:19 PM
  • Part 3

     

    8. Can you give me a step-by-step guide on how to build an SOA HPC application using Windows HPC Server 2008? 

     

     Prerequisites for this example
    • Visual Studio 2005 or higher
    • Microsoft SDK 3.0
    • Microsoft Compute Cluster Pack v2 SDK


    Sample Code
    Sample code can be downloaded from:

    https://connect.microsoft.com/Downloads/DownloadDetails.aspx?SiteID=12&DownloadID=9490

     


    Three steps are required to create an SOA application:
    • Create the service
    • Deploy the service to a cluster
    • Create a Client

    Create a Service


    1. Launch Visual Studio 2005 and create a Class Library project. Name the project EchoService.
    2. In the VS 2005 Project Explorer pane, navigate to the EchoService project.
    3. Right-click References. An Add Reference dialog appears.
    4. In the Add Reference dialog, select the .NET tab.
    5. Select System.ServiceModel. This reference is required for writing the WCF Service code.
    a. If this reference is not listed on the .NET tab, then click the Browse tab.
    b. Locate and select the file System.ServiceModel.dll from %windir%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation.
    6. Click OK.


    7. In Solution Explorer, navigate to EchoService item, then rename the file Class1.cs to EchoService.cs.
    8. Open the file EchoService.cs then copy and paste the following code into it:


     

    Code Snippet

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Diagnostics;

    using System.ServiceModel;

     

    namespace EchoService

    {

        [ServiceContract]

        public interface IEchoService

        {

            [OperationContract]

            string Echo(string input);

        }

     

        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]

        public class EchoService : IEchoService

        {

            #region IEchoService Members

     

            public string Echo(string input)

            {

                return Environment.MachineName + ":" + input;

            }

           

    #endregion

        }

    }

     

     


    9. Compile the service to create EchoService.dll.  This file should reside in Visual Studio 2005\Projects\EchoService\EchoService\bin\[Debug|Release]\


    Deploy the Service DLL file to a compute cluster

    1. Copy the file EchoService.dll to the \Services folder on the local drive of all  compute nodes

    For Beta 1 users:

    2. You must register the service DLL on each node in the cluster. To register the service DLL, create a configuration file named EchoService.config that contains the following XML.

     

    Code Snippet
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <appSettings>
            <add key="assembly" value="c:\Services\EchoService.dll"/>
            <add key="type" value="EchoService.EchoService"/>
            <add key="contract" value="EchoService.IEchoService"/>
            </appSettings>
    </configuration>

     

     

     

    The statements contain elements that specify the type and contract key attributes. These elements are optional if the service defines only one interface. Otherwise, you must specify these elements for each interface that the service defines.
    Contract and type elements are optional if the assembly has only one type which implements a web service contract.
    3. After you define the configuration file, copy the file to %CCP_HOME%\ServiceRegistry on all compute nodes in the cluster.
    4. The element with the assembly key attribute specifies where the service DLL file is located on each compute node. Copy the service DLL to the specified path on all compute nodes in the cluster.

    For CTP users:

     

    To register the service DLL, create the following registry values under

    HKLM\Software\Microsoft\Hpc\ServiceRegistry\servicename.

     

    Name

    Description

    Type

    Required

    AssemblyPath

    The full path to the service DLL.

    REG_SZ

    Yes

    ContractType

    The interface of the service (WCF contract).

    REG_SZ

    No

    ServiceType

    The class that implements the WCF contract.

    REG_SZ

    No

     

    Each node in the cluster must contain the service DLL specified in the AssemblyPath value.

    The ContractType and ServiceType values are optional if the service defines only one interface; otherwise, you must specify these values for each interface that the service defines.

    The following table shows the registry values that you would provide for the example shown above.

    Name

    Data

    AssemblyPath

    c:\Services\EchoSvcLib.dll

    ContractType

    EchoSvcLib.EchoSvc

    ServiceType

    EchoSvcLib.IEchoSvc

    To specify the architecture on which your WCF service can run, specify the Architecture value under HKLM\Software\Microsoft\Hpc\ServiceRegistry\servicename to one of the following three data values:

    • AnyCpu (this is the default if not specified)
    • x86
    • x64

    To specify environment variables used by your service, specify the EnvVars key under HKLM\Software\Microsoft\Hpc\ServiceRegistry\servicename. Each value specified under the EnvVars key is a name/value pair.

    For example, to specify a Version environment variable, create a new value and set its name to Version, its type to REG_SZ, and its data to 2.0. The type for all environment variable values is REG_SZ.

     

    The client code will be in the next post (part 4)

     

    Thursday, February 28, 2008 11:27 PM
  • Part 4

     

    Create a Client


    In this phase, you will create the client proxy code from the Service.dll

    1. Navigate to the following folder:
    Visual Studio 2005\Projects\EchoService\EchoService\bin\[Debug|Release]\
    2. Run the command svcutil EchoService.dll. This command will generate the wsdl and xsd files for the service.
    3. Run the command svcutil *.wsdl *.xsd /async /language:C# /out:EchoClientProxy.cs.
    4. Launch Visual Studio and create a Console Application project and name it EchoClient.
    5. In the Solution Explorer, navigate to EchoClient and add a reference to the file storeapi.dll. That file is in C:\Program Files\Microsoft Compute Cluster Pack SDK\bin
    6. In the Solution Explorer/EchoClient pane, add a reference to System.ServiceModel. produced in step 5.
    7. Then add the file EchoClientProxy.cs to the client project.
    8. Right-click EchoClient, select Add, then Existing Item.  A Windows Explorer dialog is then displayed. 
    9. Browse to the folder where the file EchoClientProxy.cs is located and select it.
    10. Click OK.
    11. Add the following code to the file Program.cs:, then compile the client program and run it.

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ServiceModel;
    using System.Threading;
    using Microsoft.ComputeCluster.Scheduler.Session;

    namespace EchoClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                string scheduler = "localhost";
                string serviceName = "EchoService";

                if (args.Length > 0)
                {
                    scheduler = args[0];
                    if (args.Length > 1)
                    {
                        serviceName = args[1];
                    }
                }

                // Create a session object that specifies the head node
                // to which to connect
                //and the name of the WCF service to use.
                // This example uses the default start information for a
                // session.
                SessionStartInfo info = new SessionStartInfo(scheduler, serviceName);
                info.ResourceUnitType = Microsoft.ComputeCluster.Scheduler.JobUnitType.Node;
                info.MinimumUnits = 1;
                info.MaximumUnits = 4;
              
                Console.WriteLine("Creating a session...");
                // Create the session by calling the factory method
                using (Session session = Session.CreateSession(info))
                {
                    Console.WriteLine("Session's Endpoint Reference:{0}", session.EndpointReference.ToString());
                   
                    // Binds session to the client proxy using NetTcp
                    // binding (specify only NetTcp binding). The
                    // security mode must be Transport and you cannot
                    // enable reliable sessions.
                    EchoServiceClient client = new EchoServiceClient(new NetTcpBinding(SecurityMode.Transport, false), session.EndpointReference);

                    AsyncResultCount = 100;

                    for (int i = 0; i < 100; i++)
                    // EchoCallBack is defined in EchoClientProxy.cs.
                    {
                        // This call will not block,
                       // as results becomes available
                       // the EchoCallBack method will be invoked
                        client.BeginEcho("hello world", EchoCallback, new RequestState(client, i));
                    }
                    AsyncResultsDone.WaitOne();

                    client.Close();
                    Console.WriteLine("Please enter any key to continue...");
                    Console.ReadLine();
                }
            }

            static int AsyncResultCount = 0;
            static AutoResetEvent AsyncResultsDone = new AutoResetEvent(false);

            // Encapsulates the context of the function callback
            class RequestState
            {
                int input;
                EchoServiceClient client;

                public RequestState(EchoServiceClient client, int input)
                {
                    this.client = client;
                    this.input = input;
                }

                public int Input
                {
                    get { return input; }
                }

                public string GetResult(IAsyncResult result)
                {
                    return client.EndEcho(result);
                }
            }

            static void EchoCallback(IAsyncResult result)
            {
                RequestState state = result.AsyncState as RequestState;

                Console.WriteLine("Response({0}) = {1}", state.Input, state.GetResult(result));


                if (Interlocked.Decrement(ref AsyncResultCount) <= 0)
                {
                    AsyncResultsDone.Set();
                }
            }
        }
    }

     

     

    Thursday, February 28, 2008 11:29 PM
  • Part 5

     

    9. I'm using Job Manager's parametric sweep builder UI, why would I switch to SOA?

     

    The parametric sweep builder UI is designed to allow end-users to create a parametric sweep application using the off-the-shelf or existing in-house applications that are usually invoked from command-line or scripts.  However, for new application development, the picture is quite different. 

     

    My colleague Stevan Vidch said it well:

     

    "In industries where there is a lot more emphasis on custom application development such as Capital Markets, than in   say, engineering, when designing an aircraft wing or estimating structural deformations for a large building, everyone uses the very similar ISV software.  The input data are different, but the algorithms are all implemented by third party ISVs, and they are all very similar because they are based on the exact same or similar theory.  When solving structural problems using the Finite Element Method, you will get the same results (or very close) provided that the input parameters (geometry, material characteristics, etc.) are all the same.  In Capital Markets, one firm would never use the same algorithms for derivatives pricing as another firm; there would be no differentiation.  Therefore, much of the computing is proprietary and differentiated.

     

    LOB (Line of Business) application developers are used to building their apps in Visual Studio using .NET Framework.  With CCS version 1.0, they need to make a mental shift and adopt a completely new approach to building applications.  They need to segment the application and isolate all computationally intensive logic that needs to be built into a standalone, command-line executable that does not require human intervention.  Then they deploy that executable to all compute nodes in the cluster.  They build the rest of the application using the UI of their choice but keeping in mind how the app must interact with the job scheduler.  This trusted old approach has worked well for HPC developers in other industries for the past 15 years.  However, this is simply not how LOB applications are built today on Wall Street.  As a matter of fact, if you run into a .NET object oriented purist, the first thing he will tell you is “Why do I have to worry about the plumbing”.

     

    This is precisely what the SOA model provides.  In the best tradition of object oriented programming and with full fidelity of .NET Framework, developers build their solutions not thinking at all how to run them on the cluster.  Visual Studio developers need to change nothing in their established software development methodology.  By way of creating proxies off of a well-established interface, newly built client program can distribute calculations by calling methods on the proxy objects.  The distribution of service calls and serialization of parameters used in therein are all handled by the WCF framework and Windows HPC Server 2008.  As such,  the programmer is only dealing with farmilar language constructst such as serial loops and objects, resulting in significant productivity gains.

     

    There is also a performance benefits associated with the SOA approach.  Unlike the job / task parametric sweep model where each task is launched and torn down per calculation request, the services are long running processes that are launched once and used many times.  For sub-second calculation, the overhead of launching and tearing down the task processes especially for applications with long start-up time will quickly lead to diminishing returns on distributed processing.  SOA delivers a platform that can help accerating applications with sub-second work units without requiring the application developers to do the gymnastic of batching up the requests. 

     

     

     

    Friday, February 29, 2008 9:06 PM
  • Part 6

     

    9. How to recover from the Broker Node Failure?

     

     

     

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Hpc.Scheduler.Session;
    using LongRunningSvcClient.ServiceReference1;
    using System.ServiceModel;
    using System.Threading;
    using System.Diagnostics;
    using Microsoft.Hpc.Scheduler;

    namespace LongRunningSvcClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                EndpointAddress epr = null;
                bool createSession = true;
                int numServiceInstances = 1;

                if (args.Length > 0)
                {
                    numServiceInstances = int.Parse(args[0]);
                }
               
                
                Queue<int> unfulfilled = new Queue<int>();

                for (int i = 0; i < 10000; i++)
                {
                    unfulfilled.Enqueue(i);
                }


                //
                // Loop until all the service calls are completed
                //
                ManualResetEvent finishedEvt = new ManualResetEvent(false);
                for (;;)
                {
                    int cnt = unfulfilled.Count;
                    finishedEvt.Reset();
                    Session session = null;

                    if (createSession == true)
                    {
                        Console.WriteLine("Creating session...");
                        session = CreateSession(numServiceInstances);

                        if (session == null)
                            return;

                        epr = session.EndpointReference;
                        createSession = false;
                    }
                   
                    // Create Client Proxy
                    Service1Client client = new Service1Client(
                                                        new NetTcpBinding(SecurityMode.Transport, false),
                                                        epr);

                    client.InnerChannel.OperationTimeout = new TimeSpan(1, 0, 0, 0);

                    Console.WriteLine("Proxy created EndpointReference = {0}", epr.ToString());
                    bool brokerConnectionBroken = false;

                    while (unfulfilled.Count != 0)
                    {
                        int n = unfulfilled.Dequeue();

                        try
                        {
                            client.BeginSquare(
                                    n, delegate(IAsyncResult result)
                            {
                                try
                                {
                                    int reply = client.EndSquare(result);
                                    Console.WriteLine("Square({0})={1}", result.AsyncState, reply);
                                }
                                catch (CommunicationException)
                                {
                                    unfulfilled.Enqueue((int)result.AsyncState);
                                    brokerConnectionBroken = true;
                                }
                                catch (TimeoutException)
                                {
                                    unfulfilled.Enqueue((int)result.AsyncState);
                                }

                                Interlocked.Decrement(ref cnt);
                                if (cnt == 0)
                                {
                                    finishedEvt.Set();
                                }
                            },
                            n);  // callback context

                        }
                        catch (CommunicationException)
                        {
                            brokerConnectionBroken = true;
                            finishedEvt.Set();
                            break;
                        }
                    }
                    finishedEvt.WaitOne();

                    if (unfulfilled.Count == 0)
                        break;

                    if (brokerConnectionBroken == true)
                    {
                        session.Dispose();
                        createSession = true;
                    }
                }
             
                Console.WriteLine("Please enter any key to continue...");
                Console.ReadLine();

            }

            static Session CreateSession(int numServiceInstances)
            {
                SessionStartInfo startInfo = new SessionStartInfo("r25-1183d1002",
                                                                  "SquareService1_0");

                #region resource requirements
                startInfo.ResourceUnitType = Microsoft.Hpc.Scheduler.Properties.JobUnitType.Core;
                startInfo.MinimumUnits = 1;
                startInfo.MaximumUnits = numServiceInstances;
                startInfo.Priority = Microsoft.Hpc.Scheduler.Properties.JobPriority.AboveNormal;
                #endregion

                Session session = null;

                try
                {
                   session = Session.CreateSession(startInfo);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    if (ex.InnerException != null)
                        Console.WriteLine(ex.InnerException.Message);

                    return null;
                }

                return session;
            }
        }
    }

     

     


    Friday, February 29, 2008 9:06 PM
  •  

    Friday, February 29, 2008 9:06 PM
  •  

    Part 6

     

    9. How does the Client recover from Broker node failure?

     

    The following program demonstrates how the client can recover from the Broker failure.  When broker nodes dies, the client will receive a CommunicationException.   The client uses a Queue "unfulfilled" to keep track of the outstanding requests.  When the communication breaks, WCF will throw as many CommunicationExceptions as there are fired and yet unfinished requests.  The client program requeue these requests, re-create session and resume processing.  

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Hpc.Scheduler.Session;
    using LongRunningSvcClient.ServiceReference1;
    using System.ServiceModel;
    using System.Threading;
    using System.Diagnostics;
    using Microsoft.Hpc.Scheduler;

    namespace LongRunningSvcClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                EndpointAddress epr = null;
                bool createSession = true;
                int numServiceInstances = 1;

                if (args.Length > 0)
                {
                    numServiceInstances = int.Parse(args[0]);
                }
               
                
                Queue<int> unfulfilled = new Queue<int>();

                for (int i = 0; i < 10000; i++)
                {
                    unfulfilled.Enqueue(i);
                }


                //
                // Loop until all the service calls are completed
                //
                ManualResetEvent finishedEvt = new ManualResetEvent(false);
                for (;Wink
                {
                    int cnt = unfulfilled.Count;
                    finishedEvt.Reset();
                    Session session = null;

                    if (createSession == true)
                    {
                        Console.WriteLine("Creating session...");
                        session = CreateSession(numServiceInstances);

                        if (session == null)
                            return;

                        epr = session.EndpointReference;
                        createSession = false;
                    }
                   
                    // Create Client Proxy
                    Service1Client client = new Service1Client(
                                                        new NetTcpBinding(SecurityMode.Transport, false),
                                                        epr);

                    client.InnerChannel.OperationTimeout = new TimeSpan(1, 0, 0, 0);

                    Console.WriteLine("Proxy created EndpointReference = {0}", epr.ToString());
                    bool brokerConnectionBroken = false;

                    while (unfulfilled.Count != 0)
                    {
                        int n = unfulfilled.Dequeue();

                        try
                        {
                            client.BeginSquare(
                                    n, delegate(IAsyncResult result)
                            {
                                try
                                {
                                    int reply = client.EndSquare(result);
                                    Console.WriteLine("Square({0})={1}", result.AsyncState, reply);
                                }
                                catch (CommunicationException)
                                {
                                    unfulfilled.Enqueue((int)result.AsyncState);
                                    brokerConnectionBroken = true;
                                }
                                catch (TimeoutException)
                                {
                                    unfulfilled.Enqueue((int)result.AsyncState);
                                }

                                Interlocked.Decrement(ref cnt);
                                if (cnt == 0)
                                {
                                    finishedEvt.Set();
                                }
                            },
                            n);  // callback context

                        }
                        catch (CommunicationException)
                        {
                            brokerConnectionBroken = true;
                            finishedEvt.Set();
                            break;
                        }
                    }
                    finishedEvt.WaitOne();

                    if (unfulfilled.Count == 0)
                        break;

                    if (brokerConnectionBroken == true)
                    {
                        session.Dispose();
                        createSession = true;
                    }
                }
             
                Console.WriteLine("Please enter any key to continue...");
                Console.ReadLine();

            }

            static Session CreateSession(int numServiceInstances)
            {
                SessionStartInfo startInfo = new SessionStartInfo("r25-1183d1002",
                                                                  "SquareService1_0");

                #region resource requirements
                startInfo.ResourceUnitType = Microsoft.Hpc.Scheduler.Properties.JobUnitType.Core;
                startInfo.MinimumUnits = 1;
                startInfo.MaximumUnits = numServiceInstances;
                startInfo.Priority = Microsoft.Hpc.Scheduler.Properties.JobPriority.AboveNormal;
                #endregion

                Session session = null;

                try
                {
                   session = Session.CreateSession(startInfo);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    if (ex.InnerException != null)
                        Console.WriteLine(ex.InnerException.Message);

                    return null;
                }

                return session;
            }
        }
    }

    Saturday, March 22, 2008 12:06 AM
  • Part 7  F# client for the WCF Broker

     

    The following code shows a F# client.  

     

    Code Snippet

    #light

     

    #I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\"

    #r "System.ServiceModel.dll"

     

    // Use svcutil to create a ClientProxy.cs

    // then compile the ClientProxy.cs into DLL "ClientProxy.dll"

    // Load the client proxy DLL

    #r "ClientProxy.dll"

     

    open System

    open SampleService1

    open System.ServiceModel

     

    #I @"C:\Program Files\Microsoft HPC Pack 2008 SDK\Bin\"

    #r "Microsoft.Hpc.Scheduler.dll"

    #r "Microsoft.Hpc.Scheduler.Properties.dll"

    #r "Microsoft.Hpc.Scheduler.Session.dll"

    open Microsoft.Hpc.Scheduler.Session

    open Microsoft.FSharp.Control

    open Microsoft.FSharp.Control.CommonExtensions

                     

    let startInfo = new SessionStartInfo("r25-1183ahn02", "SampleService1")

    startInfo.MinimumUnits <- 1

    startInfo.MaximumUnits <- 4

     

    let session = Session.CreateSession(startInfo)

     

    Console.WriteLine("Session's Endpoint Reference:{0}", session.EndpointReference.ToString())

     

    let clientCluster  = new Service1Client(new NetTcpBinding(SecurityMode.Transport, false), session.EndpointReference)         

     

    // This is similar to the Async approach.  But it is very hard to write

    // for n in [1..100] do

    //    clientCluster.BeginGetData(n, (fun handle -> Console.WriteLine("From Cluster: {0}", clientCluster.EndGetData(handle))), n)

     

    // Look how easy it is to write async invocation using the asynchronous workflow

    // How ever one needs to know that blocking remote calls may clog the thread pool if

    // there are some long running calls, rendering additional service instances idle

    let tasks = [ for i in 1..100 -> async { return clientCluster.GetData(i) } ]

     

    // Run those tasks in parallel

    let results = Async.Run(Async.Parallel tasks)

     

    // print the results

    for result in results do

          Console.WriteLine("{0}", result)

     

    Console.ReadLine()

     

     

    Sunday, April 13, 2008 5:52 AM