亦来云《听大牛讲Elastos Carrier的故事》社区分享会,我们邀请了牛靖宇老师为大家做分享,交流,产生灵感,碰撞,才会有火花。这次关于Elastos Carrier碰撞出了怎样的火花~一起来看看牛靖宇老师的思考。
1
Carrier是什么?亦来云为什么做Carrier平台
Carrier本身是很基础的,去中心化的通讯平台,在亦来云整个架构里,Carrier作为去中心化平台,它是整个亦来云基础平台的基础服务之一。
Carrier作为亦来云的基础平台并不直接外露给应用开发者使用。整个平台形态会把Carrier分装在ElastosRT的运行式环境里,由RT来暴露整个Carrier功能接口。虽然现在Carrier对外提供了API,但是也是中间状态,当然也支持开发者在现在Carrier平台API之上开发一些应用,做一些开发,但是最终的形态会是整合在RT内部。目前亦来云内部也有Team专门做RT整合,主要把Carrier所有的通讯能力都整合在RT内部,大家开发的时候只要关注RT的API,使用RT的API就可以使用Carrier所有的功能。
2
Carrier目前包含哪些层次的功能
Carrier目前的技术架构,本身是基于DHT去中心化、分布式的网络基础,在这之上做了friend to frined基础通讯网络,在这个通讯网络上我们提供了几层不同层次的功能接口。
目前Carrier包含以下几个层面的能力:
首先Carrier包含了节点之间的关联关系的支持,在Carrier之上所有的节点都在一个DHT网络中。但是节点和节点相对比较孤立,要建立节点和节点之间的通讯,首先要建立节点之间的关系,所以Carrier有一组API,帮助你必要的节点之间建立关联关系,有点像现实世界的friend一样,或者像微信里的friend。
A和B如果要通讯的话,首先A和B一定是friend的关系,Carrier有基础的API来支持建立节点的关系,这是基础的API。在这个基础上,Carrier还提供了面向消息的API,就是说一旦节点之间建立了关系,就可以使用最基本的消息,这个消息是没有连接的,是透过网络来做的,A和B是friend的话,A和B可以随时发消息,B和A也可以。这个消息在AB之间是不需要建立连接的,直接可以透过DHT网络来中转,实现A和B之间的消息传输,这是消息。
其次,在消息之上提供面向大数据的传输,比如说A和B之间除了消息之外,应用之间还要传输一些大块的数据,大块的数据就有点像我需要建立类似socket这样的通讯机制,Carrier也提供了Session的API,来帮助建立类似这种面向连接或者UDP数据报的数据传输,在Carrier这个体系里我们把它叫stream。
Carrier提供的session的通话能力其实分为两层,一层是类UDP数据报的模式,另外是类TCP流式的模式,这两个模式都是在stream之上实现的,你可以拉选项选定是数据报的模式还是流式的模式。这两种模式从接口上来讲使用是一模一样的,但是其实下面两个工作机制,一个是类TCP,一个是类UDP。
再次,提供了数据的加解密,多路复用,甚至接口转发上层语意,方便Carrier开发者更好的做应用支持,使用起来更方便。同时因为Carrier是一个完全去中心化的网络,它没有中间的或者一组中央服务器来运作,所以说Carrier本身这个网络不会存储任何用户的信息。比如说用户发的任何消息,节点之间的通讯记录,friend的关系,所有这些都是保存在节点自身。
Carrier的接口本身涉及到大量的IO,它下面实现的复杂度比传统网络程序要复杂很多,所以说整个实现是基于异步IO的,下面会有个工作线程,所有用户接口都是异步的。正向的调用归正向调用,反向调用都是call back形式体现出来的,比如说有消息来了,流上数据来了,这些都是透过call back来实现的,这样做相对有好处,就是用户不太关心下面的线程模型。但是对用户来讲,会有些同步和事件处理的复杂度。
所以说整个P2P模式的程序开发会和传统网络应用开发相比有一定复杂度,需要按照异步IO的模式来考虑这个问题,这是Carrier唯一使用的门槛。
3
Carrier下面穿透如何实现?下面具体做的协议是不是采用UDP
Carrier下面具体最底层传输协议一定是UDP,因为在互联网环境里如果做端到端,P2P的通讯只有采用P2P是最经济的,因为TCP穿透力很低,UDP穿透力相对比较高。在国内的网络环境里,这个穿透力基本在70%—80%场景下可以做P2P穿透的,剩下20%—30%的网络场景往往需要人类。
具体的支持在亦来云Carrier环境里,亦来云首先有一些公共节点,在这些节点上都会有relay的支持,后面随着Carrier的落地和应用部署,也会有越来越多的支持relay服务,这是一个人人为我,我为人人的网络。
虽然下面的基础传输协议采用了UDP,但是在CarrierAPI之上我们提供了数据报和流式对等传输能力,这个是通过Carrier内部通讯协议站实现的。应用不管下面实做协议是不是UDP,可以根据应用的需要,采用数据报的形式还是采用流式的形式传输数据,加密和不加密这些都可以应用选择,其实不依赖于Carrier最下层传输协议的选择。
如果关注原代码仓库的话,我们可以完全构建出完整的API参考,现在都有线上API参考,我们可以按照仓库里的说明来建立API参考文档, Carrier的API数量虽然不是很多,但是涵盖的功能还是比较全面的,可以满足大多数应用场景的开发,包括了消息到串流层面的所有支持。
4
Carrier目前接近完成状态了吗
Carrier目前不能说是接近完成状态了,只能说是可用的状态,功能相对稳定、可用,满足大多数应用场景的需要,后续Carrier会有一系列功能加入,这也是跟着社区应用的开发,包括跟着亦来云的需求逐步完善。目前Carrier只是一个起步,后续还会跟着亦来云整体技术框架的演进继续演进,所以不能说是完成的状态,只能说是一个可用的状态。
后面亦来云内部也会针对Carrier去开发一些直接基于Carrier的应用范例,比如说近期会有一个个人云盘的个人范例,仓库开放以后都可以去了解。给出一些典型的应用场景,包括对传统应用的支持,Carrier怎么使用,代码怎么写等等都有很规范的范例出来。
关于端点续传这个不在Carrier层面来考虑,因为Carrier提供的传输通道是类TCP或者类UDP的通道,不太指望socket能支持断点续传,断点续传是你在socket之上应用支持的,针对Carrier也是一样的。Carrier提供这个通道,这个通道是传数据、音频、视频,支不支持断点续传都是由你的应用来决定的。
5
关于应用场景,Carrier有哪些切入点
Carrier本身可以把网络透明化,可以在局域网、互联网,可以在任何网络场景下把两个节点连通,但是我们不鼓励拿着Carrier做翻墙。大家可以跟着自己的应用,跟着需求发散性的设想,说不定有一些比较好的想法,比较好的应用场景出来,
其实从应用场景上来讲,Carrier还是有比较多的应用场景的切入点。比方说基于Carrier做一个去中心化的IM是有可能的,包括现在的家庭设备智能网关,现在讲到智能网关是挺有痛点的切入场景。
因为我有一个朋友做智能家居的,前两年他选择了当时看起来还不错的设备和供应商,把他们的产品作为集成方案里的构成部分推给最终客户。但是两年以后到今天,有些厂商倒闭了,他们的平台也不再运作了,这时候他们家的手机也就不能再开关灯了,不能工作了。为什么呢?因为没有中央平台的支持。
如果引入Carrier来解决这个问题,用户不用在意最终这个厂商是不是倒掉,只要互联网在,开关就可以控制,手机就不会哑掉,这是Carrier的优势。去中心化的思路和中心化的思路,不是完全的对立面,有时候具有非常强的互补性,大家在考虑应用的时候原来传统的基于中心化思路的方案,转变到Carrier这种去中心化的方案上来,可能别有一番洞天。
其实互补性这一说法是亦来云一个外围的伙伴提出来的,因为他们考虑中心化和去中心化的能不能形成一个互补的方案,给用户提供最好、最优的解决方案。从亦来云的角度讲,未来的大趋势应该是去中心化的,中心化本身和去中心化也并不是很矛盾。按照陈榕老师的一些提法,如果给客户一些可选择的中心化,是不是一种去中心化呢?值得推敲,大家可以读一读陈榕老师关于中心化和去中心化的一些观点、看法,会有启发。
具体到relay怎么实现,就涉及到Carrier内部实现P2P穿透的一些基础协议。Carrier实现P2P的穿透基础协议还是采用了标准化的rfcde的规范,我们follow这个规范,所以relay的部分也是按照这个实现的,只是把这个relay的发现、查找以及使用结合DHT能够自动完成,而不需要指定一个中心化的relay类。因为在Carrier网络上会有很多relay,Carrier本身下面的算法会在这个网络上选择一个最自身来讲最优的relay使用,这些具体的机制在RFC都是有规范的。
具体到Carrier的P2P化,在消息层面,消息的整个传输是基于DHT网络来广播传输的。在P2P的section的会话通过是ICE来实做的,所以P2P化分两个层面。一个是DHT本身的运作,另外通过ICE来实现P2P的直连数据传输,提供一个最优的方案,它是一个结合的方案。在这个结合的过程中,中间relay踩了这两边,section会使用relay,relay又通过DHT来部署和发现。
目前Carrier的API接口稳定可靠,因为我们有自动化测试,每天都会跑test cases,从稳定性和AIP的可用性上讲已经达到相当可用的程度了。亦来云做大的一个目标是把亦来云的生态做大,目前亦来云对整个DApp的生态有很大的扶持力度,可以基于亦来云的基础设施做一些DApp开发,因为扶持生态、支持生态我想是亦来云最基本的责任和义务。
6
在Carrier里需要建立UID和ElaID的关联吗
在Carrier里UID就是Carrier的ID,是唯一的,在这个网络上你的ID本身就是唯一的。所有消息的传送和stream的建立都是围绕这个ID完成的,所以你其实不需要一个UID和ElaID的关联,本身Carrier的ID就是在这个网络上唯一的ID。
具体到网络层面包括socket是完全透明,我们看到的完全就是这个ID,透过这个ID就可以访问Carrier所有资源。比如说给ID代表对端发消息,发起所有呼叫,做流的传输,都是通过ID完成的。
Carrier提供的API分成两个层次,一个call的层次,一个section的层次。call本身是必需的,section是可选的,可以根据应用需要选择只引入call还是引入section,通过这个可以控制你的应用规模,可以有选择的引用一些部分,比如说只用到消息就引入call,用到流式数据传输再引入section,这样比较容易控制应用规模。
关于UID的问题,Carrier的节点一点属地化,就会由Carrier自动创建一个节点ID,这就代表了这个节点自身的身份,不需要再额外有ID了。如果在应用层面有所谓UID,那是应用层面需要考虑的,可以由应用来完成真正用户层面表现出来的UID到CarrierID的影射。
关于浏览器直接调用CarrierAPI的支持,可以关注一下北美Kevin在做的一些成果,他是把Carrier提供了一套NodeJS的API分装,同时变成Local可用的服务,比较方便在H5应用调用Carrier的能力。这个仓库在Elastos里有开源, 在这个项目里本身是把Carrier的native的API分装到了NodeJS里,同时希望透过NodeJS提供一个可以供H5访问的服务,在浏览器的应用里可以透个NodeJS提供的服务接口来使用Carrier的API。
在这里,其实还是推荐大家更多的关注ElastosRT,因为Carrier作为亦来云的一个基础服务,相对来说它是层级比较低的服务。最后所有的服务,DID、钱包、主链、侧链都会通过接口的形式装到RT里去,所以建议大家还是使用RT,RT未来会包含钱包接口、DID、Carrier,会包含所有Elastos基础的服务,分装到统一的编程层面,给大家提供统一的服务。
马上我们会开源一个个人云盘应用,这个云盘服务采用了标准oncrowd的个人云盘服务,它本身是一个browse server应用。这时候云盘需要在局域网,或者在公共互联网可访问的主机上,访问云盘的时候要提供一个URL。我们透过Carrier把云盘做了一个改造,改造以后不用考虑云盘的服务在什么位置,你可以在家里,在办公室,在任何位置。不需要关注它的IP也不需要关注URL,只要透过Carrier的ID节可以访问云盘。其实就相当于让云盘无处不在,可以随时随地的访问,跨越了网络的限制。现在我们的云盘应用服务端和IOS端都已经可已使用了,而且在仓库里已经共享,大家可以关注一下,安卓版本还没有正式发布,还在准备当中。
目前提供的个人云盘还是一个自服式的个人云盘,就相当于在家里架设一个服务供个人使用,或者供小范围群体使用。而IPFS是一个人人为我,我为人人众包式的存储平台,也就是说有IPFS矿机,run矿机的人提供存储,如果有存储的用户有存储需求的话付钱存文件,所以它是众包模式的存储服务。
7
那么,别人拿到你的CarrierID存在安全问题吗
Carrier的ID是对外你身份的标识,但是别人拿到你的CarrierID是不能直接访问数据的。首先他要跟你ID建立Friend关系,Carrier有一个基本认证,由应用来完成。所以不存在我知道你的ID,我就可以访问你的数据的问题。另外Carrier还提供了一些No Spam的支持,来防止这种垃圾的请求,大家可以关注一下API,里面有相对清晰的文档描述。所以说这里没有安全的问题,即使有你的ID,也不能访问你的数据。
Carrier本身是一个非常基础的通讯框架,它本身没有任何应用特征和应用属性,也就是说它是相对通用的开发接口,具体上面承载什么样的应用,承载什么样的逻辑,是由应用来实现的。
Carrier可以去做云盘,也可以去做IM,也可以去做智能家居的IOT的Getaway,这些都是可能的,所以Carrier的应用还是有不同的形式,不同的形态,都可以在Carrier目前提供的功能接口上实现。
8
Carrier目前提供群组支持吗
Carrier目前是没有提供群组支持的,但是Carrier未来会增加群组支持,这个可能会在Carrier下一版的开发结果上增加关于群组的支持,包括群组的消息。
目前Carrier直接提供了大多数主流平台的支持,从主机上的Linux、MAK到移动端的IOS、安卓都提供了支持,像树莓派这样的平台都有原生的支持。另外在Windows上应该也是可以的,只是我们官方现在没有提供build,如果有需要的话,大家可以直接尝试提供Windows的build环境。
Carrier整个开销相对很小,首先它静态开销大概在1兆左右,运行式的开销可能也就2、3兆。因为它下面是基于DHT的,运作起来以后要一直维持DHT网络运作,所以会有一些带宽层面的开销,维持一定频度网络数据的传输,这是它相对而言移动端需要注意的一点。
现在我们本身官方build环境已经提供了标准树莓派的支持了,提供了树莓派的编译脚本,大家可以从仓库里下载使用。
关于Carrier运行时资源的消耗,之前我们实做过一个很小的开发板,大概只有一块钱硬币的开发板,上面是Arm9,800兆主题的CPU,有62的Arm,64flash,跑Carrier跑得很顺畅。
目前我们没有提供prebuilt版本出来,但将来正式发布一些稳定的版本之后,会提供标准prebuilt二进制代码出来,可以方便开发者直接下载使用,而不需要从原代码built,但是现在还是需要大家从原代码built。从原代码built,大家可以最优化的根据自己的需要选择选项,而不是构造一个完整的,大而全的包。
另外像安卓平台还有不同的APIlevel选择,可以针对自己项目的需要,来选择最优的APIevel,提供最好的支持。
大家上手Carrier的时候,建议大家看一下Carrier仓库Apps下面有两个应用,一个是Shall,一个是PFD,还有我们马上开放个人云盘的应用,这里有相对比较规范的Carrier使用,都是亦来云官方自己做的一些应用给大家提供比较完备的参考原型,让大家比较容易去上手。特别推荐一下PFD的应用,其实通过PFD的应用大家可以构造出来很多跨网络的应用场景。比方说家里的主机或者办公室的主机,通过PFD可以远程的映射出来ACH的访问,映射出远程桌面等等。
云盘的应用我们是基于标准oncloud做改造的,oncloud本身它有自身的用户和账号体系。整合了Carrier以后,Carrier本身是没有提供账号的,它只提供了一个访问认证。也就是说,你的手机端要访问自己部署的oncloud service的时候,需要透过CarrierAPI做节点之间的关联关系,就是你的手机要和云盘服务做一个配对。这个配对是透过配对码里完成的,你在部署服务service的时候由你自己来设定的,在手机端输入正确的配对码就可以做Carrier的配对。
在做好配对以后才能提供云盘客户端到云盘的访问,没有配对码是不可能实现云盘的访问的。有了配对码以后,还要有正确云盘的账号才能访问oncloud云盘,所以是分成两层,一个是配对的认证,一个是oncloud用户账号认证。
目前Carrier不支持离线消息,也就是说Carrier节点之间发送消息的时候,节点一定要在线。比如说A和B发消息,B不在线的话,这时候这个消息是不能送到B的,网络也没有缓存能力。关于离线消息目前不支持,但是考虑透过一些折中的技术方案未来提供支持,但是当下Carrier还没有提供离线消息的支持。
目前实现现状也是受制于Carrier是完全去中心的网络环境,它没有中央的服务器。也就是说当一个节点不在线的时候,其实这个消息没人替你缓存,除非自己缓存。你应用可以自己缓存,将来等对端上线了以后再发送,其实它不是一个离线消息,还是在上线以后才发送的,这本身是去中心化网络技术本身制约了离线消息的实现。所以未来要实现离线消息的话,也得考虑引入一些其他的新的方案来支持离线消息。
如果在中心化场景里,本身没有任何障碍,但是在去中心化场景里完全没有中心化服务器的话,这就是一个很大的障碍。离线消息是这样,包括类似于安卓、IOS的推送消息,在Carrier体系架构下都会是一些障碍,但是未来这些障碍我们都会通过一些技术方案来回避掉,提供包括离线消息、推送等等。
其实这个问题可以延伸出来中心化、去中心化整个技术方案、技术架构导致的差异。因为有时候中心化有中心化的优势和劣势,去中心化也有自己的优势和劣势。所以在很多技术方案里中心化和去中心化是相对结合的,根据你应用需求让二者统一和谐共存的状态是更合理的一种状态。
9
可选择的中心化是不是一种合适的方案呢
关于这个问题有在考虑,但是这是相对在完全去中心化网络里又比较棘手的问题,和前面离线消息很类似。 Carrier的ID其实是椭圆曲线上的一个密钥对的公钥。可以理解为CarrierID非常类似于钱包的ID。CarrierID是在Carrier节点第一次运行的时候,初始化的时候会生成一个自身的CarrierID。CarrierID是公钥,后面关联着私钥,你所有的通讯都是这个私钥加密的,包括认证。
关于Ddos攻击,因为Carrier的网络是Friend to Friend的网络,也就是说如果这个节点虽然都在DHC网络之上,但是没有建立起任何Friend关系,那这两个节点是不能产生直接通讯的,所以也就无从攻击起。如果这两个节点之间建立Friend可信的关系才能发起通讯,在这种机制下很大程度上制约了Ddos的攻击。
一部手机或者一台电脑可以生成不同的CarrierID,CarrierID本身有点类似于前面提到的钱包。因为Carrier那个节点是没有中央服务器的,所以所有节点的数据都保存在本地,包括你自身的ID和你自身的私钥。所以创建的时候就需要指定一个存储这些信息本地的路径,给定不同的路径都会生成不同的ID。如果给定路径之前已经包含这个ID了,Carrier就会从之前的ID里形成。
Friend的关系是什么呢?因为Carrier的设计原则是采用了Friend to Friend的设计,也就是在Carrier网络之上的节点,只有建立Friend的关系之后才可以直接建立通讯。所有上层API设计都是围绕Friend to Friend的原则展开的,Carrier很适合做IM这种应用,因为它本身是带有Friend to Friend关系的,类似于IOT的Getaway,手机客户端要和Getaway有个数量关系,它适合这样的场景。比如说开放下载,或者作为公共服务提供,Carrier本身设计初衷和设计场景不是为这样的场景服务的,所以这样的场景不太适合采用Carrier来实现,就是有所取,有所不取。你可以根据你应用的需要预先设定一些Friend的关系。另外也可以通过默认的配对码的形式,来后期自动建立这样Friend的关系,也是一个实现方案,这两种都可以,根据你的需要去走。
另外在DH网络里,每一个节点不会存储所有的节点表,会存储由算法决定的临近的节点表。不会存整网的节点表,会存一个片断,而这个片断保存在本地,下次会直接从本地保存的节点表里提取。
目前UDP数据报在开发的定义,我们目前限定是1K。
流式的就没有限制,反正它是个流不是数据报的形式。数据报和流跟UDC和TCP的表现形态是一样的,如果是数据报的形式,你发送多大就完成多大,而流式的就未必了,不能假定这边送了十个那边一定收到十个,它没有所谓报完的概念。
目前Carrier还没有大规模落地推广,所以节点数可能并不是很多,但是具体多少我们目前没有统计。随着未来亦来云对Carrier的推广落地的支持,和越来越应用的落地,这个节点后续会一直有持续的增长。
需要了解到的是,亦来云的节点跟别人是隔离的,所有亦来云的节点是一个独立的DHT网络。亦来云从公益的角度run了自己的bootstrap节点,所以大家bootstrap的时候都是从亦来云标准bootstrap节点起来。目前在开发测试阶段亦来云提供了一组标准的bootstrap,这组标准的bootstrap都buliding in到仓库里了,大家能拿到仓库下的代码,马上能bootstrap起来。
其实在网络上relay的节点越多,公共IP的节点越多,整个网络运行会越健壮。其实在所有DHT网络里都会有这个问题,如果在防火墙内部不能穿透的节点越多,网络的效率会越受影响。在亦来云Carrier的网络也是同样的,希望Carrier会维持一组公共节点来支持整个网络顺畅的运作,包括提供relay的支持,包括提供bootstrap。亦来云未来也会鼓励落地bootstrap节点,就是公共节点,因为公共节点越多对网络性能和健壮性会越好,所以亦来云将来也会奖励大家去run Carrier的公用节点。
Carrier中间所有的数据都有传输加密,比如说节点之间的数据传输,A结点到B节点的数据传输,是拿A和B的公钥、私钥做加密的,它是跟身份有关的加密上下文。所以A发给B的数据只有B能解密,B发给A的数据只有A能解密。因此重点截取数据,对截取者而言没有任何意义,他也不能对数据进行解密,所以不涉及到中间数据的泄露。