Dapr专题之06Actors

9 篇文章 2 订阅
4 篇文章 0 订阅

#Dapr Actors



提示:以下是本篇文章正文内容,下面案例可供参考

Actors简介以及优势

  • 是一种单线程执行的工作模式

  • 避免代码里显示lock

  • 避免死锁,避免性能问题

  • 使并发编程简单


调用终结点

http://localhost:<dapr-port>/v1.0/actors/<actorType>/<actorId>/
  • <dapr-port>:Dapr正在侦听的HTTP端口
    
  • <actorType>:执行组件类型。
    
  • <actorId>:要调用的特定参与者的ID。
    

代码编写

  1. 新建类库Common,引入Nuget包:
    Dapr.Actors
    Dapr.Actors.AspNetCore

  2. 新建接口IWorkflowActor,写入以下代码:

     public interface IWorkflowActor : IActor
     {
         Task<bool> Approve();
     }
    
  3. BackEnd 引用Common,新建Actors文件夹,定义WorkflowActor,实现IWorkflowActor

      public class WorkflowActor : Actor, IWorkflowActor
      {
          public WorkflowActor(ActorHost host) : base(host)
          {
          }
    
      public async Task<bool> Approve()
      {
          await StateManager.AddOrUpdateStateAsync(Id.ToString(), "approve", (key, currentStatus) => "approve");
          return true;
      }
    }
    
  4. 注册Actors,映射Actors路由

     	builder.Services.AddActors(options =>
     	{
     	    options.Actors.RegisterActor<WorkflowActor>();
     	});
    
     	app.MapActorsHandlers();
    
    
  5. FrontEnd引入Common,并新建ActorsClientController,添加以下接口

    [HttpGet("{orderId}")]
    public async Task<ActionResult> ApproveAsync(string orderId)
    {
        var actorId = new ActorId("actorprifix-" + orderId);
        var proxy = ActorProxy.Create<IWorkflowActor>(actorId, "WorkflowActor");
    
        return Ok(await proxy.Approve());
    }
    

运行与测试

  • 启动BackEnd
    dapr run --dapr-http-port 3511 --app-port 5000 --app-id backend dotnet  .\BackEnd\bin\Debug\net6.0\BackEnd.dll --app-ssl
    
  • 启动FrontEnd
    dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net6.0\FrontEnd.dll
    

调用API可以看到成功返回true:
http://localhost:5001/api/ActorsClient/123
![在这里插入图片描述](https://img-blog.csdnimg.cn/dd54cdeaa0b6439b953190e9b45ec24f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVG9t5piv5Y-q5aW954yr,size_12,color_FFFFFF,t_70,g_se,x_16

Redis里面也可以看到状态变为了approve
在这里插入图片描述

Timer和Reminders

  • timer和reminder可以设置后台定时触发Actor,两者区别在于,Timer的数据是不会持久化的且只能作用于激活状态的Actor,Reminders则反之。

  • 代码实现

    1. 在IWorkflowActor中声明如下方法
       Task RegisterTimer();
       Task UnregisterTimer();
       Task RegisterReminder();
       Task UnregisterReminder();
      
    2. 在WorkflowActor中继承IRemindable并实现以下方法
      public Task RegisterTimer()
      {
             var serializedTimerParams = JsonSerializer.SerializeToUtf8Bytes("now is " + DateTime.Now.ToString());
             //TestTimer 注册进Actor的名称
             //nameof(this.TimerCallback)  注册进Actor的方法
             //serializedTimerParams 注册进Actor的方法的参数
             //TimeSpan.FromSeconds(3) 多长时间后第一次执行
             //TimeSpan.FromSeconds(3) 间隔多长时间执行
             return this.RegisterTimerAsync("TestTimer", nameof(this.TimerCallback), serializedTimerParams, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3));
      }
      
      public async Task TimerCallback(byte[] data)
      {
          var stateKey = "nowtime";
          var content = JsonSerializer.Deserialize<string>(data);
          _logger.LogInformation(" ---------" + content);
          await this.StateManager.SetStateAsync<string>(stateKey, content);
      }
      
      public Task UnregisterTimer()
      {
        //从Actor中注销
          return this.UnregisterTimerAsync("TestTimer");
      }
      
      public async Task RegisterReminder()
      {
          await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
      }
      
      public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
      {
          var stateKey = "nowtime";
          var content = "now is " + DateTime.Now.ToString();
          _logger.LogInformation(" reminder---------" + content);
          await this.StateManager.SetStateAsync<string>(stateKey, content);
      }
      
      public Task UnregisterReminder()
      {
          return this.UnregisterReminderAsync("TestReminder");
      }
      
      
    3. 在ActorsClientController中新增以下接口
      [HttpGet("timer/{orderId}")]
      public async Task<ActionResult> TimerAsync(string orderId)
      {
          var actorId = new ActorId("actorprifix-" + orderId);
          var proxy = ActorProxy.Create<IWorkflowActor>(actorId, "WorkflowActor");
          await proxy.RegisterTimer();
          return Ok("done");
      }
      
      [HttpGet("unregist/timer/{orderId}")]
      public async Task<ActionResult> UnregistTimerAsync(string orderId)
      {
          var actorId = new ActorId("actorprifix-" + orderId);
          var proxy = ActorProxy.Create<IWorkflowActor>(actorId, "WorkflowActor");
          await proxy.UnregisterTimer();
          return Ok("done");
      }
      
      [HttpGet("reminder/{orderId}")]
      public async Task<ActionResult> ReminderAsync(string orderId)
      {
          var actorId = new ActorId("actorprifix-" + orderId);
          var proxy = ActorProxy.Create<IWorkflowActor>(actorId, "WorkflowActor");
          await proxy.RegisterReminder();
          return Ok("done");
      }
      
      [HttpGet("unregist/reminder/{orderId}")]
      public async Task<ActionResult> UnregistReminderAsync(string orderId)
      {
          var actorId = new ActorId("actorprifix-" + orderId);
          var proxy = ActorProxy.Create<IWorkflowActor>(actorId, "WorkflowActor");
          await proxy.UnregisterReminder();
          return Ok("done");
      }
      

启动并测试

  • 启动BackEnd
    dapr run --dapr-http-port 3511 --app-port 5000 --app-id backend dotnet  .\BackEnd\bin\Debug\net6.0\BackEnd.dll --app-ssl
    
  • 启动FrontEnd
    dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net6.0\FrontEnd.dll
    

测试timer:
http://localhost:5001/api/ActorsClient/timer/123
在这里插入图片描述

查看Redis中的值:
![在这里插入图片描述](https://img-blog.csdnimg.cn/09735c46a2c348d29a7d344f3ae2f392.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVG9t5piv5Y-q5aW954yr,size_20,color_FFFFFF,t_70,g_se,x_16
在此处,我们可以把BackEnd 重启一下,可以发现timer不会触发,也验证了文章开头所说的timer不会持久化

测试reminder:
http://localhost:5001/api/ActorsClient/reminder/123
在这里插入图片描述

查看Redis中的值:
在这里插入图片描述

在此处,我们同样把BackEnd 重启一下,可以发现reminder还是会触发,验证了reminder会进行数据持久化操作


总结

以上就是这次要给大家分享的内容,本文介绍了Dapr中关于Actors的相关内容,下次将给大家介绍Dapr中的绑定,欢迎各位朋友点赞收藏,同时希望本文能够给大家带来一丝帮助与启发。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值