[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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...