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(key)方法(T目标Grain接口在哪里来获取Grain引用细微的区别在于我们调用的工厂对象GetGrain在客户端代码中,我们通过连接的客户端对象来实现。

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

对一个Grain方法的调用返回一个Task或一个Task按照粮食接口规则的要求客户端可以使用await关键字异步等待返回Task而不阻塞线程,或者在某些情况下Wait()阻止当前执行线程方法。

Grain从客户端代码和另一个客户端代码进行调用的主要区别在于Grain单线程执行模型Grain谷物被Orleans运行时限制为单线程,而客户端可能是多线程的。 Orleans在客户端没有提供任何这样的保证,因此使用任何适合其环境的同步构造 - 锁,事件Tasks,由客户来管理自己的并发

接收通知

有些情况下,简单的请求 - 响应模式不够,客户端需要接收异步通知。例如,用户可能希望在她正在关注的某人发布新消息时收到通知。

观察者就是这样一种机制,可以使客户端对象暴露在类似于Grain目标的对象中以被调用Grain呼叫观察员不会提供成功或失败的任何指示,因为它们是作为单向最佳努力消息发送的。因此,必要时,应用程序代码负责在观察者之上构建更高级别的可靠性机制。

另一种可用于向客户端传递异步消息的机制是Orleans-Streams / index.html“> Streams。Streams揭示单个消息传递成功或失败的迹象,并因此启用可靠的通信回到客户端。

例子

下面是一个客户端应用程序的示例的扩展版本,该应用程序连接到Orleans,查找玩家帐户,订阅游戏会话的更新(玩家是观察者的一部分),并打印出通知,直到程序手动终止。

namespace PlayerWatcher
{
    class Program
    {
        /// 
        /// 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.
        /// 
        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(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(watcher));

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

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

下一个

运行应用程序

你可能感兴趣的:(orleans)