命令式和声明式,哪个才是你的菜
本文转自微信号EAWorld。扫描下方二维码,关注成功后,回复“普元方法+”,将会获得热门课堂免费学习机会!
今天的主题是讨论一下“命令式”思想和“声明式”思想在分布式系统和微服务架构运维中的应用。
主要大纲:
1. “命令式”和“声明式”的概念
2. 命令式思想在分布式系统和微服务架构中遇到的困境
3. 以Kubernetes的设计思想为例,介绍声明式思想的优势
4. 普元的实践
“命令式”和“声明式”的概念
“命令式”和“声明式”这两个概念最初来自于编程语言,这两个概念并不常见,所以我们首先将他们明确一下。
第一个是“命令式”:
“命令式”有时也被称作“指令式”,好像有一个是台湾翻译,我不确定是哪一个了。“命令式”强调的是how,如果你是在写命令式的程序,那么你将step-by-step的告诉计算机如何完成一项工作,大多数的程序都是这样的。
在命令式场景下,计算机是不具备“智能”的,只是很机械的完成你交代的事情,至于结果如何,要看你的水平。就像上图,煎饼好吃不好吃、会不会糊锅,要看厨师对原料和火候的掌握。
另一个是“声明式”:
“声明式”有时也被成为“描述式”或者“申明式”,为告诉计算机你想要什么,“声明”你想要的what,由计算机自己去设计执行路径,需要计算机或者是“运行时”具备一定的“智能”。在这种情况下,计算机显然不会实现所有你想要的what,用专业术语说就是“非图灵完备”,但是针对特定的任务,“声明式”要远比“命令式”方便,其实大多数声明式语言都是针对特定任务的领域专用语言,即DSL。当然,随着深度学习驱动的自动编程技术的兴起,我们有可能在任意领域使用“声明式”完成任务,这是后话,暂且不提。
最常见的声明式语言就是SQL—— 告诉计算机你想要的结果集,SQL语言的运行时,即数据库,帮你设计获取这个结果集的执行路径,并返回结果集。众所周知,使用SQL语言获取数据,要比自行编写处理过程去获取数据容易的多。
下面是一个最简单的例子:
在这个例子里我们可以看到,使用其他通用语言“命令式”的完成查询,要比使用SQL语言“声明式”的完成查询复杂的多。在数据量很大的时候两种方法的复杂度差距会更加明显,数据库可以帮助你收集数据分布的统计信息、维护索引和选择最佳执行路径,以保证查询性能,如果你自行编码完成这些工作,那代码量会有成千上万行。
“声明式”虽然为一个编程语言的概念,但是也可以上升到一个比较高的层面,作为一个设计软件的思想或思路,就好像你可以使用“命令式”的C语言,编写一个可以“声明式”使用的数据库一样。
但是我们很少使用“声明式”思想去设计软件。下面是我能想到的几个原因:
最重要的原因是第三个,归纳和提取完备的what,是件很困难、很技术化的工作,令人望而却步。
但是在很多特定的领域,我们往往更加喜欢实现“声明式”思想的工具,比如前面提到的SQL语言。
原因也很简单,因为这些工具的编写者,已经把实践“声明式”思想的最大障碍—— 归纳和提取what,替你完成了。
命令式思想在分布式系统和微服务架构中遇到的困境
现在我们跳出编程的概念,看下“声明式”思想在系统和微服务架构的运维还有DevOps等领域的应用。
首先看一个运维故事:
再看另外一个运维故事:
开个小玩笑,这里不是黑Puppet,也不是鼓吹Docker,我想表达的是,如果你以“命令式”的思路,编写一个过程化的脚本去部署应用,很可能会发生意想不到的事情,造成部署失败;而如果以“声明式”的思路,去制作和部署一个Docker镜像,那么成功率将大大提高。当然,Puppet也支持“声明式”,Docker也可以按“命令式”去使用,比如不太友好的Entrypoint脚本,但是这些都不是重点。
重点是:使用“命令式”思路去部署一个分布式系统或者微服务架构,已经变得非常困难。
比如部署下面这个系统:
“命令式”运维存在这下述问题,这些问题在分布式系统和微服务架构中日趋严重。
在分布式系统和微服务架构中,edge case更加复杂,环境更加动态,想在脚本中处理这些问题,你需要成为一个事无巨细的绝顶高手。如果同时还想实现部署结果的一致性、事务性和版本化,那简直是不可能完成的任务,就好像只是为了查询一笔数据,却要去编写一个数据库。
如果使用“声明式”的思路,问题则简单的多:
“声明式”运维的表现,就是编写一个配置文件,描述想要的部署结果,然后由平台解析这个配置文件并自动生成这个部署结果。描述部署结果的配置文件比过程化的脚本更加易于理解,可以由开发人员自行编写。由开发人员参与的Ops,才叫DevOps。
配置文件一目了然,多人维护不是问题,有错误也很容易被发现。配置文件本身就是文档。部署结果为配置文件所描述,如果达不到这个结果,那么部署失败并回退到部署之前的状态,所以部署天然具备了一致性和事务性。
当然,上述优势需要平台去保证,Kubernetes就是这样的一个平台。
以Kubernetes的设计思想为例,介绍声明式思想的优势
接下来就以Kubernetes为例,说明一下平台软件的“声明式”设计思想。
Kubernetes非常强调声明式思想,在其文档的第一篇就明确提出:
使用Kubernetes时,用户不需要去定义do A then B then C这种workflow,而是直接去描述一个desired state,然后Kubernetes帮助用户去达到这个state。至于如何达到这个state,用户不必关心。这种设计使Kubernetes更加易用和健壮,更具弹性和扩展性。
在Kubernetes的设计原则中,也把Declarative列在首位。
State your desired results, let the system actuate.
Kubernetes实现了多个Control Loop,观测系统的运行状态,如果偏离了预期状态,Kubernetes会自动进行校正。
举一个简单的例子,Kubernetes会维护一个集群系统内的可用节点数,使其等于用户的定义数量,如果有节点发生故障,Kubernetes会自行产生新节点替换故障节点,以保证可用节点数不变。
“声明式”思想在分布式系统和微服务架构中如此重要,所以我们的一位英国小伙伴在办公桌上钉了这样一个纸条时刻提醒自己:
普元的实践
可是说归说,做归做,我们该如何去实践“声明式”思想呢?
普元将“声明式”思想贯彻到了数字化企业云平台的开发工作中,与此同时,普元还有一个秘密武器,普元前些年做了一个很牛的元数据管理产品,现在把它用在了声明信息的管理上,以高效管理声明信息,帮助实现大规模分布式系统和微服务架构的“声明式”运维工作。
最后,我们有一个OneMore Thing,是声明式思想的一个延伸概念 —— Choreography。
在前面提到的Whatis Kubernetes文档中,说“Kubernetes不仅是一个orchestration system”,而是“more akin tochoreography”。那么orchestration和choreography这两个概念代表什么呢?
Orchestration的本意是乐队指挥:
Choreography的本意是舞蹈编舞:
这两个概念的最大区别就是,乐队指挥是个中央控制点,而舞蹈中是不存在这样一个控制点的—— 舞蹈演员根据舞伴的动作来确定自己的下一个动作。
这两个概念用到IT中,也是非常的贴切,差异就在系统中有无乐队指挥那样的中央控制点。
可以看到,Orchestration是由一个中央引擎执行一个工作流,来达到一个预期状态,更贴近“命令式”概念;而Choreography则定义了交互协议—— 参与方根据相关方的动作来确定自己的下一个动作,来达到一个预期状态,更贴近“声明式”概念。
所以在Whatis Kubernetes中,特别强调Kubernetes的实践思路是more akin to choreography。
另外,很多文章将Orchestration翻译为“编排”,其实并不准确。
在大规模的分布式系统和微服务架构中,是很难实现一个“上帝视角”的中央控制点的,所以在实践“声明式”思想的时候,要时刻记得choreography。
今天的分享就到这里,谢谢大家。
关于作者:
宋潇男
EAII-企业架构创新研究院 专家委员
现任普元云计算架构师,曾在华为负责云计算产品与解决方案的规划和管理工作。曾负责国家电网第一代云资源管理平台以及中国银联基于OpenStack的金融云的技术方案、架构设计和技术原型工作。
关于EAWorld
微服务,DevOps,元数据,企业架构原创技术分享,EAii(Enterprise Architecture Innovation Institute)企业架构创新研究院旗下官方微信公众号。
扫描下方二维码,关注成功后,回 复“普元方法+”,将会获得热门课堂免费学习机会!
微信号:EAWorld,长按二维码关注。
命令式和声明式,哪个才是你的菜相关推荐
- Jenkins 流水线语法 02 片段生成器和声明式语法生成器
Pipeline 开发工具 选择任意pipeline类型的作业,点击"流水线语法"即可进入pipeline开发工具页面. 片段生成器 有些pipeline代码不是自己去写的,是要工 ...
- 编程式事务和声明式事务浅析
事务管理 在spring中,事物管理一般分为两类,编程式事务管理和声明式事务管理. 编程式事务管理,一般我们使用TransactionTemplate来实现. 声明式事物管理本质上是spring AO ...
- [事务] 编程式事务和声明式事务的优缺点
事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种. 关于事务的基础知识,如什么是事务,数据库事务以及Spring事务的ACID.隔离级别. ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- spring编程式和声明式事务控制
可优先参考:@Transactional Spring 事务的深入学习与使用[两万字] 1. 编程式事务控制 @Autowired private RoleMapper roleMapper;@Aut ...
- react 编程式导航和声明式导航
react中的两种路由导航方法[声明式导航.编程式导航] 主要使用的方法 [Link , NavLink , props, useHistory() ,Route],推荐使用前四个方法,更简单高效 1 ...
- Spring编程式和声明式事务实例讲解
历史回顾: 可能是最漂亮的Spring事务管理详解 Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很 ...
- 编程式事务和声明式事物
编程式事务 声明式事物
- java编程式事务_Spring编程式和声明式事务实例讲解
Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用, 使用XML配置声明式事务: 推荐使用(代码 ...
最新文章
- 语义分割--Mix-and-Match Tuning for Self-Supervised Semantic Segmentation
- js字符串转化为方法调用
- delphi中指针的用法
- 关于HbSrv.exe
- Chapter 12 外观模式
- JsTree实现简单的CRUD
- logistic regression一点理解
- linux 停止jar 指令,Linux编辑启动、停止与重启springboot jar包脚本实例
- 构建新模式java_Nacos 1.3.0 来了,基于全新内核构建!
- java上拉变量_「小程序JAVA实战」小程序页面的上拉下拉刷新(50)
- 被调用的对象已与其客户端断开连接 win10_【完整案例】基于Socket开发TCP传输客户端...
- MySql学习10-----存储过程和函数
- 31岁了学python还是arm_学嵌入式的,学完了51单片机,下一步呢,是学stm32还是学arm呢.有些迷茫还有Linux等。怎么一步步学好...
- 数据库实战:SQL Server系列网络课程资料集
- winscp是什么软件_避免使用绿色版破解版和不更新的FTP软件
- 图像有损压缩与无损压缩_图像:有损与无损压缩
- signature=44e925e612735a871c9c44002806d71b,英文书信格式
- 腾讯云平台WordPress建站问题记录
- 设计模式二 单例模式
- web前端响应式设计总结