NET Core 分布式框架

公司物联网项目集成Orleans以支持高并发的分布式业务,对于Orleans也是第一次接触,本文就分享下个人对Orleans的理解。

这里先抛出自己的观点:Orleans 是一个支持有状态云生应用/服务水平伸缩的基于Virtual Actor 模型的.NET分布式框架。

下面我会从以下几个关键点,进行阐述:

  1. 云生应用的挑战
  2. 何为有状态/无状态
  3. 什么是 Actor 模型
  4. 什么是 Virtual Actor 模型

云生应用的挑战

在讲云生应用之前,我们来先讲讲传统应用,对于传统应用常用的三层结构如下图所示。

随着业务的发展,数据库层通常存在瓶颈,为了缓解数据库的压力,一般会优先考虑增加一层缓存层。

而随着业务的继续发展,高并发、大数据量的应用场景逐渐凸显。如果继续在单体应用的基础上进行扩展,能做的无非是增加消息队列、异步、读写分离等机制进行性能优化。总体而言,优化空间不大,但应用的整体复杂度却随着引入的新的技术框架而迅速增加,对于应用的维护,是一个潜在的定时炸弹。

这个时候你可能会想,既然单体应用单机部署不能满足需求,我可以做集群啊。通过将单体应用按照分层结构进行纵向分离,将数据库从应用服务器分离,将缓存从应用服务器分离。这样就可以对分离的各个部分进行分别部署,再借助负载均衡完成集群效应。到这一步,你的应用应该能撑一段时间了。

这个时候,如果回到业务本身去分析,对于一个复杂应用来说,通常的性能瓶颈就是几个核心服务上。如果能够对存在性能瓶颈的服务进行伸缩,既能大大提高应用的整体可用性又能提高资源的利用率。那怎么做呢?服务拆分。

云生应用就是服务拆分的结果,云生应用最大的特点就是:

  • 并行:是指同一时刻能够处理多个任务。这无可厚非,云生应用以多个服务形式提供服务,自然是支持并行的。
  • 分布式:是指一个应用/服务多次部署,以应对高并发,提升应用/服务的整体性能。

或者简单来说,云生应用通过服务拆分支持服务并行,同时各个服务能够快速伸缩以提升系统吞吐量来应对高并发的业务场景。

虽然通过服务拆分简化了整个应用的业务复杂度,但是实现的技术复杂度却只增不减。

有状态 Vs 无状态

转向云生应用我们面对的第一个难题就是:如何进行服务拆分,才能确保其能分布式部署,或者说是水平伸缩?!

有经验的同学,可能会立马想到,要将应用/服务设计为无状态的。但是这里我要向你讨教几个问题:

  1. 这个状态是指什么?
  2. 何为有状态?
  3. 何为无状态?

大家不妨先停下来思考一下。(欢迎大家在评论中阐述不同观点。)

这里,我尝试从以下两个角度来谈下自己的看法:

1. 对象

面向对象编程强调的是对现实事物的抽象和封装。通过对事物状态和行为进行抽象然后封装为对象(类),其中状态封装为类的属性、字段,将行为封装为类的方法。这个时候得到的对象是没有生命力的,因为它本质是一个抽象的结果。只有在程序运行中对类进行实例化得到一个对象的实例时,才可以说这个实例对象是有状态和行为的,因为这个状态和行为是其独自持有的,这是一个非常核心的条件。独自持有,换句话说,就是非共享成员。
独自持有非共享的成员就可以说这个对象实例是有状态的吗?
这里面你就要看清状态有状态的区别!
举个简单例子,大街上你看到一大叔开着豪车,你觉得他很富有。“开着豪车”是你即时看到的状态属性。“富有”是你的状态断言。但这个状态断言是一个假设,毕竟可能是借的嘛。
怎样才能断定“富有”就是这位大叔拥有的状态呢?很简单,假设一年365天你天天见到他开豪车,那基本八九不离十了。

所以,如果认定一个对象是否有状态,还要看其状态属性是否持久化!

如果你同意这个观点,那么哪天你看我骑个共享单车,气喘吁吁从你面前经过,就不要简单认为我是苦逼工薪族。毕竟我也是身价上千万,只是偶尔骑个车锻炼锻炼。(身价上千万,昨晚梦到的。)

所以,从对象角度看,一个对象是否有状态的充分必要条件是:

  1. 对象已实例化(处于运行时)
  2. 拥有非共享的状态属性
  3. 状态持久化

那问题来了,我们经常写的类创建的实例,是有状态的吗?

2. 应用

基于上面的总结,我们再来从应用的角度来看分析这个问题。

那应用的状态和行为是什么?
首先,只有运行中的应用才有状态和行为。基于这个前提,个人理解运行时应用的状态是应用持有的数据,行为是应用提供的功能。那应用的有无/无状态界定就要看运行时应用持有的数据能否持久化。

以简单的Web分层应用举例 。从逻辑架构上来讲应用一般分为三层,表示层、业务层和数据访问层。上层进行状态行为的封装,数据层提供数据的持久化。所以从整体的角度来看,其是一个有状态的应用。但单独来看,我们不能对每一层进行有/无状态的界定。第一,每一层不能单独运行;第二,分层的目的是为了职责的隔离,每一层负责相应职责的抽象和封装,其输出的是类文件,是对象的集合,没有生命力。

那从物理架构上来讲,Web应用可以分开两个部分进行部署:Web实例和MySQL实例。也就是说应用和数据库是可以分开部署的。这个时候Web实例就是无状态的。那我们一般常说的无状态服务其实是就是从这个拆分的角度来说的。

Actor 模型

理清完服务拆分的核心问题后,我们不得不来处理第二个棘手的问题:如何解决云生应用高并发的应用场景呢?
那首先我们需要明确处理高并发的难点在哪?第一个是高性能,第二个就是:资源竞争导致的数据一致性问题。对于第一个难点,通过水平扩展服务可以化解;对于第二个难点,一般就是采用锁机制,而对于云生分布式的应用场景下,处理手段就更加复杂,可能需要使用分布式锁,而这种做法,大大降低了应用的整体响应性能。那有没有更好的解决方案,既兼顾性能又可以确保数据一致性呢?

有,借助Actor模型。

简单来讲:Actor模型 = 状态 + 行为 + 消息。一个应用/服务由多个Actor组成,每个Actor都是一个独立的运行单元,拥有隔离的运行空间,在隔离的空间内,其有独立的状态和行为,不被外界干预,Actor之间通过消息进行交互,而同一时刻,每个Actor只能被单个线程执行,这样既有效避免了数据共享和并发问题,又确保了应用的伸缩性。

另外Actor基于事件驱动模型进行异步通信,性能良好。且位置透明,无论Actor是在本机亦或是在集群中的其他机器,都可以直接进行透明调用。

因此Actor模型赋予了应用/服务的生命力(有状态)、高并发的处理能力和弹性伸缩能力。

Virtual Actor 模型 与 Orleans

对于Actor模型,业界已经有系列的实现框架,比如Erlang、Akka。然而Actor模型作为一个偏底层的技术框架,对于开发者来说,需要有一定分布式应用的开发经验,才能用好Actor(包括Actor的生命周期管理,状态管理等等)。为了进一步简化分布式编程,微软的研究人员引入了 Virtual Actor 模型概念,简单来讲Virtual Actor模型是对Actor模型的进一步封装和抽象。
其与Actor模型的最大的区别在于,Actor的物理实例完全被抽象出来,并由Virtual Actor所在的运行时自动管理。

Orleans 就是作为一款面向.NET的Virtual Actor模型的实现框架,提供了开发者友好的编程方式,简化了分布式应用的开发成本。在Orleans中Virtual Actor由Grain来体现。

Orleans中核心优势:开发效率高、透明可伸缩。

开发效率高具体表现为:

  1. 面向对象的编程范式去实现Grain
  2. Grain单线程执行
  3. Grain透明实例化:换句话说,应用无需关注Actor实例的创建、销毁,可以直接调用Actor提供的方法。Actor的生命周期由Virtual Actor 运行时进行管理,类似GC,可以把Actor理解为完全托管的状态。
  4. Grain位置透明:Actor之间通过持有彼此的逻辑引用(非实例引用)进行相互调用,而不需要知道Actor所处的实际位置。
  5. Grain状态透明存储
  6. 异常的自动传播

透明可伸缩体现为:

  1. 应用状态的隐式细粒度划分
  2. 自适应的资源管理:Grain的生命周期完全由Orleans 运行时托管。
  3. 多路通信:Grain的位置透明,Grain之间通过一组固定的TCP链接进行多路复用来进行消息传递。
  4. 高效调度
  5. 显式异步

最后

这篇文章,就简单写到这里,对于Orleans的详细介绍后续会结合实际项目输出更系统的应用细节,下次再见。

有状态 Vs 无状态的更多相关文章

  1. http协议和web应用有状态和无状态浅析

    http协议和web应用有状态和无状态浅析 (2013-10-14 10:38:06) 转载▼ 标签: it   我们通常说的web应用程序的无状态性的含义是什么呢? 直观的说,“每次的请求都是独立的 ...

  2. REST有状态与无状态的理解

    1. 什么是REST? REST(REpresentation State Transfer)表述性状态传递,是一种软件架构风格,是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可 ...

  3. SSH深度历险(三) EJB Session Bean有状态和无状态的差别与联系

    刚開始对两种sessionbean存在误解.觉得有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用.而觉得无状态是每次调用实例化一次,不保留用户信息.细致分析并用实践检验后,会发现,事实 ...

  4. SSH深度历险(三) EJB Session Bean有状态和无状态的区别与联系

    刚开始对两种sessionbean存在误解,认为有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用,而认为无状态是每次调用实例化一次,不保留用户信息.仔细分析并用实践检验后,会发现,事实 ...

  5. HTTP 无状态啊无状态啊

    无状态的根本原因 根本原因是:因为,HTTP协议使用的是Socket套接字TCP连接的,每次监听到的套接字连接是不可能一个个保存起来的.(很消耗资源,假如一个人服务器只保存一个通信连接,一万个岂不是要 ...

  6. 线程安全,有状态,无状态的对象<转>

    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.另外 ...

  7. IPv6系列-彻底弄明白有状态与无状态配置IPv6地址

    深入研究自动分配IPv6地址的Stateless(无状态)与Stateful(有状态)方式 小慢哥的原创文章,欢迎转载 目录 ▪ 一. Link-Local Address的生成方式 ▪ 二. Glo ...

  8. Kubernetes 有状态与无状态介绍

    Kubernetes 有状态与无状态介绍 无状态:deployment - 认为所有pod都是一样的,不具备与其他实例有不同的关系. - 没有顺序的要求. - 不用考虑再哪个Node运行. - 随意扩 ...

  9. JavaEE(8) - 本地和远程调用的有状态以及无状态Session EJB

    1. 使用NetBeans开发Session Bean #1. 创建项目:File-->New Project-->Java EE-->EJB Module #2. 在项目中创建Se ...

随机推荐

  1. Selenium+java - 关于富文本编辑器的处理

    什么是富文本编辑器? 富文本编辑器,Rich Text Editor, 简称 RTE, 是一种可内嵌于浏览器,所见即所得的文本编辑器.具体长啥样,如下图: 通过自动化操作富文本编辑器 模拟场景:在富文 ...

  2. python3中的数字类型

    今天在学校机房刷python题时发现自己对python中的数字类型不理解,回寝室后百度一下. 现在做一个总结. python中的数字类型有: 整数,布尔值,复数,科学计数法,浮点数 1,整数,大小没有 ...

  3. 资源推荐:PPT快闪资源合集附配套字体下载

    样例ppt下载 搜索公众号“拒收”或扫码关注公众号 回复关键字“快闪ppt”获取全部福利 本公众号只出精品,拒收劣质 或者点击菜单链接获取获取全部资源

  4. cl_demo_output=>display 介绍

    Methods of CL_DEMO_OUTPUT PS:自己测试是display后的内表不能带表头. 类CL_DEMO_OUTPUT 在示例程序中创造了很多简单的数据输出的方法而不需要经典的list ...

  5. .net core入门-跨域访问配置

    Asp.net Core 跨域配置   一般情况WebApi都是跨域请求,没有设置跨域一般会报以下错误 No 'Access-Control-Allow-Origin' header is prese ...

  6. 自定义Visual Studio调试器中的对象显示方式

    你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...

  7. ls用法

    常用 ll -h  大小直接显示K,M,G 语 法:ls [-1aAbBcCdDfFgGhHiklLmnNopqQrRsStuUvxX][-I <范本样式>][-T <跳格字数> ...

  8. Python爬取620首虾米歌曲,揭秘五月天为什么狂吸粉?!

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: CDA数据分析师 PS:如有需要Python学习资料的小伙伴可以加点 ...

  9. Linux网络——配置防火墙的相关命令

    Linux网络——配置防火墙的相关命令 摘要:本文主要学习了如何在Linux系统中配置防火墙. iptables命令 iptables准确来讲并不是防火墙,真正的防火墙是运行于系统内核中的netfil ...

  10. PHP setcookie 网络函数

    setcookie - 发送 Cookie. 语法: setcookie ( string $name [, string $value = "" [, int $expire = ...