通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务

  我个人认为Actor应该是Dapr里比较重头的部分也是Dapr一直在讲的所谓“stateful applications”真正具体的一个实现(个人认为),上一章讲到有状态服务可能很多同学看到后的第一反应是“不就是个分布式缓存吗”。那今天就讲讲Actor,看看这个东西到底能不能算得上有状态服务,同时由于篇幅有限,这里只会快速的过一遍Actor相关的概念,着重还是代码层面的实现

目录:
一、通过Dapr实现一个简单基于.net的微服务电商系统

二、通过Dapr实现一个简单基于.net的微服务电商系统(二)——通讯框架讲解

三、通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr

四、通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布

五、通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理

六、通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务
附录:(如果你觉得对你有用,请给个star)
一、电商Demo地址

二、通讯框架地址

  最早我接触到Actor应该是微软的Orleans框架(熟悉Actor或者Orleans的同学这一大段可以直接跳过),百度Actor关键词一大堆“通用并发编程模型”可能让人云里雾里的,其实它并不是一个特别复杂的概念。什么是并发编程?这个概念大家应该很熟悉了,现在主流的web服务器(如.netcore的kestrel或者dotnetty)几乎都是支持并行访问的,通过线程池充分调度操作系统的多线程来并行完成任务。在传统的多线程模式中如果多个线程同时访问某个数据并对其进行非幂等操作,往往是线程不安全的。

  在单应用时代我们可以很方便的通过lock关键字或者semaphore信号量或者concurrent线程安全集合或者Interlocked这样的CAS原子操作去规避多线程访问导致的数据不安全,亦或者直接采用以数据库事务为基础的乐观 or 悲观事务来实现,而一旦我们的应用由于吞吐瓶颈需要以集群的方式部署时或者分布式部署后对数据库也进行了拆分后,上面的那些方案都会失效或者会导致高昂的成本(比如数据库分布式事务协调机制)。这个时候往往需要引入一些分布式组件比如zookeeper或者redis锁来解决。这也是分布式系统比较常用的数据一致性方案。而actor则是提出了一个新的在分布式环境下解决多线程污染数据的思路。

  actor概念相对比较复杂这里就不展开了,简单粗暴的来理解就是在内存里为每一个actor对象维护了一个消息队列,当任意的请求不管该请求是来自于其他进程的线程亦或是当前进程的线程,都会将请求写入该消息队列,而Actor对象会监听该队列,当收到消息后Actor会处理该请求,在请求处理期间,外部线程会被阻塞在消息队列中,并且新的请求也会入队等待,直到actor对象完成操作后从队列里取出下一个请求处理直到整个队列为空。同时每一个actor对象在其临界区内的内存是私有的,并不会被其他线程共享,从而就实现了内存安全。这样当我们客户端发起数个请求访问一个或多个Actor对象时每个请求都会进入对应的Actor对象的消息队列(术语叫Mailboxs)并等待actor消费。同时Dapr框架会确保同一个Actor对象在同一时间在整个分布式系统中只会被激活一个实例!从而确保了你无论从分布式系统的任意角落访问某个Actor对象(user?id=1),总能得到唯一的一个实例

通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务

  Dapr框架会确保你的Actor实例永远能够被访问到(正确激活),哪怕对象在长时间未被访问后系统回收休眠亦或者在未处理的异常导致其崩溃后

  正确使用Actor唯一的要求就只有一条,由于Actor是一个内存并发模型所以不要在并发访问Actor时去做任意的可能的IO阻塞(比如读取数据库)!

  开始撸码,首先我们做一个RPC服务,看看多线程访问下的数据会是什么个情况,再对比一下Actor模式!在RPC层我们创建一个接口,代表产品服务,其有两个方法对应读取产品以及减扣库存

通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务

   接着我们在servicesample层实现一下这个服务(这里直接创建一个静态变量模拟多线程下访问共享内存数据的场景)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyyjsd.html