[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居然能玩到一起 ...
随机推荐
- docker环境部署
docker环境部署 1 查看当前系统版本 只支持CentOS7版本的系统,如果不是的话,可以让项目方进行重装或者系统内核升级. [root@bogon bin]# cat /etc/redhat-r ...
- Java并发编程阅读笔记-Java监视器模式示例
1.前言 书中在解释Java监视器模式的时候使用了一个车辆追踪器例子,根据不同的使用场景给出了不同的实现和优化. 2.监视器模式示例 实现一个调度车辆的"车辆追踪器",每台车使用一 ...
- 女皇武则天:我不愿被 extends
01. 利用继承,我们可以基于已存在的类构造一个新类.继承的好处在于,子类可以复用父类的非 private 的方法和非 private 成员变量. is-a 是继承的一个明显特征,就是说子类的对象引用 ...
- Vue 进阶之路(六)
上篇文章我们分析了一下 vue 中的条件渲染,本篇我们说一下 vue 中的列表渲染和 set 方法. <!DOCTYPE html> <html lang="en" ...
- java游戏开发杂谈 - 线程
线程,让游戏拥有了动态变化的能力. java的图形界面,在启动的时候,就开始了一个线程. 这个线程负责处理:JFrame.JPanel等的绘制.事件处理. 它是由操作系统调用的,在程序启动时开启,程序 ...
- HTTP网络协议与手写Web服务容器
Http协议 1.深入概念 Http:HyperText Transfer Protocol,即是超文本传输协议. 2.浅出概念(使用浏览器访问服务器端网页时需要遵循的一系列规则) Http:将各种不 ...
- Java进阶篇设计模式之五-----外观模式和装饰器模式
前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...
- 重学前端 --- Promise里的代码为什么比setTimeout先执行?
首先通过一段代码进入讨论的主题 var r = new Promise(function(resolve, reject){ console.log("a"); resolve() ...
- 设计模式之责任链模式——Java语言描述
责任链模式为请求创建了一个接受者对象的链.这种模式给予请求的类型,对请求的发送者和接受者进行解耦.这种类型的设计模式属于行为模式.在这种模式下,通常每个接收者都包含对另一个接收者的引用.如果一个对象不 ...
- 解决小米手机USB安装apk时AS报错:INSTALL_FAILED_USER_RESTRICTED
今天,直接用AS在小米手机上运行安装的时候总是报错:INSTALL_FAILED_USER_RESTRICTED,于是乎,通过以下方式解决: 在开发者选项将USB安装打开,然后,哈,解决了.记录一下.