dapr微服务.netcore sdk入门

Actors入门

先决条件

概述

本文档描述如何在客户端应用程序上创建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.Interfaces

cd 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 MyActorService

cd 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 name
                data);      // 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 reminder
                null,                      // User state passed to IRemindable.ReceiveReminderAsync()
                TimeSpan.FromSeconds(5),   // Time to delay before invoking the reminder for the first time
                TimeSpan.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 timer
                this.OnTimerCallBack,       // Timer callback
                null,                       // User state passed to OnTimerCallback()
                TimeSpan.FromSeconds(5),    // Time to delay before the async callback is first invoked
                TimeSpan.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 type
                    actorRuntime.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 MyActorClient

cd 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 Service
            var 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 interface
            var proxy = ActorProxy.Create(actorID, actorType);
            // Need to specify the method name and response type explicitly
            var 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连接.

    INFO[0000] starting Dapr Runtime -- version  -- commit
     INFO[0000] log level set to: info
     INFO[0000] standalone mode configured
     INFO[0000] dapr id: myapp
     INFO[0000] loaded component statestore (state.redis)
     INFO[0000] application protocol: http. waiting on port 3000
     INFO[0000] application discovered on port 3000
     INFO[0000] application configuration loaded
     2019/08/27 14:42:06 redis: connecting to localhost:6379
     2019/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: 30s
     INFO[0000] actors: starting connection attempt to placement service at localhost:50005
     INFO[0000] http server is running on port 3500
     INFO[0000] gRPC server is running on port 50001
     INFO[0000] dapr initialized. Status: Running. Init Elapsed 19.699438ms
     INFO[0000] actors: established connection to placement service at localhost:50005
     INFO[0000] actors: placement order received: lock
     INFO[0000] actors: placement order received: update
     INFO[0000] actors: placement tables updated
     INFO[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

原文地址:https://www.cnblogs.com/migomiddle/p/12055454.html

时间: 2024-10-22 08:26:33

dapr微服务.netcore sdk入门的相关文章

微服务SpringCloud+Docker入门到高级实战

第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧2.技术选型和学后水平简介:课程所需基础和技术选型讲解,学完课程可以到达怎样的程度, 第二章 架构演进和分布式系统基础知识 1.传统架构演进到分布式架构简介:讲解单机应用和分布式应用架构演进基础知识 (画图)2.微服务核心基础讲解简介:讲解微服务核心知识 :网关.服务发现注册.配置中心.链路追踪.负载均衡器.熔断3.常见的微服务框架简介:讲解常用的微服务框架4.微服务下

微服务和SpringCloud入门

微服务是什么 微服务的核心是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底去耦合,每个微服务提供单个业务功能的服务,一个服务做一件事情,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够进行单独启动和销毁,可以拥有独立的数据库. 微服务与微服务架构的区别 微服务:它强调的事服务的大小,它关注的是某个点,是具体解决某一个问题/提供落地对应服务的一个服务应用 微服务架构:它是一种架构模式,它提成将单一应用程序划分成一组小的服务,服务之间相互配合协调,为服务提供最终价值.每个服务运行在

微服务SpringCloud+Docker入门到高级实战(教程详情)

第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧 2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可以到达怎样的程度, 1.IDEA JDK8 Maven SpringBoot基础 Linux 2.理解掌握并开发SpringCloud里面主流架构和组件的基础使用,还有部分源码原理的理解 3.掌握学习的技巧和解决问题的思路 第二章 架构演进和分布式系统基础知识 1.传统架构演进到分布式架构 简介:讲

微服务SpringCloud+Docker入门到高级实战(目录)

第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可以到达怎样的程度, 第二章 架构演进和分布式系统基础知识 1.传统架构演进到分布式架构 简介:讲解单机应用和分布式应用架构演进基础知识 (画图)2.微服务核心基础讲解 简介:讲解微服务核心知识 :网关.服务发现注册.配置中心.链路追踪.负载均衡器.熔断3.常见的微服务框架 简介:讲解常用的微服务框架4

微服务Spring Cloud 入门

什么是微服务? 微服务就是把原本臃肿的一个项目的所有模块拆分开来并做到互相没有关联,甚至可以不使用同一个数据库.   比如:项目里面有User模块和Power模块,但是User模块和Power模块并没有直接关系,仅仅只是一些数据需要交互,那么就可以吧这2个模块单独分开来,当user需要调用power的时候,power是一个服务方,但是power需要调用user的时候,user又是服务方了, 所以,他们并不在乎谁是服务方谁是调用方,他们都是2个独立的服务,这时候,微服务的概念就出来了. 微服务和分

SpringCloud从入门到进阶(四)——使用SpringBoot搭建微服务

内容 SpringBoot整合SpringCloud的Eureka.Zuul等组件,快速实现简单易懂且具有服务熔断.负载均衡的分布式架构1.0,体验微服务的魅力. 版本 IDE:IDEA 2017.2.2 x64 JDK:1.8.0_171 manve:3.3.3 SpringBoot:1.5.9.RELEASE SpringCloud:Dalston.SR1 适合人群 ?Java开发人员 说明 转载请说明出处:SpringCloud从入门到进阶(四)--使用SpringBoot搭建微服务 参考

【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发

<ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-translator/ "微服务"的概念在 2014 年正式提出之后,越来越多的团队开始用它来设计自己的业务系统,各种微服务框架和开发过程管理方法也同时兴起.不断成熟.微服务设计方法清晰地定义了各个开发团队的业务边界,微服务框架以不同的方式实现了服务之间的协作与集成,根据康威定律我们可以推导这

微服务系列教程

视频课程包含:微服务精品课程包含Spring Cloud基础视频教程.Spring Cloud高级教程+项目实战.Spring boot入门教程.Spring boot进阶教程.Spring Ecosystem 微服务相关.Spring Boot 入门 IDEA 版本.Spring Boot实战与原理分析视频课程.docker构建微服务.docker入门.docker进阶.docker解析及轻量级PAAS平台演练等视频教程+项目源码!135G这里给大家按照一定思路整理了全套微服务视频教程,微服务

微服务的入门级微框架Spring Boot快速入门

详情请交流  QQ  709639943 00.微服务的入门级微框架Spring Boot快速入门 00.基于java的微信公众号二次开发视频教程 00.leetcode 算法 面试 00.北风网 零基础到数据(大数据)分析专家-首席分析师 00.快速上手JMeter 00.Jmeter 00.2017年Java web开发工程师成长之路 00.R语言速成实战 00.R语言数据分析实战 00.Python+Django+Ansible Playbook自动化运维项目实战 00.Java深入微服务