Orleans 初接触 入门例子

Posted 爱上猫的红烧鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Orleans 初接触 入门例子相关的知识,希望对你有一定的参考价值。

 【返回导航

  在简单了解了Orleans 之后我们可以通过几个例子去加深印象

一、Orleans入门例子

  这个例子是跟着《Orleans入门例子》(https://www.cnblogs.com/gaopang/articles/7379802.html

  1.创建

  首先创建一个四个项目的解决方案,如图所示

  

  四个项目分别是:

  1. Client:这个显而易见,里面就是要运行GrainClient的。它要和Host通信,这就要求它引用IGrains项目。这是个控制台项目
  2. Host:这个也是显而易见,里面就是要运行Silo的。它应该引用Grains项目以及IGrains项目,因为它要承载Grain(这就要求引用Grains类),并且需要Grain实例间的通信(这就要求引用IGrains项目),这是个控制台项目
  3. Grains:这个里面实现所有IGrain载明的接口,实现所有的Grain类,包括它们的方法以及字段。(它要求引用IGrain。。。废话)这是个类库项目
  4. IGrains:这里放置所有Grains类要扩展的接口。这是个类库项目。

  然后使用NuGet引用Microsoft.Orleans.Server

  

  接着使用NuGet引用Microsoft.Orleans.Client

  

  2.编码

  IGrains.IBasic

  public interface IBasic : IGrainWithIntegerKey
    {
        Task<string> SayHello(string hellostr);
    }

  Grains.BasicGrain

  public class BasicGrain : Grain, IGrains.IBasic
    {
        public Task<string> SayHello(string hellostr)
        {
            Console.WriteLine("{0} : {1}", DateTime.Now.ToString("HH:mm:ss.fff"), hellostr);
            return Task.FromResult<string>("done");
        }
    }

  Host.Program

  class Program
    {
        static void Main(string[] args)
        {
            //获得一个配置实例
            //他需要两个端口,第一个端口2334是用来silo与silo之间的通信的,第二个1234是用于监听client的请求的
            var config = Orleans.Runtime.Configuration.ClusterConfiguration.LocalhostPrimarySilo(2234, 1234);
            //初始化一个silohost,这里使用了Orleans提供的silohost而不是silo,其中silo的名字命名为Ba;
            SiloHost siloHost = new SiloHost("Ba", config);
            //初始化仓储
            siloHost.InitializeOrleansSilo();
            //启动
            siloHost.StartOrleansSilo();

            //检查一下
            if (siloHost.IsStarted)
            {
                Console.WriteLine("silohost 启动成功");
            }
            else
            {
                Console.WriteLine("启动失败");
            }
            Console.ReadKey();
        }
    }

  

    class Program
    {
        static void Main(string[] args)
        {
            //等待服务端启动完毕
            Console.ReadKey();
            //然后我聪明的敲击了回车键
            Run();
            Console.ReadKey();
        }

        static async void Run()
        {
            //利用内置方法获得一个配置类,这个类指明服务端的端口是1234
            //可以利用配置文件,不过这里我就先用这个简单的配置类
            var config = Orleans.Runtime.Configuration.ClientConfiguration.LocalhostSilo(1234);

            //初始化一个GrainClient
            GrainClient.Initialize(config);

            //从silo处,获得了一个BasicGrain的接口
            IGrains.IBasic agrain = GrainClient.GrainFactory.GetGrain<IGrains.IBasic>(314);

            //调用里面的方法,等待它返回
            string result = await agrain.SayHello("还好");
            Console.WriteLine(result);
        }
    }

  3.运行

  但是在运行Client的时候导致了一个问题

  

  还不知道怎么解决,就卡在这里了。

  后续解决:

    在博客园获得了博主大大的提示,仔细检查之后,发现原来是我的host项目没有引用引用Grains项目以及IGrains项目。在引用之后,整个项目就能完整的运行下来了。

 

二、快速入门示例

   这个例子是跟着《Microsoft Orleans 之 入门指南》(https://www.cnblogs.com/endv/p/6147976.html)中的快速入门示例做的

  1.创建

  同样,是先创建一个四个项目的解决方案,这里把它命名为OrleansSamples

  

  项目的结构和上一个例子一样,同样是引用Microsoft.Orleans.Server(服务端包)和Microsoft.Orleans.Client(客户端包)

  不一样的是这个例子使用了和上一个例子不一样的接口

  2.编码

  IUserService

    public interface IUserService : IGrainWithIntegerKey
    {
        Task<bool> Exist(string mobileNumber);
    }

  UserService

    public class UserService : Grain, IUserService
    {
        public Task<bool> Exist(string mobileNumber)
        {
            return Task.FromResult<bool>(mobileNumber == "15665699774");
        }
    }

  Server

    class Program
    {
        static void Main(string[] args)
        {
            using (var host = new SiloHost("Default"))
            {
                host.InitializeOrleansSilo();
                host.StartOrleansSilo();
                Console.WriteLine("启动成功!");
                Console.ReadLine();
                host.StopOrleansSilo();
            }
        }
    }

  Client

    class Program
    {
        static void Main(string[] args)
        {
            System.Threading.Thread.Sleep(15000);
            GrainClient.Initialize();

            while (true)
            {
                Console.WriteLine("请输入用户手机号:");
                var mobileNumber = Console.ReadLine();
                //这里由于我们采用的grain继承的是IGrainWithIntegerKey ,所以我们采用调用数值类型的key=10来创建这个grain,
                //可能有人会问key是干嘛的,他是唯一标识这个grain的,当你指定一个key的时候,Orleans 会创建一个,它首先到
                //你的存储介质中找(如果你配置了的话,默认采用内存存储,这种方式适合开发期,生产环境需要保持状态的,所以需要配置到能持久化存储的地方去,比如sqlserver等)
                //如果找到了就直接返回,如果没找到就根据你指定的这个key然后创建一个,这个就是grain的激活,具体详细的,可以看官方问的关于Grain一章。
                var userService = GrainClient.GrainFactory.GetGrain<IUserService>(10);
                //C#的一种新的表达式语法,这样就方便多了,省的我们拼接字符串。
                Console.WriteLine($"用户{mobileNumber},{(userService.Exist(mobileNumber).Result ? "已经存在" : "不存在")}");
            }

        }
    }

  3.运行

  想要将这个Orleans 运行起来,还需要做件事

  在Server目录下添加OrleansConfiguration.xml

<?xml version="1.0" encoding="utf-8" ?>
<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <StorageProviders>
      <Provider Type="Orleans.Storage.MemoryStorage" Name="MemoryStore" />
      <Provider Type="Orleans.Storage.MemoryStorage" Name="Default" />
      <!--<Provider Type="Orleans.Storage.AzureTableStorage" Name="AzureStore"/>-->
    </StorageProviders>
    <SeedNode Address="localhost" Port="22222"/>
    <Messaging ResponseTimeout="30s"/>
  </Globals>
  <Defaults>
    <Networking Address="localhost" Port="22222"/>
    <ProxyingGateway Address="localhost" Port="40000" />
    <Tracing DefaultTraceLevel="Info" TraceToConsole="true" TraceToFile="{0}-{1}.log" PropagateActivityId="false" BulkMessageLimit="1000">
      <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" />
      <!--
<TraceLevelOverride LogPrefix="Runtime.Dispatcher" TraceLevel="Verbose" />
<TraceLevelOverride LogPrefix="AssemblyLoader.Silo" TraceLevel="Warning" />
-->
    </Tracing>
    <Statistics MetricsTableWriteInterval="30s" PerfCounterWriteInterval="30s" LogWriteInterval="300s" WriteLogStatisticsToTable="true" StatisticsCollectionLevel="Info"/>
  </Defaults>
</OrleansConfiguration>

  在Client目录下添加ClientConfiguration.xml

<?xml version="1.0" encoding="utf-8" ?>
<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="localhost" Port="40000"/>
  <!-- To turn tracing off, set DefaultTraceLevel="Off" and have no overrides.
    For the trace log file name, {0} is replaced by "Client" and {1} is the current time. -->
  <Tracing DefaultTraceLevel="Info" TraceToConsole="false" TraceToFile="{0}-{1}.log" BulkMessageLimit="1000">
    <TraceLevelOverride LogPrefix="Runtime" TraceLevel="Info" />
    <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" />
    <TraceLevelOverride LogPrefix="AssemblyLoader" TraceLevel="Warning" />
  </Tracing>
  <Statistics MetricsTableWriteInterval="300s" PerfCounterWriteInterval="30s" LogWriteInterval="300s" WriteLogStatisticsToTable="true" StatisticsCollectionLevel="Info"/>
  <Messaging ResponseTimeout="30s" ClientSenderBuckets="8192" MaxResendCount="0"/>
</ClientConfiguration>

  并且对这两个xml文件设置属性-高级-复制到输出目录-如果较新则复制

  将Server(服务端)和Client(客户端)分别运行后,即可得到效果

  

  至此一个简单的单服务的Orleans就已经完成了,从这个例子里能简单的理解一下Orleans。但是究竟一个分布式的集群服务器应该怎么搭建,还是毫无头绪,然我们继续学习西区

 

以上是关于Orleans 初接触 入门例子的主要内容,如果未能解决你的问题,请参考以下文章

Orleans的入门教程

Orleans学习总结

Orleans MultiClient 多个Silo复合客户端

Orleans学习总结--创建工程

Learn Orleans 03 - 无锁

有状态 Vs 无状态