[orleans2.1]这是你没玩过的船新版本
不知不觉orleans就发布到2.1版本的,但是说也奇怪orleans越是完善我发现园子相关的博客就越少,大概是大佬都在美滋滋用在生产环境,不屑于玩demo了吧。
但是小弟不才还是只会玩demo,所以只能简单的介绍介绍2.1版本的新玩法了。
1.新建一个asp.net core的webapi项目,然后引用下面几个nuget包:
Microsoft.Orleans.OrleansRuntime
Microsoft.Orleans.CodeGenerator.MSBuild
Microsoft.Orleans.Transactions
Orleans.Providers.MongoDB
OrleansDashboard
2.包装一下orleans的silobuilder类,并且继承IHostedService直接和asp.net core运行在一起
public class SiloWrapper : IHostedService
{
private readonly ISiloHost _silo;
public readonly IClusterClient Client; public SiloWrapper()
{
_silo = new SiloHostBuilder()
.UseLocalhostClustering()
.ConfigureApplicationParts(parts =>
parts.AddApplicationPart(typeof(Grains.IUserGrain).Assembly).WithReferences())
.EnableDirectClient()//2.1新增的功能,单个Host可以直接使用SiloHost的Client,不需要再用ClientBuilder建Client了
.AddMongoDBGrainStorageAsDefault(options =>
{
options.ConnectionString = "mongodb://localhost/OrleansTestApp";
})//配置数据库
.ConfigureLogging(x =>
{
x.AddConsole();
x.SetMinimumLevel(LogLevel.Warning);
})
.UseDashboard(x =>
{
x.HostSelf = false;
})//HostSelf设置为false
.UseTransactions()//2.1的事务配置简化了
.Build(); Client = _silo.Services.GetRequiredService<IClusterClient>();//把sliohost的IClusterClient暴露出去。
} public async Task StartAsync(CancellationToken cancellationToken)
{
await _silo.StartAsync(cancellationToken);
} public async Task StopAsync(CancellationToken cancellationToken)
{
await _silo.StopAsync(cancellationToken);
}
}
3.Startup类配置:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<SiloWrapper>();//注入SiloWrapper
services.AddSingleton<IHostedService>(x=>x.GetRequiredService<SiloWrapper>());//同时把SiloWrapper注入为IHostedService
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton(x => x.GetRequiredService<SiloWrapper>().Client);//注入SiloWrapper的Client
services.AddServicesForSelfHostedDashboard();//注入orleans的dashboard
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseOrleansDashboard(new OrleansDashboard.DashboardOptions { BasePath = "/dashboard"});//设置一下dashboard的访问路径
app.UseMvc();
}
}
4.新建一些Grain类,这里只给出一个后面我会贴代码地址出来。
public class UserGrain:Grain<UserInfo>,IUserGrain
{
public ValueTask<UserInfo> GetInfo()//同步代码可以返回ValueTask
{
return new ValueTask<UserInfo>(State);
} public async Task<UserInfo> UpdateInfo(UserInfo info)
{
State = info;
await WriteStateAsync();//更新数据才需要数据库相关的操作
return State;
} public async Task<uint> GetBalance()
{
var account = this.GrainFactory.GetGrain<IAccountGrain>(this.GetPrimaryKeyLong());//通过GrainFactory访问其他grain
return await account.GetBalance();
}
}
[StatelessWorker]
public class ATMGrain : Grain, IATMGrain//转账事务的专用grain
{
Task IATMGrain.Transfer(long fromAccount, long toAccount, uint amountToTransfer)
{
return Task.WhenAll(
this.GrainFactory.GetGrain<IAccountGrain>(fromAccount).Withdraw(amountToTransfer),
this.GrainFactory.GetGrain<IAccountGrain>(toAccount).Deposit(amountToTransfer));
}
} public class AccountGrain : Grain, IAccountGrain//加钱,减钱,查钱啦
{
private readonly ITransactionalState<Balance> _balance; public AccountGrain(
[TransactionalState("balance")] ITransactionalState<Balance> balance)
{
_balance = balance ?? throw new ArgumentNullException(nameof(balance));
} async Task IAccountGrain.Deposit(uint amount)
{
await _balance.PerformUpdate(x => x.Value += amount);
} async Task IAccountGrain.Withdraw(uint amount)
{
await _balance.PerformUpdate(x =>
{
if (x.Value < amount)
{
throw new InvalidOperationException( "The transferred amount was greater than the balance.");
}
return x.Value -= amount;
});
} Task<uint> IAccountGrain.GetBalance()
{
return _balance.PerformRead(x => x.Value);
}
}
5.controller相关的代码,这里也是照旧只贴一部分
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IClusterClient _client;
public ValuesController(IClusterClient client)
{
_client = client;
}
[HttpGet("[action]/{id}")]
public async Task<object> GetInfo(long id)
{
var userGrain = _client.GetGrain<IUserGrain>(id);
return await userGrain.GetInfo();
}
}
代码地址:https://github.com/iJzFan/orleansdemo
可以看到2.1之后配置真的简单了很多,简单几步之后你就能快乐的进行无数据库设计无并发考虑的编程啦。
最后面是我用jmeter做的一个小测试(不是特别严谨,日志都是开着的,不要太纠结数据),配置嘛就是那个1核两G的腾讯云垃圾主机啦,上面跑了一个两个docker,一个是前面的orleansdemo,一个是mongodb。
测试条件就是用户1和用户2相互转账( ̄︶ ̄)↗ ,10个线程,分别转1000次(对应的URL:/api/values/atm?from=1&to=2&amount=1和/api/values/atm?from=2&to=1&amount=1)。

测试条件就是1转2,2转3,3转4,4转1,10个线程,分别转500次(url参考上面)。

时延还是挺低的,平均才55~61ms,腾讯云那个垃圾主机一秒都能处理150~160的事务请求。
最最后面贴几个orleans相关的代码库,毕竟我上面的demo还是太小儿科了,
https://github.com/RayTale/Ray 分布式、高性能、事件溯源、事件驱动、最终一致性框架
https://github.com/Squidex/squidex Headless CMS and Content Managment Hub
[orleans2.1]这是你没玩过的船新版本的更多相关文章
- 没玩过这些微信小游戏你就out了
你确定没玩过下面这些微信小游戏?是不是有点out了?赶紧添加微信号kangfuyk,回复H5马上畅玩! 当然了,扫一下二维码关注后回复H5更快捷噢! 微信小游戏列表,持续更新中 辨色大比拼!心理游戏 ...
- 好久没玩docker了,温下手
好久没玩docker了,温下手 安装 Docker Docker 软件包已经包括在默认的 CentOS-Extras 软件源里.因此想要安装 docker,只需要运行下面的 yum 命令: yum i ...
- 好久没玩laravel了,今天玩下Laravel项目迁移步骤
.在新的目录中克隆git远程版本库 .执行composer install安装依赖 .执行php artisan key:generate生成key 好久没玩laravel了,今天玩下Laravel项 ...
- 你没玩过的全新版本!Win10这些骚操作你知多少
你没玩过的全新版本!Win10这些骚操作你知多少 [PConline技巧]不知不觉,Win10与我们相伴已经整整四个年头了,从最开始的组团抗拒到现在的默默接受,个中滋味相信谁心里都有个数.近日微软开始 ...
- 好久没玩laravel了,5.6玩下(三)
好了,基础的测试通了,咱们开始增删改了 思路整理 先创建项目功能控制器 然后设置路由访问规则 然后开发项目的增删改功能 1 先创建项目的控制器 php artisan make:controller ...
- 好久没玩laravel了,5.6玩下(二)
做个项目的增删改查 第一步 把数据库的表结构建好,生成迁移 1 怎么建,当然是用php artisan命令了 使用 Artisan 命令 make:migration 来创建一个新的迁移: php ...
- 好久没玩laravel了,5.6玩下(一)
那么先到官方找到框架,然后安装下 composer安装的,composer怎么安装的 我就不说了 前置条件: PHP >= OpenSSL PHP Extension PDO PHP Exten ...
- 你没有见过的【高恪】船新版本(SX3000 NAT1 X86魔改)
最近魔改了高恪SX3000 X86,做了如下更改: 开启了SSH 集成了插件(酸酸乳.V2RXY.SMB等等) 开启了NAT1 DIY了主题 精简了官方内置的无用应用和模块 截图(建议右击图片,在新标 ...
- 万万没想到!ModelArts与AppCube组CP了
摘要:嘘,华为云内部都不知道的秘密玩法,我悄悄告诉您! 双"魔"合璧庆双节 ↑开局一张图,故事全靠编 华为云的一站式开发平台ModelArts和应用魔方AppCube居然能玩到一起 ...
随机推荐
- java基于BasicPlayer调用 播放音乐
无聊中想想用java调用下听音乐的api.晚上很多文章用的比较老大方法了,都是用原生的代码写,而且不支持mp3格式,BasicPlayer第三方包提供了很好的api调用,简单的3行代码就可以调用mp3 ...
- java游戏开发杂谈 - 有限状态机
在不同的阶段,游戏所运行的逻辑.所显示的界面,都是不同的. 以五子棋举例,游戏开始.游戏中.胜负已分,对应的界面和逻辑都不同. 在游戏中,又分为:自己下棋.对方下棋.游戏暂停.悔棋等多个状态. 再比如 ...
- Jmeter利用正则表达式提取器提取登录cookie供下一步使用
最近在学Jmeter,遇到需要登录之后才能进行下一步操作的场景,网上查了各位大神的资料,东拼西凑总算是做好满足需求了,写一下经过和步骤吧. 一.正常调用 按正常流程添加线程组.HTTP请求(登录和添加 ...
- 从壹开始微服务 [ DDD ] 之终篇 ║当事件溯源 遇上 粉丝活动
回首 哈喽~大家好,时间过的真快,关于DDD领域驱动设计的讲解基本就差不多了,本来想着周四再开一篇,感觉没有太多的内容了,剩下的一个就是验证的问题,就和之前的JWT很类似,就不打开一个章节了,而且这个 ...
- Google 的 QUIC 华丽转身成为下一代网络协议: HTTP/3.0
HTTP/2.0 还没有普及,HTTP/3.0 标准就要被制定了. 据 IETF 透露,HTTP-over-QUIC 实验协议将被重命名为 HTTP/3,并成为 HTTP 协议的第三个正式版本. IE ...
- 学习 JavaScript (八) 引用类型之 Object
在JavaScript中,引用类型是一种数据结构.包括对象(Obejct).数组(Array).日期(Date).正则表达式(RegExp).函数(Function).基本包装类型(new Boole ...
- springmvc重定向
String success="07大吉大利25"; @RequestMapping("str") public String test1(){ return ...
- MSSQL 更改表结构
更改表结构: alter TABLE 表1 ALTER COLUMN 列名1 NCHAR(40)
- python3 树莓派 + usb摄像头 做颜色识别 二维码识别
今天又啥也没干 我完蛋了哦 就是没办法沉下心来,咋办....还是先来条NLP吧.. 七,凡事必有至少三个解决方法 对事情只有一个方法的人,必陷入困境,因为别无选择. 对事情有两个方法的人也陷入困境, ...
- Luogu P5309 [Ynoi2012]D1T1
小清新分块题,从头到尾都十分套路,和CXR大佬一起YY了一下就出来了 首先套路地设个阈值\(S\),把修改的\(x\)分成大于\(S\)和小于等于\(S\)两部分,然后我们考虑分别求解这两部分 \(x ...