作者:陈超,北京中科金财科技股份有限公司研发中心技术经理,精通Java/Go等开发语言,熟练掌握 Kubernetes、 Docker、微服务架构,了解比特币、以太坊等公链技术体系,了解 Fabric 等联盟链技术体系,精通泛金融数字化 解决方案。
KubeSphere 开源社区的伙伴们,大家好。我是北京中科金财科技股份有限公司区块链中心的平台即服务产品研发负责人陈超,很高兴有机会同大家一起分享中科金财基于 KubeSphere 融合区块链技术二次开发改造的经验。
自 2019 年 10 月 24 日区块链上升为国家战略至今已满两年。继 20 年区块链被纳入“新基建”后,21 年 3 月份,区块链被写入《中华人民共和国国民经济和社会发展第十四个五年规划和 2035 年远景目标纲要》,规划提出培育壮大区块链等新兴数字产业。
公司研究政策趋势并结合多年 B 端科技服务的经验,将区块链技术及应用建设纳入公司的战略,持续在区块链技术底层、上层业务应用及整体运维管理方面进行建设。
区块链技术集众多技术之大成,且在行业中的应用价值方面还处于不断探索的阶段。从底层链技术方面来看,国外的联盟链 Fabric、公链以太坊等,国内的开源联盟链 fisco bcos、政府背书的星火链,长安链,树图等,同时国内还有一些企业自主开发的区块链技术,如趣链公司的区块链、中科金财的中科金链、天河国云的天河链、复杂美的 chain33,不同的链底层技术所涉及的部署、维护、应用接入方式都可能不太一样,造成了开展行业应用的成本较高,而为了降低用户在接入和维护区块链设施时的实践成本和学习成本,且尽可能的适配不同的技术底层,在区块链中间件的标准定义下,需要一套区块链即服务(Blockchain as a Service)平台。
中科金财于 18 年已开展 BaaS 平台的建设,采用相对成熟稳定的应用架构进行开发,逐渐加入了基于多租户的 RBAC 权限体系、资源及区块链网络监控、区块链动态部署及节点管理等功能,并在一些项目场景中投入使用。
但由于整体架构的缺陷,在部署效率、部署资源动态管理、区块链网络服务状态实时监控、账本高可用、证书托管等方面遇到了较大的技术难度,进一步迭代升级的成本非常大。因此重新进行 BaaS 的总体设计,拥抱 Kubernetes、拥抱云原生变得非常重要。
云原生是关于速度和敏捷性的,有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用,能够构建容错性好、易于管理和便于观察的松耦合系统。
符合云原生架构的应用程序应该是采用开源技术栈(Kubernetes+Docker)进行容器化部署,利用基础设施管理能力实现资源弹性伸缩、服务动态部署与资源利用率优化等。
中科金财 SinoBaaS 平台在对区块链网络进行动态部署管理、运行检测、资源弹性扩充等方面的迫切需求与云原生的一些特点非常契合,因此在新的版本改造过程中决定全面集成 Kubernetes。
在决定拥抱云原生架构的时候我们选型决定要使用其中非常活跃和成熟的 Kubernetes 作为我们平台的底层支撑,但是 Kubernetes 整体系统比较复杂学习成本比较高,对非专业用户使用非常不友好。综合考虑之后我们决定选择一个较完善的 Kubernetes 发行版本。我们针对市场上一些比较流行的平台做了评估,最终选择了 KubeSphere 作为我们的管理平台。
选择 KubeSphere 主要原因有以下几点:
KubeSphere 拥有一套非常完善的配套功能,这让我们只需要重点关注区块链相关的功能组件开发就可以。中科金财 BaaS 平台在 KubeSphere 上做了以下融合:
中科金财针对 BaaS 平台所需要具备如灵活部署、资源动态伸缩管理、可视化运维、细颗粒度监控与预警、运行高可靠等方面的核心能力,进行了中科金财区块链即服务平台 SinoBaaS 的总体设计,设计图如下:

SinoBaaS 在初期的实践中使用了 PersistentVolume 的 localhost 模式,这种方式使得区块链节点对物理节点的耦合性非常高,且证书也都保存在物理环境中,使得 Kubernetes 的自动调度的特性被严重限制了。在组建区块链网络中还需要通过证书加密,证书保存到本地安全隐患也非常高,一旦磁盘损坏可能会导致证书丢失,失去了证书的节点服务就跟失去了身份的人一样,后续的补偿措施非常困难。
因此在开发过程中,引入了独立的分布式存储,并将证书等信息存储在 Kubernetes 的 ConfigMap 中,整个区块链网络运行所产生的账本数据、状态数据、证书等都得到了高可靠的存储,解决了 Kubernetes 在漂移调度过程中资源依赖问题。
在 BaaS 平台未融合 KubeSphere 改造前,区块链网络部署过程相当繁琐,首先需要我们手动生成区块链网络所需的证书再分别拷贝到节点机器上,再通过修改脚本参数生成部署组织节点的 yaml 文件,然后才能部署到各个机器中,整个部署过程十分不标准且容易出错,排查起来问题比较困难,整体部署效率较低。
我们在选择 KubeSphere 时就考虑到它拥有一套标准的部署流程,而且 ks-installer 工具也是开源的非常适合我们针对部署痛点进行优化。优化过后的 ks-installer 集群可以实现只需要根据不同项目环境修改特定的几个参数就可以非常流畅的部署一套标准的 BaaS 平台。
我们认为使用 BaaS 进行部署区块链网络时一般考虑几点要素:
创建完的联盟的架构如下:
整个区块链联盟使用 Namespace 作为资源的隔离,整体的搭建也分为三层 : 服务层(service),容器层(Pod),和分布式存储。

区块链的管理,直接面对用户,提供给运维或者普通用户来操作,所以既要保证可操作性又要保证关键数据的呈现。
当然针对各类应用场景如数据层证,资产转账等常用场景我们也提供了内置的链码,如需定制化智能合约可以通过链码仓库来上传链码,并进行实例化等操作,能有比较好的开放性。

在对 KubeSphere 进行二次开发的过程中,前端的本地化开发比较容易只需要替换 server/config.yaml 中的 server:apiServer:url/wsUrl 地址便可。但后端的本地化开发便涉及到若干问题:如何确保开发环境与测试环境的一致,如何快速开发调试,如果开发涉及到多个云上多个服务之间的相互调用又该如何?这些问题成为了团队开发的痛点。
这让我们团队积极探索本地化开发的方式,其中telepresence和kt-connect都能解决以上痛点,实现的效果类似,都能将集群流量转发到本地。_ 这里使用 kt-connect 官方原图说明一下 _。

KubeSphere 平台提供了多租户管理,角色管理,并以企业空间,项目进行更细颗粒度的权限管理。结合区块链 BaaS 平台也需要多租户,创建区块链联盟,并在联盟中创建区块链节点和服务。BaaS 在 KubeSphere 的多租户的基础上进行融合,提供多租户的登录能力,每一个租户创建自己的区块链服务;通过 BaaS 创建的区块链服务来满足业务系统的上链需求。
区块链创建一个联盟,包含一个和多个组织同时每个组织拥有一定数量的区块链节点,提供区块链服务。通过 BaaS 平台创建用户并关联相应的组织,当创建联盟时邀请相关组织加入联盟。

用户基本信息如下: 包括用户名,用户所属组织,用户邮箱等信息。

在 Baas 平台中的组织管理中可以添加组织并关联到用户,再邀请到创建的联盟中进行通道和智能合约的操作。

SinoBaaS 平台从开始改造,到积极拥抱云原生架构,到最终选择 KubeSphere 作为技术开发平台,也遇到不少的问题和挑战 :
SinoBaaS 平台经过 KubeSphere 的初步改造升级,完成了区块链联盟的创建,组织管理,通道管理,链码仓库,链码管理,区块和交易查询,数据存证和资产转账等功能。联盟的创建和删除更加的便捷,融合 KubeSphere 的企业空间和项目进行了多层级的权限管理,不同角色的用户可以有不同的区块链视图,看到不同的区块链的节点和服务信息。简单效果如下:
区块链浏览器页面:

联盟概览页面:

信息查询页面(可以通过区块号,区块 hash,交易 ID 等进行查询操作):

在 SinoBaaS 1.0 版本开发结束后,我们也在抓紧推进后续版本的规划和迭代,在此也做一下列举说明,以供参考交流。
目前可以实现将 ks-apiserver 云上的流量全部拦截在本地,但是在面对多人协同开发时还存在不足,下一步需要实现创建路由规则重定向特定流量,实现多人协作场景下互不影响的本地调试。
目前区块链网络还是以本地化 SDK 的方式接入,在使用便捷性和标准化方面还存在不足,且还无法对访问进行审计管控,因此还需要在平台中开发基于 AK/SK 的 API 服务,作为区块链网络对外接入访问的入口,并将 API 的服务作为 KubeSphere 的一个服务组件,并配置进 ks-installer 中,随平台的一起初始化部署,并在 Service Components 中可以查询到服务的状态。

后续甚至可以加入更多的 DApp 应用,都可以纳入服务组件中统一管理,并在应用环节深度集成到平台的各个功能中。
SinoBaas 平台为更好的适应复杂网络场景下的需求,如多个参与组织都有独立的局域网,相互间以专线形式通讯,考虑依托 KubeSphere 的多集群托管模式实现跨集群区块链组网和区块链跨网络通信,真正解决联盟链应用下复杂网络对区块链运行及管理的影响。
KubeSphere 中提供了应用商店的功能,用户可以上传、部署应用商店的应用或者自定义应用。区块链中有很多基于智能合约的应用(溯源、存证、加密猫,基于 ERC721 的数字藏品等),将基于智能合约的应用打造成标准的合约模板,借助应用商店的机制来打造合约商店,方便 SinoBaaS 平台的用户自主选择合约应用进行部署。
本文由博客一文多发平台 OpenWrite 发布!
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我似乎经常遇到一些设计问题,但我不知道是什么是真的很合适。一方面我经常听到我应该限制耦合和坚持单一职责,但当我这样做时,我常常发现它很困难到在需要时将信息获取到程序的一部分。为了例如,classSingerdefinitialize(name)@name=nameendattr:nameend那么Song应该是:classSongdefnew(singer)@singer=singerendend或classSongdefnew(singer_name)@singer_name=singer_nameendend后者耦合性小,按道理应该用。但如果我以后发现宋有什么需要了解更多歌手,我的
我需要使用ActiveMerchant库在我们的一个Rails应用程序中设置支付解决方案。尽管这个问题非常主观,但人们对主要网关(BrainTree、Authorize.net等)的体验如何?它必须:处理定期付款。有能力记入个人帐户。能够取消付款。有办法存储用户的付款详细信息(例如Authotize.netsCIM)。干杯 最佳答案 ActiveMerchant很棒,但在过去一年左右的时间里,我在使用它时发现了一些问题。首先,虽然某些网关可能会得到“支持”——但并非所有功能都包含在内。查看功能矩阵以确保完全支持您选择的网关-http
我有一个像这样的ruby散列{"stuff_attributes"=>{"1"=>{"foo"=>"bar","baz"=>"quux"},"2"=>{"foo"=>"bar","baz"=>"quux"}}}我想把它变成一个看起来像这样的散列{"stuff_attributes"=>[{"foo"=>"bar","baz"=>"quux"},{"foo"=>"bar","baz"=>"quux"}]}我还需要保留键的数字顺序,并且键的数量是可变的。上面是super简化的,但我在底部包含了一个真实的例子。执行此操作的最佳方法是什么?附言还需要递归就递归而言,这是我们可以假设的:1)
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin