做哪个外贸网站不用交费,公司网站域名申请,wordpress文章缩进,wordpress tintGrains是Orleans应用程序的构建块#xff0c;它们是彼此孤立的原子单位#xff0c;分布的#xff0c;持久的#xff0c; 一个典型的Grain是有状态和行为的一个单实例#xff0c;每个Grain实例的在单线程内执行#xff0c;Grain之间共享数据通过消息传递#xff0c;Grain…Grains是Orleans应用程序的构建块它们是彼此孤立的原子单位分布的持久的 一个典型的Grain是有状态和行为的一个单实例每个Grain实例的在单线程内执行Grain之间共享数据通过消息传递Grains是由Silo自动化管理。
Grain之间传递消息过程中也可能出现死锁的情况如Grain A发送消息给Grain B并等待它的完成此时Grain B发送一个消息给Grain A也等待其完成这时候出现相互等待而造成死锁。Orleans对Grain之间产生的死锁问题解决也是非常简单的只需要在Grain上加[Reentrant]属性具体可查看官方Concurrency。
Grain状态有好几种存储方式比如AzureTableStorage、AzureBlobStorage、SQLStorage、MemoryStorage 等我们还可以自定义存储。MemoryStorage在测试项目使用没问题但实际生产环境要使用其他持久存储的方式因为一旦一个Silo被关闭内存存储的状态将会消失。
在分布式下State的使用可以减少很多对数据库层面的压力。当然也不是所有的Grain都推荐使用State还是看实际业务需求。我们可以想象一个场景一个商品的库存如果保存在State中所有请求都共享这个State在判断是否有剩余商品的时候是不是就不需要每次都去查询数据库了
定义接口
public interface IPersonGrain : IGrainWithStringKey
{Task SayHelloAsync();
}
实现接口
public class PersonGrain : Grain, IPersonGrain
{public Task SayHelloAsync(){string primaryKey this.GetPrimaryKeyString();Console.WriteLine(${primaryKey} said hello!);return Task.CompletedTask;}
}
为了实现状态存储我们需要创建一个class
public class PersonGrainState
{public bool SaidHello { get; set; }
}
修改代码实现的PersonGrain不应该再继承Grain而是GrainT
[StorageProvider(ProviderName OrleansStorage)]
public class PersonGrain : GrainPersonGrainState, IPersonGrain
{public async Task SayHelloAsync(){string primaryKey this.GetPrimaryKeyString();bool saidHelloBefore this.State.SaidHello;string saidHelloBeforeStr saidHelloBefore ? already : null;Console.WriteLine(${primaryKey}{saidHelloBeforeStr} said hello!);this.State.SaidHello true;await this.WriteStateAsync();}
}
第一次调用这个方法的时候this.State.SaidHello为false输出xxx said hello!。然后我们通过WriteStateAsync修改SaidHello为true当第二次被调用的时候从State里取出的SaidHello已经变成了true则输出xxx already said hello!
Orleans 提供了非常简单的API来处理持久化装状态看方法名就知道什么啥意思了WriteStateAsync()、ReadStateAsync() 、 ClearStateAsync()。
同时在PersonGrain加了一个StorageProvider属性参数ProviderName赋值为OrleansStorage这里需要对Silo的配置文件OrleansConfiguration.xml做调整添加StorageProviders配置Type表示存储方式Name表示名称程序内指定的ProviderName需要和配置中这个名称保持一致。
注意当Name为Default时如果某个Grain使用Default来存储可以不需要加StorageProvider属性。StorageProviders下可以有多个Provider每个Provider的Type可以不一样每个Grain指定的存储方式也可以不一样ProviderName指定是谁就用谁存储。
?xml version1.0 encodingutf-8 ?
OrleansConfiguration xmlnsurn:orleansGlobalsSeedNode Addresslocalhost Port11111 /StorageProvidersProvider TypeOrleans.Storage.MemoryStorageNameOrleansStorage //StorageProviders/GlobalsDefaultsNetworking Addresslocalhost Port11111 /ProxyingGateway Addresslocalhost Port30000 //Defaults
/OrleansConfiguration
为了验证Grain之间是独立的在Client加入以下代码 var joe GrainClient.GrainFactory.GetGrainIPersonGrain(Joe);
joe.SayHelloAsync();
joe.SayHelloAsync();var sam GrainClient.GrainFactory.GetGrainIPersonGrain(Sam);
sam.SayHelloAsync();
sam.SayHelloAsync();
测试结果 Test Result
SQL Server 持久存储State
上面提到State以内存存储的方式并不适合生产环境那下面我们使用SQL Server来实现。
在Silo程序集中安装依赖包
Install-Package Microsoft.Orleans.OrleansSqlUtils
Install-Package System.Data.SqlClient
创建数据库和表
在SQL Server中创建一个数据库命名如OrleansStorage随意在解决方案下找到目录packages\Microsoft.Orleans.OrleansSqlUtils.1.5.0\lib\net461\SQLServer目录下有一个.sql文件在OrleansStorage数据库下执行这个sql脚本即可
修改OrleansConfiguration.xml的StorageProviders节点为
StorageProvidersProvider TypeOrleans.Storage.AdoNetStorageProviderNameOrleansStorageAdoInvariantSystem.Data.SqlClientDataConnectionStringServer.;DatabaseOrleansStorage;User IDsa;Password123456;/
/StorageProviders
重新启动Silo和Client
执行完成后查看数据库中表Storage的内容数据的值是二进制是方式存储。 storage
之后不管重启多少次输出的结果都是 xxx already saild hello! 。
参考链接
Actor模型Orleans案例Demo-OrleansState
相关文章
.NET的Actor模型Orleans微软分布式云计算框架Orleans(1)Hello World微软分布式云计算框架Orleans(2)容灾与集群(1)Aaron Stannard谈Akka.NET 1.1使用Akka.net开发第一个分布式应用Orleans入门例子Orleans例子再进一步Orleans稍微复杂的例子—互动Orleans简单配置Orleans配置---持久化Orleans—一些概念Orleans的集群构建Oleans集群之Consul再解释Orleans解决并发之痛一单线程
原文地址http://www.jianshu.com/p/ccd9cffa77bf .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注