.netcore dapr micro-micro-Services dapr service .netcore sdk entry

dapr micro-entry service .netcore sdk

 

Actors Getting Started

prerequisites

Outline

This document describes how to create an Actor on the client application (MyActor) and call its methods.

MyActor --- MyActor.Interfaces
         |
         +- MyActorService
         |
         +- MyActorClient
  • Interface project (\ MyActor \ MyActor.Interfaces). This project contains the participant interface definition. Actor interfaces can be defined in any item name. Interface defines the client shared actor actor contract implementation and call the actor. Because the client project may depend on it, so it makes sense generally centrally defined in the program to achieve the separation of the actor.

  • actor Services (\ MyActor \ MyActor service). This project implements the core ASP.Net web service, which will host the participants. It contains the implementation of actor MyActor.cs. actor achieved derives from a base class that implements the interface and the type of actor MyActor.interfaces defined in the project. actor must also implement a class constructor, the constructor takes ActorService ActorId and examples, and passes them to the base class actor.

  • actor client project (\ MyActor \ MyActor client) This item contains realized actor client, the client calls MyActor method actor defined in the interface.

Step 1 - Create Actor Interface

Actor interface defines the client shared Actor Actor contract implementation and calls Actor.

Actor interface definition is as follows:

  • Actor interface must inherit  Dapr.Actors.IActor the interface
  • Actor must be a method return type of Task or Task <object>
  • Actor method can have at most one parameter

Create a project and add dependencies

Copy the code
# Create Actor Interfaces
dotnet new classlib -o MyActor.Interfaces

cd MyActor.Interfaces

# Add Dapr.Actors nuget package
dotnet add package Dapr.Actors
Copy the code

Upgrade project to .NET Core 3.0

Csproj file netcore update to .NET Core 3.0

Copy the code
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Dapr.Actors" Version="0.1.0-preview01" />
  </ItemGroup>

</Project>
Copy the code

Achieve IMyActor Interface

And interfaces defined IMyActor MyData data objects.

Copy the code
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}";
        }
    }
}
Copy the code

Step 2 - Create Actor services

Dapr using ASP.NET web service hosting Actor services. This section will implement  IMyActor the interface and register Actor to Dapr runtime.

Create a project and add dependencies

Copy the code
# 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
Copy the code

Add to realize Actor

IMyActor implement an interface and derived from Dapr.Actors.Actor class. The following example also demonstrates how to use Actor reminder. For Actor, using reminders, it must come from IRemindable. If you do not intend to use the reminder function can be implemented to skip the display in the following code IRemindable and reminders particular method.

Copy the code
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;
        }
    }
}
Copy the code

Use an explicit type name actor

By default, the client saw the actor's "type" is the name of the actor to achieve the derived class. If desired, it can be attached to the actor by actor implementation class property attribute to specify the name of an explicit type.

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

Actor registration to run Dapr

将 MyActor Sign up to the actor runtime and set the local host port ( https://localhost:3000), DAPR Runtime port call by the actor.

Copy the code
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}/");
Copy the code

Update Startup.cs

Copy the code
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();
            }
        }
    }
Copy the code

Step 3 - Add Client

Create a simple console application to call actor services. Dapr SDK provides proxy client to call Actor Actor Actor methods defined in the interface.

Create a project and add dependencies

Copy the code
# 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
Copy the code

Actor Actor use remote service invocation method

We recommend using a local agent to actor instance, because ActorProxy.Create <IMyActor> (actorID, actorType) returns a strongly typed actor instance to set up a remote procedure call.

Copy the code
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);
        }
    ...
}
Copy the code

Actor Non-call method to remotely

If the Actor method takes at most one parameter, you can call the method without remoting Actor (directly or by using a helper method ActorProxy http provided). Actor from the client runtime deserializing incoming request body parameters and used to invoke the method Actor method. When non-remote call processing, the Actor method parameters and return types are serialized, deserialized JSON.

ActorProxy.Create(actorID, actorType) Examples ActorProxy return and allow the original http client The method defined in IMyActor end call.

Copy the code
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);
        }
    ...
}
Copy the code

Run Actor

In order to verify and debug actor and client service, we first need to run actor Dapr CLI service.

  1. Run Dapr Runtime via Dapr cli

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

    After running through Dapr when executed MyActorService, and to ensure that find application successfully established actor connections on port 3000.

    Copy the code
    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
     ...
    
    Copy the code
  2. Run MyActorClient

    Managed actor in MyActorService if MyActorClient in a successful call, it will output in the console.

    If you specify a different Dapr runtime http port (default port: 3500), you need to set Dapr_http_port environment variable before running the client.

    Success
    PropertyA: ValueA, PropertyB: ValueB
    

 

Original Reference translation: https://github.com/dapr/dotnet-sdk/blob/master/docs/get-started-dapr-actor.md

Actors Getting Started

prerequisites

Outline

This document describes how to create an Actor on the client application (MyActor) and call its methods.

MyActor --- MyActor.Interfaces
         |
         +- MyActorService
         |
         +- MyActorClient
  • Interface project (\ MyActor \ MyActor.Interfaces). This project contains the participant interface definition. Actor interfaces can be defined in any item name. Interface defines the client shared actor actor contract implementation and call the actor. Because the client project may depend on it, so it makes sense generally centrally defined in the program to achieve the separation of the actor.

  • actor Services (\ MyActor \ MyActor service). This project implements the core ASP.Net web service, which will host the participants. It contains the implementation of actor MyActor.cs. actor achieved derives from a base class that implements the interface and the type of actor MyActor.interfaces defined in the project. actor must also implement a class constructor, the constructor takes ActorService ActorId and examples, and passes them to the base class actor.

  • actor client project (\ MyActor \ MyActor client) This item contains realized actor client, the client calls MyActor method actor defined in the interface.

Step 1 - Create Actor Interface

Actor interface defines the client shared Actor Actor contract implementation and calls Actor.

Actor interface definition is as follows:

  • Actor interface must inherit  Dapr.Actors.IActor the interface
  • Actor must be a method return type of Task or Task <object>
  • Actor method can have at most one parameter

Create a project and add dependencies

Copy the code
# Create Actor Interfaces
dotnet new classlib -o MyActor.Interfaces

cd MyActor.Interfaces

# Add Dapr.Actors nuget package
dotnet add package Dapr.Actors
Copy the code

Upgrade project to .NET Core 3.0

Csproj file netcore update to .NET Core 3.0

Copy the code
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Dapr.Actors" Version="0.1.0-preview01" />
  </ItemGroup>

</Project>
Copy the code

Achieve IMyActor Interface

And interfaces defined IMyActor MyData data objects.

Copy the code
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}";
        }
    }
}
Copy the code

Step 2 - Create Actor services

Dapr using ASP.NET web service hosting Actor services. This section will implement  IMyActor the interface and register Actor to Dapr runtime.

Create a project and add dependencies

Copy the code
# 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
Copy the code

Add to realize Actor

IMyActor implement an interface and derived from Dapr.Actors.Actor class. The following example also demonstrates how to use Actor reminder. For Actor, using reminders, it must come from IRemindable. If you do not intend to use the reminder function can be implemented to skip the display in the following code IRemindable and reminders particular method.

Copy the code
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;
        }
    }
}
Copy the code

Use an explicit type name actor

By default, the client saw the actor's "type" is the name of the actor to achieve the derived class. If desired, it can be attached to the actor by actor implementation class property attribute to specify the name of an explicit type.

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

Actor registration to run Dapr

将 MyActor Sign up to the actor runtime and set the local host port ( https://localhost:3000), DAPR Runtime port call by the actor.

Copy the code
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}/");
Copy the code

Update Startup.cs

Copy the code
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();
            }
        }
    }
Copy the code

Step 3 - Add Client

Create a simple console application to call actor services. Dapr SDK provides proxy client to call Actor Actor Actor methods defined in the interface.

Create a project and add dependencies

Copy the code
# 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
Copy the code

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

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

Copy the code
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);
        }
    ...
}
Copy the code

非远程方式调用 Actor 方法

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

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

Copy the code
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);
        }
    ...
}
Copy the code

运行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连接.

    Copy the code
    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
     ...
    
    Copy the code
  2. 运行 MyActorClient

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

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

    Success
    PropertyA: ValueA, PropertyB: ValueB
    

 

Original Reference translation: https://github.com/dapr/dotnet-sdk/blob/master/docs/get-started-dapr-actor.md

Guess you like

Origin www.cnblogs.com/Leo_wl/p/12324875.html