接触Orleans 有一段时间了,之前也翻译了一系列官网文档,今天我们就来一个实际的例子,来看看到底如何用这个东西来开发项目,当然经典的也是醉人的,我们就从HelloWorld开始吧。

通过前面的知识准备我们知道Orleans 项目需要n个服务端(就是silohost),n个客户端(就是调用方),然后就是提供的actors(在Orleans 中成为grain),废话少说。

首先建立一个解决方案,叫做OrleansSamples

然后,增加一个模块解决方案,叫做HelloWorlds,在解决方案下增加两个类库Sample.Interfaces,Sample.Implements,其中Sample.Implements引用Sample.Interfaces,

这两个项目中引用Orleans的核心库,你可以手动一个一个引用进来,但还是老老实实的用nuget吧。

nuget的引用两种方式一种,通过图形化的方式,另一种通过命令的方式,命令:Install-Package Microsoft.Orleans.Core (注:在这里可以找到所需的包http://dotnet.github.io/orleans/NuGets)

记得引用完后如果在nuget里有更新就更新一下,对于新版本,可能里面有些库会没有进来,否则就会报错,反正我是这么做,做完这一切,项目结构如下:

在Sample.Interfaces中增加一个接口IUserService,并且继承接口IGrainWithIntegerKey(关于这个接口有姊妹接口,关于这些接口后续会陆续讲到)

代码如下:

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

在Sample.Implements项目中增加实现类UserService,并且继承Grain(Grain这个基类同时也提供了相应的泛型实现Grain<>,关于他们的不同点,以及功能,后续会讲到),且实现IUserService接口

代码如下:

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

好了到此为止,我们已经开发好actor虽然简单,接下来我们接着增加服务启动寄宿项(关于寄宿项,可以是控制台、windows服务、winfrom、asp.net ),这里我们采用控制台,下面我们创建一个服务控制台应用程序(Server)

引用上面创建两个项目:Sample.Implements、Sample.Interfaces。(注:其实这两个项目不一定要引用进来,只要在生成项目的目录下存在他们的编译好的dll即可,silo用来自动加载启动这个他们)

引用orleans项目中服务端的类库(使用nuget命令:Install-Package Microsoft.Orleans.Server

项目结构如下:

代码如下:

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

好一切准备就绪,我们F5吧,

当你看到这得时候是不是觉得成功了,真的成功了吗,不一定吧!

哦对了怎么没看到日志呢,好我们在项目目录下看看日志:

果然有日志文件,一看文件名称,直接告诉我们发生错误了,好让我们打开看看吧。

从发生的异常看出,好像少了一个配置文件,在orleans 服务启动时,需要一个配置文件,这个配置文件可以是OrleansConfiguration.xml或者orleans.config或者orleans.config.xml

好知道原因了,知道该怎么做了吧,在server根目录下创建一个xml文件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="false" 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>

再次启动F5,当看到启动成功的输出时,我们再次看看生成的日志:

这次发现比之前生成的东西多了,但是当我们继续往下浏览的时候发现有个异常:

Exc level 0: System.IO.FileNotFoundException: 未能加载文件或程序集“Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60”或它的某一个依赖项。系统找不到指定的文件。
在 Orleans.Runtime.Startup.ConfigureStartupBuilder.ConfigureStartup(String startupTypeName)
在 Orleans.Runtime.Startup.ConfigureStartupBuilder.Orleans.Runtime.Startup.IStartupBuilder.ConfigureStartup(String startupTypeName)
在 Orleans.Runtime.Silo..ctor(String name, SiloType siloType, ClusterConfiguration config, ILocalDataStore keyStore)

原来是少了程序集:Microsoft.Extensions.DependencyInjection

知道原因了,我们通过nuget来引用这个类库,引用成功,再次运行,然后查看日志,异常消失,但是有个问题,每次打开日志文件要看,是否有错误,或者一些关于服务的监控内容,这样是不是很麻烦,其实我们可以更改一下配置信息,让它输出到控制台,这样在开发过程中就方便多了,可以时时看到动态信息,如下:

打开OrleansConfiguration.xml 文件找到<Tracing DefaultTraceLevel="Info" TraceToConsole="false" TraceToFile="{0}-{1}.log" 这个节点,将TraceToConsole的值更改为true保存,再次运行,如下:

好了一切都完美了,接下来我们在继续开发客户端。

在解决方案下创建一个控制台应用程序Client,引用客户端相关类库:Install-Package Microsoft.Orleans.Client

引用项目:Sample.Interfaces

代码如下:

namespace Client
{
class Program
{
static void Main(string[] args)
{
System.Threading.Thread.Sleep();
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>();
//C#的一种新的表达式语法,这样就方便多了,省的我们拼接字符串。
Console.WriteLine($"用户{mobileNumber},{(userService.Exist(mobileNumber).Result?"已经存在":"不存在")}");
} }
}
}

在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>

注:要记得更改文件属性哦

一切准备就绪,下来让改一下启动方式为多项目启动,然后就F5等待飞吧!

终于看到胜利的果实了,哈哈!接下来我们接着说说另外一种开发方式以及发布方式。

上面的这种开发方式为了说明开发的那些具体步骤,需要引用那些类库,以及客户端如何去调用,步骤比较麻烦,尤其是服务端的开发、引用类库,也没有相应的单元测试,接下来我们看看另外一种服务端的开发方式。

跟上面的大体步骤一样

1.创建接口类库

2.创建实现类库

3.开发测试服务寄宿程序

在开始之前首先要确认一下你是否安装了Orleans的vs模版插件,如果安装了那么如下图:

如果没有安装,赶紧去下载一个吧地址在:http://dotnet.github.io/orleans/NuGets

找到这一节,如下图:

点开里面有你想要的插件,然后安装重启vs

1.创建接口类库

2.创建实现类库

3.创建服务寄宿程序

服务创建完之后,发现下面有自动生成的一个类OrleansHostWrapper,并且在Program下自动生成了很多代码,代码的大体意思就是,将服务端启动程序的逻辑封装在OrleansHostWrapper,然后启动是单独创建一个应用程序域,增加一些测试例子代码,方便多了吧,我们不需要写任何服务端的服务启动代码,在实际开发过程中我们只需要关心业务模块

即接口创建,接口实现,方便多了吧。

将相应的代码贴入进去,还记得上面出现的那个异常吗,记得要将Microsoft.Extensions.DependencyInjection类库引用进来哦,F5吧。

一切如预期所料,成功!

接下来我们创建一个单元测试程序库,方便服务端的程序单元测试Sample.Test

引用项目Sample.Implements、Sample.Interfaces

引用Orleans测试包 PM> Install-Package Microsoft.Orleans.TestingHost



我们创建一个测试类就叫UserServiceTest,继承自Orleans 测试库TestingSiloHost
 [ClassCleanup]
public static void ClassCleanup()
{
// Optional.
// By default, the next test class which uses TestignSiloHost will
// cause a fresh Orleans silo environment to be created.
StopAllSilosIfRunning();
}

测试代码如下:

namespace Sample.Test
{
[TestClass]
public class UserServiceTest: TestingSiloHost
{
[ClassCleanup]
public static void ClassCleanup()
{
// Optional.
// By default, the next test class which uses TestignSiloHost will
// cause a fresh Orleans silo environment to be created.
StopAllSilosIfRunning();
} [TestMethod]
public async void TestExist()
{
var grain = GrainFactory.GetGrain<IUserService>();
bool bo = await grain.Exist("");
Assert.IsTrue(bo);
}
}
}

记得增加两个配置文件,

ClientConfigurationForTesting.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>

OrleansConfigurationForTesting.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="false" 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>

更改xml文件属性为:如果较新则复制

测试项目结构大体如下:

好,测试编写完成,如何操作你懂得,这里就不废话了。

接下来说一下部署,部署吧,各有各的妙招,控制台、winform、windows服务等等,这里我说一个框架自带的一个部署控制台怎么用

记得Orleans 里面有这么一个程序OrleansHost.exe,他是干什么用的呢,对了就是用来部署的。

我们来看看他的源码,弄清楚他到底是做了一件什么事情

如下图:

打开这个文件,可以发现这个文件跟上面我们通过模版创建的server中的文件OrleansHostWrapper很相似,对了,这个就是为了保持开发部署的一致性,所以这个就可以用来直接部署了

我们在server的Debug下找到相应的程序,将程序复制到某个盘符比如D:\demo下面

如下图:

然后将配置文件拷贝进来OrleansConfiguration.xml

一切准备就绪,我们运行把,双击StartOrleans.cmd服务启动

运行成功.
你会发现这个服务部署于我们的开发互不影响,当我们开发好一个grain的时候,直接编译丢到这个部署目录下,别的地方就可以访问了,可以让我们重点关注业务逻辑,而不需要关心那些复杂的配置或者服务的开启关闭等等。 实例代码

Orleans之Hello World的更多相关文章

  1. .NET的Actor模型:Orleans

    Orleans是微软推出的类似Scala Akka的Actor模型,Orleans是一个建立在.NET之上的,设计的目标是为了方便程序员开发需要大规模扩展的云服务, 可用于实现DDD+EventSou ...

  2. 一种基于Orleans的分布式Id生成方案

    基于Orleans的分布式Id生成方案,因Orleans的单实例.单线程模型,让这种实现变的简单,贴出一种实现,欢迎大家提出意见 public interface ISequenceNoGenerat ...

  3. ORLEANS REMOTE DEPLOYMENT

    Orleans Remote Deployment Table of Contents Overview: 1 Prerequisites. 2 Deployment Steps. 2 Orleans ...

  4. Microsoft Orleans 之 入门指南

    Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...

  5. orleans/Documentation

    福利 奥尔良的主要好处是︰开发人员工作效率,甚至为非专家程序员;和默认的透明可伸缩性与程序员没有特别努力.我们扩大每个下面这些好处. 开发人员的生产力 奥尔良的编程模型通过提供以下关键的抽象. 担保和 ...

  6. github.com/dotnet/orleans

    Orleans is a framework that provides a straight-forward approach to building distributed high-scale ...

  7. 微软分布式云计算框架Orleans(1):Hello World

    自从写了RabbitHub框架系列后的一段时间内一直在思索更加轻量简便,分布式高并发的框架(RabbitHub学习成本较高),无意间在网上级联看到了很多新框架:从helios到Akka.NET在到Or ...

  8. 微软分布式云计算框架Orleans(2):容灾与集群(1)

    在上一篇:微软分布式云计算框架Orleans(1):Hello World,我们大概了解了Orleans如何运用,当然上一篇的例子可以说是简单且无效的,因为用了Orleans不可能只写一个Hello ...

  9. Orleans是什么 (一)

    官网:http://dotnet.github.io/orleans/ 文档:http://dotnet.github.io/orleans/What's-new-in-Orleans 源码:http ...

  10. Orleans 高级特性-目录

    这里将介绍一些Orleans的高级特性,适合对Orleans已经有不少了解的用户,先列出一个索引,博客文章慢慢补充 1.使用Immutable 优化复制 2.自定义序列化 (待完成) 3.可重入 Gr ...

随机推荐

  1. js判断密码强度

    html代码: <form name="form1" action=""> 密码:<input type="password&quo ...

  2. Node.js 在 PayPal实战

    之前有过一个谈了很多关于PayPal移动到node.js的一个应用平台.作为设置我的免费用户界面的第1部分的延续,我很高兴地说,这些传言是真的,我们的Web应用程序正在从Java迁移到JavaScri ...

  3. IOS开发 应用程序图标数字角标

    其实实现这个功能很简单,只要调用UIApplication即可.   用法用例:[UIApplication sharedApplication].applicationIconBadgeNumber ...

  4. Intellij IDEA 14的注册机

    将以下代码保存成keygen.java import java.math.BigInteger; import java.util.Date; import java.util.Random; imp ...

  5. 将w3cplus网站中的文章页面提取并导出为pdf文档

    最近在看一些关于CSS3方面的知识,主要是平时看到网页中有很多用CSS3实现的很炫的效果,所以就打算系统的学习一下.在网上找到很多的文章,但都没有一个好的整理性,比较凌乱.昨天看到w3cplus网站中 ...

  6. [转载] Redis

    转载:http://snowolf.iteye.com/blog/1630697 大约一年多前,公司同事开始使用Redis,不清楚是配置,还是版本的问题,当时的Redis经常在使用一段时间后,连接爆满 ...

  7. 随机抽样一致性算法(RANSAC)示例及源代码

    作者:王先荣 大约在两年前翻译了<随机抽样一致性算法RANSAC>,在文章的最后承诺写该算法的C#示例程序.可惜光阴似箭,转眼许久才写出来,实在抱歉.本文将使用随机抽样一致性算法来来检测直 ...

  8. 安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误

    安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误 这个错误几个月以前解决过一次,但是到又碰到的时候,竟然完全忘记当时怎么解决的了, 看来上了年纪记忆真是越来越不行了... 解决方案很简单 ...

  9. 配置算法(第4版)的Java编译环境

    1. 下载 1.1 JDK http://www.oracle.com/technetwork/java/javase/downloads/index.html选择“Windows x64 180.5 ...

  10. 【转】--在Android源码树中添加userspace I2C读写工具(i2c-util)

    通过/dev/i2c-n节点,用户可以在userspace直接访问板上的i2c外设寄存器,主要是透过I2C_RDWR这个IO控制命令将i2c_msg数组传递给kernel去执行.下面的代码可以完成这个 ...