dapr微服务.net sdk入门

Actors入门

先决条件

  • .Net Core SDK 3.0

  • Dapr CLI

  • Dapr DotNet SDK

概述

本文档描述如何在客户端应用程序上创建Actor(MyActor)并调用其方法.

MyActor --- MyActor.Interfaces|+- MyActorService|+- MyActorClient
  • 接口项目(\MyActor\MyActor.Interfaces)。此项目包含参与者的接口定义。Actor接口可以在任何名称的项目中定义。接口定义了actor实现和调用actor的客户机共享的actor契约。因为客户机项目可能依赖于它,所以通常在与actor实现分离的程序集中定义它是有意义的.

  • actor服务项目(\MyActor\MyActor service)。这个项目实现了ASP.Net核心web服务,该服务将承载参与者。它包含actor MyActor.cs的实现。actor实现是从基类型actor派生并实现MyActor.interfaces项目中定义的接口的类。actor类还必须实现一个构造函数,该构造函数接受ActorService实例和ActorId,并将它们传递给基本actor类.

  • actor客户端项目(\MyActor\MyActor client)此项目包含actor客户端的实现,该客户端调用actor接口中定义的MyActor方法.

第1步 - 创建Actor接口

Actor接口定义Actor实现和调用Actor的客户机共享的Actor契约.

Actor接口定义如下:

  • Actor接口必须继承 Dapr.Actors.IActor 接口

  • Actor方法的返回类型必须是Task或Task<object>

  • Actor方法最多可以有一个参数

创建项目和添加依赖

# Create Actor Interfaces
dotnet new classlib -o MyActor.Interfacescd MyActor.Interfaces# Add Dapr.Actors nuget package
dotnet add package Dapr.Actors

升级项目到 .NET Core 3.0

更新csproj文件中的netcore到 .NET Core 3.0

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>netcoreapp3.0</TargetFramework></PropertyGroup><ItemGroup><PackageReference Include="Dapr.Actors" Version="0.1.0-preview01" /></ItemGroup>
</Project>

实现 IMyActor 接口

定义 IMyActor 接口和 MyData 数据对象.

using Dapr.Actors;
using System.Threading.Tasks;namespace MyActor.Interfaces
{public interface IMyActor : IActor{Task<string> SetDataAsync(MyData data);Task<MyData> GetDataAsync();Task RegisterReminder();Task UnregisterReminder();Task RegisterTimer();Task UnregisterTimer();}public class MyData{public string PropertyA { get; set; }public string PropertyB { get; set; }public override string ToString(){var propAValue = this.PropertyA == null ? "null" : this.PropertyA;var propBValue = this.PropertyB == null ? "null" : this.PropertyB;return $"PropertyA: {propAValue}, PropertyB: {propBValue}";}}
}

第2步 - 创建Actor服务

Dapr使用ASP.NET web服务托管Actor服务. 本节将实现 IMyActor 接口以及注册Actor到Dapr运行时.

创建项目及添加依赖

# Create ASP.Net Web service to host Dapr actor
dotnet new webapi -o MyActorServicecd MyActorService# Add Dapr.Actors nuget package
dotnet add package Dapr.Actors# Add Dapr.Actors.AspNetCore nuget package
dotnet add package Dapr.Actors.AspNetCore# Add Actor Interface reference
dotnet add reference ../MyActor.Interfaces/MyActor.Interfaces.csproj

添加Actor实现

实现IMyActor接口并从Dapr.Actors.Actor类派生。下面的示例还演示了如何使用Actor提醒。对于Actor来说,使用提醒,它必须来源于IRemindable。如果不打算使用提醒功能,可以跳过实现下面代码中显示的IRemindable和提醒特定方法.

using Dapr.Actors;
using Dapr.Actors.Runtime;
using MyActor.Interfaces;
using System;
using System.Threading.Tasks;namespace MyActorService
{internal class MyActor : Actor, IMyActor, IRemindable{/// <summary>/// Initializes a new instance of MyActor/// </summary>/// <param name="actorService">The Dapr.Actors.Runtime.ActorService that will host this actor instance.</param>/// <param name="actorId">The Dapr.Actors.ActorId for this actor instance.</param>public MyActor(ActorService actorService, ActorId actorId): base(actorService, actorId){}/// <summary>/// This method is called whenever an actor is activated./// An actor is activated the first time any of its methods are invoked./// </summary>protected override Task OnActivateAsync(){// Provides opportunity to perform some optional setup.Console.WriteLine($"Activating actor id: {this.Id}");return Task.CompletedTask;}/// <summary>/// This method is called whenever an actor is deactivated after a period of inactivity./// </summary>protected override Task OnDeactivateAsync(){// Provides Opporunity to perform optional cleanup.Console.WriteLine($"Deactivating actor id: {this.Id}");return Task.CompletedTask;}/// <summary>/// Set MyData into actor's private state store/// </summary>/// <param name="data">the user-defined MyData which will be stored into state store as "my_data" state</param>public async Task<string> SetDataAsync(MyData data){// Data is saved to configured state store implicitly after each method execution by Actor's runtime.// Data can also be saved explicitly by calling this.StateManager.SaveStateAsync();// State to be saved must be DataContract serialziable.await this.StateManager.SetStateAsync<MyData>("my_data",  // state namedata);      // data saved for the named state "my_data"return "Success";}/// <summary>/// Get MyData from actor's private state store/// </summary>/// <return>the user-defined MyData which is stored into state store as "my_data" state</return>public Task<MyData> GetDataAsync(){// Gets state from the state store.return this.StateManager.GetStateAsync<MyData>("my_data");}/// <summary>/// Register MyReminder reminder with the actor/// </summary>public async Task RegisterReminder(){await this.RegisterReminderAsync("MyReminder",              // The name of the remindernull,                      // User state passed to IRemindable.ReceiveReminderAsync()TimeSpan.FromSeconds(5),   // Time to delay before invoking the reminder for the first timeTimeSpan.FromSeconds(5));  // Time interval between reminder invocations after the first invocation}/// <summary>/// Unregister MyReminder reminder with the actor/// </summary>public Task UnregisterReminder(){Console.WriteLine("Unregistering MyReminder...");return this.UnregisterReminderAsync("MyReminder");}// <summary>// Implement IRemindeable.ReceiveReminderAsync() which is call back invoked when an actor reminder is triggered.// </summary>public Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period){Console.WriteLine("ReceiveReminderAsync is called!");return Task.CompletedTask;}/// <summary>/// Register MyTimer timer with the actor/// </summary>public Task RegisterTimer(){return this.RegisterTimerAsync("MyTimer",                  // The name of the timerthis.OnTimerCallBack,       // Timer callbacknull,                       // User state passed to OnTimerCallback()TimeSpan.FromSeconds(5),    // Time to delay before the async callback is first invokedTimeSpan.FromSeconds(5));   // Time interval between invocations of the async callback}/// <summary>/// Unregister MyTimer timer with the actor/// </summary>public Task UnregisterTimer(){Console.WriteLine("Unregistering MyTimer...");return this.UnregisterTimerAsync("MyTimer");}/// <summary>/// Timer callback once timer is expired/// </summary>private Task OnTimerCallBack(object data){Console.WriteLine("OnTimerCallBack is called!");return Task.CompletedTask;}}
}

使用显式actor类型名

默认情况下,客户端看到的actor的“类型”是从actor实现类的名称派生的。如果需要,可以通过将actor attribute属性附加到actor实现类来指定显式类型名.

[Actor(TypeName = "MyCustomActorTypeName")]
internal class MyActor : Actor, IMyActor
{// ...
}

注册 Actor 到 Dapr 运行时

将 MyActor 注册到 actor runtime并设置本地主机端口(https://localhost:3000) , Dapr runtime可以通过该端口调用actor.

private const int AppChannelHttpPort = 3000;public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseActors(actorRuntime =>{// Register MyActor actor typeactorRuntime.RegisterActor<MyActor>();}).UseUrls($"http://localhost:{AppChannelHttpPort}/");

更新Startup.cs

public class Startup{...public void ConfigureServices(IServiceCollection services){services.AddRouting();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseHsts();}}}

第3步 - 添加客户端

创建一个简单的控制台应用程序来调用actor服务。Dapr SDK提供Actor代理客户端来调用Actor接口中定义的Actor方法.

创建项目并添加依赖

# Create Actor's Client
dotnet new console -o MyActorClientcd MyActorClient# Add Dapr.Actors nuget package
dotnet add package Dapr.Actors# Add Actor Interface reference
dotnet add reference ../MyActor.Interfaces/MyActor.Interfaces.csproj

使用Actor远程服务调用Actor方法

我们建议使用本地代理到actor实例,因为ActorProxy.Create<IMyActor>(actorID,actorType)返回强类型actor实例来设置远程过程调用.

namespace MyActorClient
{using Dapr.Actors;using Dapr.Actors.Client;using MyActor.Interfaces;using System;using System.Threading.Tasks;...static async Task InvokeActorMethodWithRemotingAsync(){var actorType = "MyActor";      // Registered Actor Type in Actor Servicevar actorID = new ActorId("1");// Create the local proxy by using the same interface that the service implements// By using this proxy, you can call strongly typed methods on the interface using Remoting.var proxy = ActorProxy.Create<IMyActor>(actorID, actorType);var response = await proxy.SetDataAsync(new MyData(){PropertyA = "ValueA",PropertyB = "ValueB",});Console.WriteLine(response);var savedData = await proxy.GetDataAsync();Console.WriteLine(savedData);}...
}

非远程方式调用 Actor 方法

如果Actor方法最多接受一个参数,则可以调用Actor方法而无需远程处理(直接通过http或使用ActorProxy中提供的helper方法)。Actor运行时将从客户端反序列化传入的请求体,并将其用作方法参数来调用Actor方法。当进行非远程处理调用时,Actor方法参数和返回类型被序列化,反序列化为JSON.

ActorProxy.Create(actorID, actorType) 返回 ActorProxy 实例并允许使用原始http客户端调用IMyActor中定义的方法.

namespace MyActorClient
{using Dapr.Actors;using Dapr.Actors.Client;using MyActor.Interfaces;using System;using System.Threading.Tasks;...static async Task InvokeActorMethodWithoutRemotingAsync(){var actorType = "MyActor";var actorID = new ActorId("1");// Create Actor Proxy instance to invoke the methods defined in the interfacevar proxy = ActorProxy.Create(actorID, actorType);// Need to specify the method name and response type explicitlyvar response = await proxy.InvokeAsync<string>("SetMyDataAsync", new MyData(){PropertyA = "ValueA",PropertyB = "ValueB",});Console.WriteLine(response);var savedData = await proxy.InvokeAsync<MyData>("GetMyDataAsync");Console.WriteLine(savedData);}...
}

运行Actor

为了验证及调试 actor 服务及客户端, 我们首先需要通过Dapr CLI运行actor服务.

  1. Run Dapr Runtime via Dapr cli

    $ dapr run --app-id myapp --app-port 3000 dotnet MyActorService.dll

    在通过Dapr运行时执行MyActorService之后,确保在端口3000上发现应用程序并成功建立actor连接.

  1. INFO[0000] starting Dapr Runtime -- version  -- commitINFO[0000] log level set to: infoINFO[0000] standalone mode configuredINFO[0000] dapr id: myappINFO[0000] loaded component statestore (state.redis)INFO[0000] application protocol: http. waiting on port 3000INFO[0000] application discovered on port 3000INFO[0000] application configuration loaded2019/08/27 14:42:06 redis: connecting to localhost:63792019/08/27 14:42:06 redis: connected to localhost:6379 (localAddr: [::1]:53155, remAddr: [::1]:6379)INFO[0000] actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30sINFO[0000] actors: starting connection attempt to placement service at localhost:50005INFO[0000] http server is running on port 3500INFO[0000] gRPC server is running on port 50001INFO[0000] dapr initialized. Status: Running. Init Elapsed 19.699438msINFO[0000] actors: established connection to placement service at localhost:50005INFO[0000] actors: placement order received: lockINFO[0000] actors: placement order received: updateINFO[0000] actors: placement tables updatedINFO[0000] actors: placement order received: unlock...
  2. 运行 MyActorClient

    如果MyActorClient成功调用托管在MyActorService中的actor,它将在控制台输出.

    如果指定不同的Dapr运行时http端口(默认端口:3500),则需要在运行客户端之前设置Dapr_http_port环境变量.

    Success
    PropertyA: ValueA, PropertyB: ValueB
    

 

原文参考翻译:https://github.com/dapr/dotnet-sdk/blob/master/docs/get-started-dapr-actor.md

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TPL Dataflow组件应对高并发,低延迟要求

长话短说2C互联网业务增长&#xff0c;单机多核的共享内存模式带来的排障问题、编程困难&#xff1b;随着多核时代和分布式系统的到来&#xff0c;共享模型已经不太适合并发编程&#xff0c;因此actor-based模型又重新受到了人们的重视。---------------------------调试过多线…

abp模块生命周期设计思路剖析

abp中将生命周期事件抽象为4个接口&#xff1a;//预初始化 public interface IOnPreApplicationInitialization {void OnPreApplicationInitialization([NotNull] ApplicationInitializationContext context); }//初始化 public interface IOnApplicationInitialization {void …

.Net Core + 微信赋能企业级智能客服系统--学习笔记

摘要围绕目前需求猛增的微信及移动端企业智能客服业务&#xff0c;利用 .NET Core 的一系列优秀特性及 SignalR 模块打造全双工、跨微信/QQ/钉钉等应用平台、跨系统平台、跨终端、支持企业级并发的移动端客服系统。讲师介绍目录微信应用生态简介微信小程序基础通讯原理Senparc.…

基于docker-compose的Gitlab CI/CD实践排坑指南

长话短说经过长时间实操验证&#xff0c;终于完成基于Gitlab的CI/CD实践&#xff0c;本次实践的坑位很多&#xff0c; 实操过程尽量接近最佳实践&#xff08;不做hack, 不做骚操作&#xff09;&#xff0c;记录下来加深理解。看过博客园《docker-compose真香》一文的园友留意到…

Is It a Complete AVL Tree AVL树

思路&#xff1a; 考察的点是建立AVL树以及如何判断是否为满二叉树。 建立AVL树需要搞清楚LL、LR、RR、RL四种情况如何左旋和右旋&#xff0c;如下&#xff1a; 类型BF条件操作LLBF(root)2,BF(root->lchild)1root右旋LRBF(root)2,BF(root->lchild)-1先root->lchild左…

AcWing 删减 栈思想

思路&#xff1a; 这道题要是不卡时间复杂度&#xff0c;是道大水题&#xff0c;然而字符串的长度到了6次方&#xff0c;若使用string中的erase函数&#xff0c;看似时间复杂度不高&#xff0c;其实&#xff0c;每次删除子字符串后&#xff0c;后边的字符串需要移动到前面来&am…

读《可复制的领导力》

最近很忙&#xff0c;是特别忙&#xff0c;连上厕所的时间都在回复着各种消息&#xff0c;但还是挤时间看完了《可复制的领导力》&#xff0c;这本书也是领导推荐的。说起领导力&#xff0c;大多数人都会觉得得靠悟&#xff0c;并不能做到言传身教&#xff0c;但书名中却提到了…

AcWing 构造数组 区间合并

思路&#xff1a; 这道题第一眼来看以为是动态规划类型的题目&#xff0c;然而尝试了用dp的方法做&#xff0c;然而超时了&#xff0c;过了差不多一半的测试店&#xff0c;显示的是超时。那么应该来说动态规划是可以做的&#xff0c;但数据卡的比较严。在看其他同学的评论后&am…

为什么需要动态SQL

为什么需要动态SQL在使用 EF或者写 SQL语句时&#xff0c;查询条件往往是这样一种非常常见的逻辑&#xff1a;如果客户填了查询信息&#xff0c;则查询该条件&#xff1b;如果客户没填&#xff0c;则返回所有数据。我常常看到很多人解决这类问题时使用了错误的静态 SQL的解决办…

【好文】为什么必须学好.Net Core?怎样弯道超车新年高薪?这样做,一周就够了!(文末彩蛋)...

都2020了你还不会.Net Core&#xff1f;恕我直言&#xff0c;2020年还不会.Net Core是会被淘汰的&#xff01;12月3号&#xff0c;.Net Core3.1的LTS版正式发布&#xff0c;4年来7个正式版本和几十个Preview版本&#xff0c;热烈可见一斑&#xff01;越来越多的互联网软件公司开…

基于 Kubernetes 的基础设施即代码

11 月 9、10 号两天&#xff0c;.NET 社区第一次以“.NET 大会”为品牌在上海召开了第一届峰会&#xff0c;现场与会者达到 600 人规模。大会的第 1 天是各类演讲分享&#xff0c;第 2 天有多个动手实践课。张善友队长、 刘腾飞 和我一起策划了基于 Kubernetes 的 .NET Core 微…

Steeltoe 2.4新增代码生成工具、全新入门指南等,助力.NET微服务开发

Steeltoe框架现可帮助.NET开发人员创建云原生应用。随着其功能的扩充&#xff0c;该框架越来越受欢迎&#xff0c;下载量达到580万&#xff08;并且仍在增加&#xff09;&#xff0c;这其中大部分的功能创新都源自于用户反馈、社区贡献和.NET运行环境各方面的改进。但这些还不够…

2019 年终回顾:不忘初心,负重前行

点击上方蓝字关注“汪宇杰博客”导语2019 年就要接近尾声&#xff0c;这一年对于我来说&#xff0c;有许多有意义的事件。我成长了许多&#xff0c;并依然保持着对技术的热情。在辞旧迎新之际&#xff0c;我想回顾一下我这一年中有意义的事件与收获&#xff0c;期待与大家一起在…

【C#】设计模式的学习征途系列文章目录(2019版)

Photo &#xff1a;Design Patterns文 | Edison Zhou2017年&#xff0c;我开始系统学习设计模式&#xff0c;参考了《大话设计模式》、《设计模式的艺术》等书籍&#xff0c;并通过C#语言写了各种模式的代码示例&#xff08;已经放到了我的github上并收获了120个star&#xff0…

原创 | 为什么年终奖是一个彻头彻尾的职场圈套?

0前言之前写过几篇职场专题的文章&#xff0c;反响不错&#xff0c;也先后被不少公众号转载过&#xff0c;这几天来了不少新朋友&#xff0c;如果之前没阅读过&#xff0c;可以在后台回复“职场”2个字&#xff0c;查看系列文章。转眼又到年底了&#xff0c;不知道有多少人在心…

Blazor 机制初探以及什么是前后端分离,还不赶紧上车?

上一篇文章发了一个 BlazAdmin 的尝鲜版基于 Blazui 的 Blazor 后台管理模板 BlazAdmin 正式尝鲜&#xff0c;这一次主要聊聊 Blazor 是如何做到用 C# 来写前端的&#xff0c;传送门&#xff1a;https://www.cnblogs.com/wzxinchen/p/12057171.html飚车前需要说明的一点是&…

云原生

一、云原生概念的诞生云原生&#xff08;Cloud Native&#xff09;的概念&#xff0c;由来自Pivotal的MattStine于2013年首次提出&#xff0c;被一直延续使用至今。这个概念是Matt Stine根据其多年的架构和咨询经验总结出来的一个思想集合&#xff0c;并得到了社区的不断完善&a…

基于 Kubernetes 的 CICD 基础设施即代码

在上一篇基于 Kubernetes 的基础设施即代码一文中&#xff0c;我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊 使用的基础设施是如何使用代码描述的&#xff0c;以及它的自动化执行过程。如果要查看基于 Kubernetes 的基础设施即代码架构全图&…

Azure Arc:微软是怎么玩多云游戏的?

混合云在竞争性云提供商的基础上提供了来自云提供商的服务&#xff0c;从而使组织能够以不同方式一起使用来自不同供应商的云服务。例如&#xff0c;组织可以使用将数据存储在一个云中存储上的功能&#xff0c;而另一个云服务商则在该应用程序或数据之上运行。因此&#xff0c;…

当我们在谈 .NET Core 跨平台时,我们在谈些什么?--学习笔记

摘要.NET Framework在过去十多年在跨平台上的尝试。.NET Core跨平台的实现有何不同&#xff1f;基于 .NET Standard的平台兼容性是如何实现的&#xff1f;讲师介绍历史枷锁.NET Framework FCL CLR"跨平台"的 .NET Framework完全独立&#xff0c;各自为政复用之殇由…