1. 程式人生 > >Orlens入門概念(3)客戶端

Orlens入門概念(3)客戶端

什麼是Grain客戶端?

術語“客戶”或有時“GrainClient”用於與其互動Grain但本身不是Grain邏輯的一部分的應用程式程式碼客戶端程式碼在Orleans稱為託管Silo位置伺服器叢集之外執行Grain因此,客戶端充當叢集和所有Grain應用程式的聯結器或通道

通常,客戶端用於前端Web伺服器以連線到Orleans作為Grain執行業務邏輯的中間層叢集在典型的設定中,前端Web伺服器:

  • 接收網路請求
  • 執行必要的認證和授權驗證
  • 決定哪些穀物應該處理請求
  • 使用Grain Client對穀物進行一次或多次方法呼叫
  • 處理穀物呼叫和任何返回值的成功完成或失敗
  • 傳送網路請求的響應

Grain Client的初始化

Grain客戶端可用於呼叫Grain託管在Orleans叢集中之前,需要對客戶端進行配置,初始化並連線到叢集。

通過一個ClientConfiguration物件提供配置,該物件包含用於以程式設計方式配置客戶端的配置屬性層次結構。還有一種通過XML檔案配置客戶端的方法,但該選項將來會被棄用。更多資訊在客戶端配置指南中在這裡,我們將簡單地使用一個助手方法來建立一個硬編碼的配置物件,用於連線到本地Silo執行localhost

ClientConfiguration clientConfig = ClientConfiguration.LocalhostSilo(); 

一旦我們有了一個配置物件,我們就可以通過這個

ClientBuilder建立一個客戶端

IClusterClient client = new ClientBuilder().UseConfiguration(clientConfig).Build();

最後,我們需要呼叫Connect()構造的客戶端物件上的方法,使其連線到Orleans叢集。這是一個返回a的非同步方法Task所以我們需要等一個awaitor 完成它.Wait()

await client.Connect(); 

呼叫Grain

從客戶端呼叫Grain方法沒啥特殊的地方,從內作出這樣的呼叫Grain程式碼在這兩種情況下使用同樣的GetGrain<T>(key)

方法(T目標Grain介面在哪裡來獲取Grain引用細微的區別在於我們呼叫的工廠物件GetGrain在客戶端程式碼中,我們通過連線的客戶端物件來實現。

IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Task t = player.JoinGame(game)
await t;

對一個Grain方法的呼叫返回一個Task或一個Task<T>按照糧食介面規則的要求客戶端可以使用await關鍵字非同步等待返回Task而不阻塞執行緒,或者在某些情況下Wait()阻止當前執行執行緒方法。

Grain從客戶端程式碼和另一個客戶端程式碼進行呼叫的主要區別在於Grain單執行緒執行模型Grain穀物被Orleans執行時限制為單執行緒,而客戶端可能是多執行緒的。 Orleans在客戶端沒有提供任何這樣的保證,因此使用任何適合其環境的同步構造 - 鎖,事件Tasks,由客戶來管理自己的併發

接收通知

有些情況下,簡單的請求 - 響應模式不夠,客戶端需要接收非同步通知。例如,使用者可能希望在她正在關注的某人釋出新訊息時收到通知。

觀察者就是這樣一種機制,可以使客戶端物件暴露在類似於Grain目標的物件中以被呼叫Grain呼叫觀察員不會提供成功或失敗的任何指示,因為它們是作為單向最佳努力訊息傳送的。因此,必要時,應用程式程式碼負責在觀察者之上構建更高級別的可靠性機制。

另一種可用於向客戶端傳遞非同步訊息的機制是<a href="http://dotnet.github.io/orleans/Documentation/%3Ccode%20class=" defaulcode"="" style="background-color: transparent; color: rgb(51, 122, 183); cursor: pointer;">Orleans-Streams / index.html“> Streams。Streams揭示單個訊息傳遞成功或失敗的跡象,並因此啟用可靠的通訊回到客戶端。

例子

下面是一個客戶端應用程式的示例的擴充套件版本,該應用程式連線到Orleans,查詢玩家帳戶,訂閱遊戲會話的更新(玩家是觀察者的一部分),並打印出通知,直到程式手動終止。

namespace PlayerWatcher
{
    class Program
    {
        /// <summary>
        /// Simulates a companion application that connects to the game
        /// that a particular player is currently part of, and subscribes
        /// to receive live notifications about its progress.
        /// </summary>
        static void Main(string[] args)
        {
            RunWatcher().Wait();
            // Block main thread so that the process doesn't exit.
            // Updates arrive on thread pool threads.
            Console.ReadLine();
        }

        static async Task RunWatcher()
        {
            try

            {
                // Connect to local silo
                var config = ClientConfiguration.LocalhostSilo();
                var client = new ClientBuilder().UseConfiguration(config).Build();
                await client.Connect();

                // Hardcoded player ID
                Guid playerId = new Guid("{2349992C-860A-4EDA-9590-000000000006}");
                IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
                IGameGrain game = null;

                while (game == null)
                {
                    Console.WriteLine("Getting current game for player {0}...", playerId);

                    try
                    {
                        game = await player.GetCurrentGame();
                        if (game == null) // Wait until the player joins a game
                        {
                            await Task.Delay(5000);
                        }
                    }
                    catch (Exception exc)
                    {
                        Console.WriteLine("Exception: ", exc.GetBaseException());
                    }
                }

                Console.WriteLine("Subscribing to updates for game {0}...", game.GetPrimaryKey());

                // Subscribe for updates
                var watcher = new GameObserver();
                await game.SubscribeForGameUpdates(
                    await client.CreateObjectReference<IGameObserver>(watcher));

                Console.WriteLine("Subscribed successfully. Press <Enter> to stop.");
            }
            catch (Exception exc)
            {
                Console.WriteLine("Unexpected Error: {0}", exc.GetBaseException());
            }
        }
    }

    /// <summary>
    /// Observer class that implements the observer interface. Need to pass a grain reference to an instance of this class to subscribe for updates.
    /// </summary>
    class GameObserver : IGameObserver
    {
        // Receive updates
        public void UpdateGameScore(string score)
        {
            Console.WriteLine("New game score: {0}", score);
        }
    }
    }
}

下一個