[orleans2.1]這是你沒玩過的船新版本

来源:https://www.cnblogs.com/jzfan/archive/2018/10/11/orleans_demo.html
-Advertisement-
Play Games

不知不覺orleans就發佈到2.1版本的,但是說也奇怪orleans越是完善我發現園子相關的博客就越少,大概是大佬都在美滋滋用在生產環境,不屑於玩demo了吧。 但是小弟不才還是只會玩demo,所以只能簡單的介紹介紹2.1版本的新玩法了。 1.新建一個asp.net core的webapi項目,然 ...


  不知不覺orleans就發佈到2.1版本的,但是說也奇怪orleans越是完善我發現園子相關的博客就越少,大概是大佬都在美滋滋用在生產環境,不屑於玩demo了吧。

  但是小弟不才還是只會玩demo,所以只能簡單的介紹介紹2.1版本的新玩法了。

  1.新建一個asp.net core的webapi項目,然後引用下麵幾個nuget包:

1 Microsoft.Orleans.OrleansRuntime
2 Microsoft.Orleans.CodeGenerator.MSBuild
3 Microsoft.Orleans.Transactions
4 Orleans.Providers.MongoDB
5 OrleansDashboard

  2.包裝一下orleans的silobuilder類,並且繼承IHostedService直接和asp.net core運行在一起

 1     public class SiloWrapper : IHostedService
 2     {
 3         private readonly ISiloHost _silo;
 4         public readonly IClusterClient Client;
 5 
 6         public SiloWrapper()
 7         {
 8             _silo = new SiloHostBuilder()
 9                 .UseLocalhostClustering()
10                 .ConfigureApplicationParts(parts =>
11                     parts.AddApplicationPart(typeof(Grains.IUserGrain).Assembly).WithReferences())
12                     .EnableDirectClient()//2.1新增的功能,單個Host可以直接使用SiloHost的Client,不需要再用ClientBuilder建Client了
13                     .AddMongoDBGrainStorageAsDefault(options =>
14                     {
15                         options.ConnectionString = "mongodb://localhost/OrleansTestApp";
16                     })//配置資料庫
17                     .ConfigureLogging(x =>
18                     {
19                         x.AddConsole();
20                         x.SetMinimumLevel(LogLevel.Warning);
21                     })
22                     .UseDashboard(x =>
23                     {
24                         x.HostSelf = false;
25                     })//HostSelf設置為false
26                     .UseTransactions()//2.1的事務配置簡化了
27                     .Build();
28 
29             Client = _silo.Services.GetRequiredService<IClusterClient>();//把sliohost的IClusterClient暴露出去。
30         }
31 
32         public async Task StartAsync(CancellationToken cancellationToken)
33         {
34             await _silo.StartAsync(cancellationToken);
35         }
36 
37         public async Task StopAsync(CancellationToken cancellationToken)
38         {
39             await _silo.StopAsync(cancellationToken);
40         }
41     }

  3.Startup類配置:

 1     public class Startup
 2     {
 3         public Startup(IConfiguration configuration)
 4         {
 5             Configuration = configuration;
 6         }
 7 
 8         public IConfiguration Configuration { get; }
 9 
10         public void ConfigureServices(IServiceCollection services)
11         {
12             services.AddSingleton<SiloWrapper>();//註入SiloWrapper
13             services.AddSingleton<IHostedService>(x=>x.GetRequiredService<SiloWrapper>());//同時把SiloWrapper註入為IHostedService
14             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15             services.AddSingleton(x => x.GetRequiredService<SiloWrapper>().Client);//註入SiloWrapper的Client
16             services.AddServicesForSelfHostedDashboard();//註入orleans的dashboard
17         }
18 
19         public void Configure(IApplicationBuilder app, IHostingEnvironment env)
20         {
21             if (env.IsDevelopment())
22             {
23                 app.UseDeveloperExceptionPage();
24             }
25 
26             app.UseOrleansDashboard(new OrleansDashboard.DashboardOptions { BasePath = "/dashboard"});//設置一下dashboard的訪問路徑
27             app.UseMvc();
28         }
29     }

  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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 引言 - 一切才剛剛開始 structc 是 C 結構基礎庫. 簡單有態度. structc - https://github.com/wangzhione/structc 之前推過幾次 structc, 沒什麼效果. 這次乘著最近加班不多, 來詳細解說哈 structc 的思考初衷. 0.0 整體 ...
  • 示例: 什麼是對象  《JAVA編程思想》對於對象的定義是:將問題空間中的元素以及它們在方案空間的表示物稱作“對象”。  1. 問題空間:實際解決的問題模型;  2. 方案空間: 電腦(機器模型)。  實際的問題在電腦(機器模型)中的表示稱為對象。在上面示 ...
  • [TOC] Dubbo入門 Editor:SimpleWu Dubbo是 阿裡巴巴公司開源的一個高性能優秀的服務框架使得應用可通過高性能的 RPC 實現服務的輸出和輸入功能,可以和 Spring框架無縫集成。 背景 隨著互聯網的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分散式服務架 ...
  • 經過上一篇教程的學習,我們知道對象將它的狀態存在域中。然而,Java中也使用了“變數”這個術語。在這一篇教程中,我們將會討論它們之間的關係,以及變數命名的規則和慣例,基本數據類型以及它們的預設值和字面量。 ...
  • JVM學習筆記1:Java虛擬機記憶體模型 學習JVM,Java虛擬機對理解Java程式執行過程和Java程式性能調優具有很大幫助。本系列博客旨在由淺到深學習並理解JVM。參考閱讀:《深入理解Java虛擬機 JVM高級特性和最佳實踐》。這個書寫的非常好,推薦有條件的讀者買一本來閱讀,網上也有電子版的。 ...
  • 在JDK1.8後,對HashMap源碼進行了更改,引入了紅黑樹。在這之前,HashMap實際上就是就是數組+鏈表的結構,由於HashMap是一張哈希表,其會產生哈希衝突,為瞭解決哈希衝突,HashMap採用了開鏈法,即對於用對象hashCode值計算哈希表數組下表時,當出現相同情況時,會在相同的地方 ...
  • 二叉樹中和為某一值的路徑: 輸入一顆二叉樹的跟節點和一個整數,列印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(註意: 在返回值的list中,數組長度大的數組靠前) 思路: 1.二叉樹的前序遍歷,中左右順序 2.把目標值target傳... ...
  • ORM-SqlRepoEx 是 .Net平臺下相容.NET Standard 2.0,一個實現以Lambda表達式轉轉換標準SQL語句,使用強類型操作數據的輕量級ORM工具,在減少魔法字串同時,通過靈活的Lambda表達式組合,實現業務數據查詢的多樣性。 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...