长安链 VM Engine架构设计深度解读

news2024/11/18 23:28:08

VM Engine是长安链智能合约引擎的推荐选型,采用Docker容器化架构,容器内部由一个任务调度器和多个合约进程组成,实现了多合约隔离与多进程并发,支持独立部署,目前支持Golang语言合约。

1. 背景说明

自2009年11月以来,Golang语言已经发展了13年,凭借着高并发、高性能、高开发效率迅速发展为热门语言,尤其在区块链领域,Golang语言已然成为底链必不可少的语言选型。在介绍总体架构前,我们需要解释两个具体的技术选型背景:

第一,长安链已经支持轻量级的TinyGo了,我们为什么还要选择原生Go语言?有如下两个原因:

1.  内存管理缺陷:TinyGo对wasm的支持不太完善,对内存逃逸分析、GC等方面有不足之处,容易造成栈溢出。因此对于循环、函数栈深度、内存申请等有较大的限制。

2.  导入包受限:TinyGo对导入包的支持有限(参考https://tinygo.org/lang-support/stdlib/),实际测试支持的并不完整,会发生一些错误,难以满足复杂的合约场景。

相信使用过TinyGo的开发者都有过上述经历。与公链有所不同,联盟链的合约更关注语言的丰富度与自由度,我们完全可以选择原生Go语言,从而使用更完备的类库,实现更稳定的区块链应用。

第二,我们为什么使用Docker容器化服务来支撑VM Engine项目呢?有如下三个原因:

(1) 可移植性:VM Engine启动Docker容器来运行合约虚拟机,调度和执行合约任务。用户能够在任意Linux机器上快速部署一套VM Engine虚拟机容器。

(2)  可扩展性:VM Engine与区块链属于不同的进程,通过gRPC进行通信,这牺牲了一部分性能,但是具有更高的扩展性。VM Engine能够进行独立部署,作为合约计算引擎服务提供给多个区块链。

(3)  安全性:如果要避免进程间/网络通信,需与区块链同进程,要用插件系统(Go Plugin),插件系统目前不成熟,无法主动释放,内存占用大。更重要的是,原生Golang代码自由度很高,用户合约行为难以限制。

基于上面两种技术选型我们依次推出了VM Docker GoVM Engine核心引擎。

VM Engine是VM Docker Go的重构版本,相比原有版本,VM Engine具有50%的性能提升,支持任意合约语言的跨合约调用,更合理的进程资源限制,更稳定的合约执行环境。

在介绍VM Engine前,我们先介绍VM Docker Go的设计理念与架构。

2.  VM Docker Go的架构设计

VM Docker Go使用单容器多进程架构,与区块链通过双向流式gRPC的方式进行通信,具体模块交互架构方案如下:

图1

其中,各个模块的介绍如下:

1.  ChainMaker:长安链区块链项目主模块。

2.  VM Docker Go:基于Docker的容器化合约交易调度和执行引擎。

2.1  Contract Engine:合约交易调度引擎,负责转发请求/响应,调度请求与合约进程资源

i.  ChainMaker RPC:区块链RPC服务端,VM Docker Go与ChainMaker交互的唯一模块,交互内容主要包括交易请求、合约文件请求与响应、合约调用请求与响应和交易执行结果;

ii.  Docker Scheduler:容器调度器,负责解析并转发请求/响应;

iii.  Process Manager:进程管理器,负责管理请求/合约进程资源;

iv.  Process Balance:进程负载均衡器,负责管理同一合约同一版本的所有合约进程资源和交易;

v.  Process:进程控制器,负责管理一个合约进程的生命周期;

vi.  Process Handler:进程处理器,负责接收并调度合约进程的所有调用交互;

vii.  Sandbox RPC:合约进程RPC服务端,Contract Engine与Sandbox交互的唯一模块,交互内容主要包括交易请求、合约调用请求、合约调用响应和合约进程执行结果。

2.2  Sandbox:合约进程,合约二进制代码的运行实体,同一个合约可能有多个合约进程,从而实现交易并发。

通过上述架构设计,我们总结出【VM Docker Go的设计思想】如下:

(1)  合约隔离:每个合约任务用独立进程(Sandbox)来执行,采用CGroup限制进程资源的占用(暂未强制限制),避免合约恶意消耗、非法访问或写入系统资源。

(2)  任务独立:Sandbox中同时只存在一笔交易,这会牺牲较多性能,但能够避免Sandbox出现问题时多笔交易失败,读写集不一致。

(3)  单合约最大进程数并发:为了尽可能避免Sandbox进程关闭与启动,系统会尽量为每个任务创建新Sandbox进程,直到达到用户设定的单合约进程数最大阈值,一定时间空闲后释放进程。但这样也会引入进程数量无法控制的问题。

3.  VM Docker Go重构的原因

我们为什么要对VM Docker Go进行重构呢,我们的目标如下:

1.  更高效:VM Docker Go原生Go语言的性能方面已经非常优异。但我们依然想要达到更高的性能,调整的方式如下:

(1) 避免多余的RPC通信,Sandbox与链进行常规交互时,可以不经过Contract Engine;

(2)  总进程数限制,让单个合约能够拥有更多的进程资源并发执行交易;

(3)  其他优化,包括gRPC调优、缓存、分段锁、并发控制等。

2.  更稳定:VM Engine功能支持更加完备,极端情况下表现稳定:

(1)  VM Docker Go采用单合约进程数限制方式来限制进程资源,单合约进程数限制设置过大时,在合约数过多时,容易出现大量进程创建的情况,设置过小时,在压力峰值时,资源无法充分利用;如果预设用户数不合理,会导致进程无法分配到用户而超时,重构方案实现了抢占式的合约进程资源动态切换与调度算法,对总进程数进行了限制,充分利用进程资源;

(2)  跨合约调用, VM Docker Go仅支持调用同样的合约,重构支持所有合约相互调用;

(3)  VM Engine采用基于流式的任务处理与消息通知机制,吞吐量更高,架构设计更合理。

4.  VM Engine架构设计与常见调用流程

4.1 VM Engine架构设计

VM Engine的架构进行了重构设计,具体的系统架构如下:

图2

4.1.1  ChainMaker:长安链区块链项目主模块

(1)  Runtime Server:合约交互服务端,直接处理来自Sandbox的交易请求和执行结果.

(2)  Contract Engine Client:合约引擎客户端,负责发送交易请求/合约文件给Contract Engine。

(3)  VM Runtime Instance:交易运行时处理器,负责处理交易运行时的所有请求与响应。

4.1.2 VM Engine:基于Docker的容器化合约交易调度和执行引擎。

(1)  Contract Engine:合约交易调度引擎,负责转发请求/响应,调度请求与合约进程资源。

i.  Contract Engine Server:合约引擎服务端,VMEngine与ChainMaker交互的唯一模块,交互内容主要包括交易请求、合约文件请求与响应和交易异常信息;

ii.  Request Scheduler:请求调度器,负责解析并转发请求/响应;

iii.  Request Group:交易组,负责管理同一合约同一版本的所有交易,并根据交易存数来申请进合约程资源;

iv.  Contract Manager:合约管理器,负责管理合约文件/缓存信息;

v.  Process Manager:进程管理器,负责管理合约进程资源;

vi.  Process:进程控制器,负责管理一个合约进程的生命周期;

vii.  User Manager:用户管理器,负责管理合约进程Linux用户;

viii.  Security:安全控制器,负责CGroup等系统资源管理。

(2)  Sandbox:合约进程,合约二进制代码的运行实体,同一个合约可能有多个合约进程,从而实现交易并发(Java版本尚未推出)

i.  Runtime Client:合约交互客户端,直接向ChainMaker进行调用请求;

ii.  SDK Instance:合约SDK实例,存储交易相关元信息;

iii.  Contract Engine Client:交易传输客户端,接收来自VM Engine的交易并返回完成信号。

4.2 VM Engine常见调用流程

下面我们介绍几种常见的调用流程:

4.2.1  简单合约调用流程

阶段1:发送交易

图3

该阶段由ChainMaker并发调用VM Runtime Instance,多笔交易调用请求会通过Contract Engine Client发送到VM Engine,Contract Engine Server接收到后会直接发送给Request Scheduler进行调度。

阶段2:调度交易

图4

Request Scheduler根据交易中的链ID、合约名、合约版本将其分配到不同的Request Group中,如果交易积攒过多,Request Group会向Process Manager申请进程资源,Process Manager优先分配未启动进程,再尝试切换闲置进程资源。Process监听Tx Channel,并发送给Sandbox执行任务。

阶段3:合约调用

图5

Sandbox在执行过程所有的合约交互都直接与ChainMaker的Runtime Server进行同步交互。由于交易隔离性和安全性考虑,Sandbox内部不支持交易并发执行。

阶段4:返回结果

图6

Sandbox执行完成后,会向ChainMaker的Runtime Server返回执行结果,并向Contract Engine的对应的Process发送完成信号,从而继续处理下一笔交易。

4.2.2  创建合约流程

所有交易都是从创建合约开始的,创建合约的具体流程如下:

图7

事实上,如果Contract Engine合约丢失,它也会向ChainMaker发送请求获取合约文件。

4.3  跨合约调用流程

图8

跨合约调用本质上是调度一笔新的交易执行,执行结果返回给上一个等待的交易,该版本支持不同语言间跨合约调用。

5.  VM Engine进程状态机设计与进程资源分配机制

5.1 VM Engine进程状态机设计

VM Engine中进程资源的状态机设计包括Process详细状态和Process Manager总体状态,双方保持强一致性。具体状态机如下:

图9

Process状态机:

(1)  created:初始创建状态,进程刚刚创建;

(2)  ready:就绪状态,进程创建后握手成功或刚刚执行完成交易或刚从idle状态转换过来;

(3)  busy:忙碌状态,进程正在执行交易;

(4)  idle:闲置状态,进程就绪一段时间后都没有新交易执行;

(5)  changing:进程切换到新合约进程的中间态,闲置后可以被其他合约进程抢占,即将切换合约信息与任务信息;

(6) closing:进程关闭的中间态,进程即将退出并销毁。

Process Manager状态机:

(1)  busy,忙碌状态,包括Process中的created、ready与busy状态,该状态下进程资源不可被抢占;

(2)  idle,闲置状态,对应Process中的idle状态,该状态下进程资源可以被抢占。

5.2 VM Engine进程资源分配机制

Request Group进程申请机制:每一个Request Group都包含原始交易队列和跨合约交易队列,分别放置第一层交易和>1层子交易,在合约就绪、新交易入队和上次进程返回时触发合约进程资源申请,申请进程数为:总任务数-处于ready/busy状态中的合约进程,最小值为0。

Process Manager进程数据结构:原始进程与跨合约进程由不同的Process Manager管理,内部结构保持一致,主要包括:

(1)  闲置进程,长时间没有执行交易的进程,随时会被抢占;

(2)  忙碌进程:正在处理/准备处理任务的进程;

(3)  等待中的Request Group,有闲置进程时,优先释放给队头元素。

Process Manager进程分配原则:申请新进程时,优先启动进程,如果不够则释放闲置进程,最后将其加入等待队列。(如果申请数为0,说明不需要进程,将其从等待队列移出)

Process Manager进程回收原则:系统会进行进程资源的周期性回收,回收数为配置的回收比例和闲置进程的最小数。

图10

6.  VM Engine的架构优势与实际效果

VM Engine的架构设计优势如下:

(1)  性能更高,通过gRPC通信次数的降低、gRPC参数的调优、协程状态机的合理控制、缓存与并发的优化等,VM Engine具备更高的性能;

(2)  稳定性更高,通过合约进程资源总数的最大限制与合理的进程资源动态切换与调度算法,合约进程能够以较优的方式进行动态分配,高效并发地执行交易;

(3)  应用更广泛,支持多语言的跨合约调用,能够满足任意语言的合约之间相互调用;

(4)  可维护性更高,模块分工明确,采用基于流式的任务处理与消息通知机制与进程状态机控制,架构设计更加清晰。

为了验证重构的效果,我们按照下面的测试条件进行测试:

图11

性能测试结果如下:

图12

7. 兼容性问题

VM Engine在v2.3.0版本推出并长期维护,对于VM Docker Go合约/引擎用户来说,如何实现兼容呢?

由于gRPC架构的调整,v2.3.0及后续版本的VM Engine与v2.3.0及后续版本合约SDK(contract-sdk-go)是配套的,而VM Docker Go是与v2.2.X版本的合约SDK是配套的。如果想要使用VM Engine,请使用新版合约SDK,并启用VM Engine,如果想要使用VM Docker Go,请使用旧版合约SDK,并启用VM Docker Go。具体如下:

1.  仅使用VM Engine,请使用对应的新版本合约SDK编译合约,并在chainmaker.yml中启用VM Engine,此时区块链会拉起VM Engine合约容器,安装并调用新合约时只会发送到VM Engine容器中(如果使用了旧版的合约SDK编译合约,会收到VM Docker Go未配置的错误信息);

2.  仅使用VM Docker Go,请使用对应的旧版本合约SDK编译合约,并在chainmaker.yml中启用VM Docker Go,此时区块链会拉起VM Docker Go合约容器,安装并调用旧合约时只会发送到VM Docker Go容器中(如果使用了新版的合约SDK编译合约,会收到VM Engine未配置的错误信息);

3.  同时使用VM Engine与VM Docker Go,分别使用对应的合约SDK编译合约,在chainmaker.yml中同时启用两种容器,此时区块链会拉起两种容器,安装并调用合约会发送到各自的容器中。

另外,cmc与sdk的调用方式不变,新版VM Engine额外支持将方法从调用的params中抽离到外层的methods中(详情请参考长安链官方文档)。

8. 总结

VM Engine在VM Docker Go的基础上进行了全面的重构和优化,包括架构优化设计、多种性能提升手段应用、进程总数资源限制、跨合约调用扩展等等。新的合约引擎将作为核心支撑持续保障长安链项目的稳定高效运行。

长安链ChainMaker

长安链 · ChainMaker是新一代区块链开源底层软件平台,包含区块链核心框架、丰富的组件库和工具集,致力于为用户高效、精准地解决差异化区块链实现需求,构建高性能、高可信、高安全的新型数字基础设施。

38篇原创内容

公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/128351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUDA 冬令营1

基本概念 1.CPU的任务:为串行任务优化 2.GPU的任务:为并行任务优化 3.L4T ubuntu:基于NVIDIA Tegra芯片的ubuntu系统(linux for Tegra) 4.Tegra:继承了ARM CPU 和 NVIDIA GPU的处理器芯片 5.X86&#xff1…

2023京东年货节全民炸年兽活动最详细规则

2023京东全民炸年兽活动规则 1、活动时间 整体活动时间: 2022年12月26日00: 00: 00–2023年01月15日23: 59: 59 2、活动玩法 (1)玩法一:全民炸年兽瓜分10亿压岁钱 活动时间: 2022年12月26日00: 00: 00–2023年01月15日23: 59: 59 (2) 玩法二:每晚8点分百万红包 活动时间…

Houdini和C4D区别在哪?哪个更好用

Houdini和C4D作为当前软件市场上非常热门的设计软件,现在越来越多的小伙伴开始学习。所以咱们今天就从行业应用、建模、动画和使用难易度等进行多方面对比,帮助小伙伴们更清楚地了解这两款软件—— Houdini作为一款非常受欢迎的3D&VFX制作工具&#…

美国公司是如何搞创新的,又是如何失败的......

PARC,施乐帕洛阿图研究中心,和贝尔实验室媲美的IT界圣地。从这里走出了一大批伟大的发明,直接改变了整个计算机行业。Alto PC ,图形用户界面,所见即所得,以太网,PostScript,面向对象…

复购高,退货低的日本市场成为跨境电商新风口,新手如何快速入局

据统计预测,未来几年将会有越来越多的跨境卖家涌入日本电商市场。但由于在语言、文化和消费习惯上存在一定的差异,很多中国卖家并不熟悉日本的文化与市场需求,也很难在短时间内快速适应日本电商平台的运营规则与服务。 日本作为一个经济发达的…

【PS-选区编辑】变换选区、反向命令、建立工作路径

目录 变换选区 1、位置 2、多种操作 反向命令 1、反选选区:ctrlshifti 2、边界 3、平滑 4、扩展和收缩 5、羽化 建立工作路径 变换选区 1、位置 制作了一个制作了选区后,鼠标右击找到【变换选区】,或在【选择】菜单中找到【变换…

JavaScript 入门基础 - 运算符(三)

JavaScript 入门基础 - 运算符(三) 文章目录JavaScript 入门基础 - 运算符(三)1.什么是运算符2.表达式和返回值3.算术运算符概述4. 赋值运算符5.递增和递减运算符5.1 递增和递减运算符概述5.2 递增运算符5.2.1 前置递增运算符5.2.…

Ajax(1)---了解Ajax和XML

目录 Ajax XML了解 Ajax的特点 HTTP协议请求报文与响应文本结构 HTTP 请求报文 响应报文 Ajax AJAX全称为Asynchronous JavaScript And XML,就是异步的JS和XML通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX不是新…

一篇带你彻底弄懂SpringBoot项目jdk版本及依赖不兼容问题

💟💟前言 ​ 友友们大家好,我是你们的小王同学😗😗 今天给大家打来的是 一篇带你彻底弄懂SpringBoot项目jdk版本及依赖不兼容问题 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞👍 收…

MySQL 大表优化方案

单表优化 读写分离 缓存 表分区 垂直拆分 水平拆分 兼容MySQL且可水平扩展的数据库 NoSQL 当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不…

通过Django发送邮件

通过Django发送邮件非常的简单,在Python中已经内置了一个smtplib邮件发送模块,Django在此基础上进行了简单地封装,我们可以在Django的环境中方便的发送邮件。大部分邮件发送成功主要是邮件的参数配置,本文以常用的126邮箱和QQ邮箱…

《2022中国数据智能产业图谱3.0版》重磅发布

‍数据猿出品本次“数据猿行业盘点季大型主题策划活动——《2022中国数据智能产业图谱3.0版》”为2022年度图谱版本的升级更新版,下一次版本迭代将于2023年4月底发布2023年1.0版,敬请期待,欢迎报名。‍数据智能产业创新服务媒体——聚焦数智 …

svn修改提交日志信息

参考:唐小码个人博客 一、svn修改提交的msg信息和作者信息 鼠标右键找到show log> 选择要修改的日志行,第一个是修改作者信息,第二个是修改日志信息 二、svn修改提交的日期信息 修改日期信息的话,你得先有svn服务器的权限&…

光电接收的TIA设计

APD的光电接收电路如下图所示,APD的光电流较SiPM是小很多的,所以需要TIA来做跨阻放大,一般RF电阻要5k到10k左右,光电流一般也就几十uA,这个跨阻放大主要是对Cf大小的选择,Cf的选择主要考虑下面的两点。从放…

【基础强训】day4

一、选择题 &#x1f308;第1题 有以下程序 #include<iostream> #include<cstdio> using namespace std; int main(){ int m0123, n123; printf("%o %o\n", m, n); return 0; } 程序运行后的输出结果是&#xff08;&#xff09; A 0123 0173 B 01…

汇聚数据库创新力量,加速企业数字化转型

2022年12月29日&#xff0c;以“汇聚数据库创新力量&#xff0c;加速企业数字化转型”为主题的openGauss Summit 2022在线上举行。会上&#xff0c;openGauss社区理事会理事长江大勇对外公布了最近社区及生态进展&#xff0c;并宣布推出资源池化架构&#xff0c;实现软硬融合&a…

人脸识别实战教程

人脸识别实战教程 本教程介绍如何使用Alibaba Cloud SDK for Java进行人体属性识别、人体计数和人脸搜索任务。 背景信息 人脸人体识别技术是基于阿里云深度学习算法&#xff0c;结合图像或视频的人脸检测、分析、比对以及人体检测等技术&#xff0c;为您提供人脸人体的检测…

【Java语言】— 运算符、案例:键盘录入

目录运算符1.算术运算符案例&#xff1a;数值拆分2.“”做连接符3.自增自减运算符自增自减的使用事项自增自减的案列4.赋值运算符基本赋值运算符&#xff1a;“”扩展赋值运算符&#xff1a;“”、“-”、“*”、“/”5.关系运算符6.逻辑运算符短路逻辑运算符总结7.三元运算符三…

DAS和NAS

对于有大量数据存储需求的人群可能都听过NAS或者DAS&#xff0c;由两者演化出来的产品也各有不同&#xff0c;但是两者的真正的区别是什么、各有哪些优势和劣势、分别适用哪些人群一直以来也是困扰大家的问题。 DAS全称为直接附加存储(Direct Attached Storage&#xff0c;DAS…

安全用电守护卫士,同为(TOWE)带漏电保护功能桌面PDU插座

随着人民生活水平的提高&#xff0c;人们日常对电的需求量越来越高&#xff0c;尤其是在隆冬季节&#xff0c;很多居民冬季采用电炉、电热毯和空调等取暖&#xff0c;用电负荷较大&#xff0c;一旦出现漏电、过载、短路等问题&#xff0c;很容易引发火灾。据了解&#xff0c;大…