[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 jackson 忽略不存在的属性字段 和 按照属性名转json
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, isGetterVisibi ...
- JAVAEE——SpringMVC第一天:介绍、入门程序、架构讲解、SpringMVC整合MyBatis、参数绑定、SpringMVC和Struts2的区别
1. 学习计划 第一天 1.SpringMVC介绍 2.入门程序 3.SpringMVC架构讲解 a) 框架结构 b) 组件说明 4.SpringMVC整合MyBatis 5.参数绑定 a) Sp ...
- java基础(六)-----String性质深入解析
本文将讲解String的几个性质. 一.String的不可变性 对于初学者来说,很容易误认为String对象是可以改变的,特别是+链接时,对象似乎真的改变了.然而,String对象一经创建就不可以修改 ...
- SSRS报表服务随笔(rdl报表服务)-报表结构与样式
设计rdl报表,比设置HTML页面简单多了,Reporting报表分为页眉,页脚,主体三个部分 rdl文件实际是xml结构的文件,具体是什么语言呢,很抱歉,这点我还不能回复,在我看来,是由固定节点的x ...
- 带你学习AOP框架之Aspect.Core[1]
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的 ...
- EIGRP 基础实验
一.环境准备 1. 软件:GNS3 2. 路由:c7200 二.实验操作 实验要求: 1.掌握EIGRP 的基本配置 2.掌握EIGRP 的通配符掩配置方法 3.掌握EIGRP 的自动汇总特性,理解E ...
- 腾讯视频国际版(Android)电量测试方法研究与总结
本文由云+社区发表 作者:腾讯移动品质中心TMQ 1.研究背景: 在2017年Google I/O大会上,Google发布了Google Play管理中心的新功能:Android vitals.当ap ...
- 粮草先行——Android折叠屏开发技术点(二)
继该系列的第一篇和番外篇之后,今天我们来聊一聊多窗口开发的注意事项.实际上,与其说"多窗口开发",不如说让我们的APP适应多窗口模式. 可能有朋友会问,为什么要提到多窗口模式呢? ...
- 【swoole】如果使用好定时器功能
swoole中提供了一个定期器的用法 $server->tick(1000, function() use ($server, $fd) { $server->send($fd, &quo ...
- [Android 除錯] Conflict with dependency
Android Studio build 時的錯誤訊息 : Conflict with dependency 詳細錯誤訊息 : Conflict with dependency 'com.androi ...