每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

CORNERSTONE | DevOps平台是如何实现开发效率的双倍提升?

CORNERSTONE 发表了文章 • 0 个评论 • 52 次浏览 • 17 小时前 • 来自相关话题

随着企业业务对软件系统日益依赖,IT管理与研发模式也随之对“敏捷”模式产生了需求,也就是今天人们时常提起的DevOps。提升效率,是DevOps实践的核心内容之一。就让我们来一起从软件生命周期的业务流与工作流,探讨DevOps实践效率提升的方向与方法吧。 ...查看全部

随着企业业务对软件系统日益依赖,IT管理与研发模式也随之对“敏捷”模式产生了需求,也就是今天人们时常提起的DevOps。提升效率,是DevOps实践的核心内容之一。就让我们来一起从软件生命周期的业务流与工作流,探讨DevOps实践效率提升的方向与方法吧。


一、CORNERSTONE | DevOps之“流”分析

软件工程将软件的生命周期定义为问题定义、需求分析、软件设计、程序编码、软件测试、运行维护等过程,无论是对于传统模式、敏捷模式还是DevOps模式,软件生命周期过程基本一致,如下图所示。
image.png


软件生命周期各个过程也组成了软件工程的“业务流”,而在不同团队采用相应地开发模式中,具体执行的开发及相关的活动,我们则成为工作流”。


CORNERSTONE,DevOps实践中,最主要改进的内容,就是对于这些 “工作流”的活动进行“关停并转”,从而实现整体与局部上对于效率的提升。


这些工作,也就是需要开展的活动,可以分为以下几类:


人与人的互动

这类活动交互的双方均为自然人,如业务需求收集,活动的特点是具备高度的不规则与不规律性。


人与机的互动

这类活动交互的一方为自然人,一方为依托于计算机的程序,如编码活动、人工审核/审批等,活动的特点是人的活动必须依循计算机相关主题的规则,部分活动可以抽取为规范化的过程。


机与机的互动

这类活动的特点是交互的双方都是依托于计算机的程序,如编译构建、自动化测试,活动的过程高度规范化。不同的作业类型,在效率提升的优化中,需要采用的方法各有不同。


二、CORNERSTONE | DevOps效率提升之协作

协作的本质是在不同的主体之间进行快速、有效的信息共享,从而进一步协调各主体进行步调一致、有序的工作执行,实现整体上的一致性与顺畅性,协作是DevOps实践中效率提升的重要方向和内容之一。

DevOps实践中的协作更多需要是从软件生命周期整体系统化考虑与设计,协作设计上面主要包括以下两个方面。

01、信息共享

传统的模式中,相关业务信息仅共享于各阶段内部,而在CORNERSTONE中,则更强调信息的跨阶段共享,面向产品的全生命周期,共享信息包括:

业务类信息
即业务目标、业务背景、业务需求、业务限制等信息。

执行类信息
即软件开发、编译、测试、部署等执行的相关信息,如开始时间、结束时间、执行时长、执行操作记录等。

反馈类信息
即各步骤、阶段执行的信息反馈,如需求拆分反馈、任务执行反馈、代码编译结果、测试结果、发布验证结果等。

CORNERSTONE为以上信息提供统一的信息管理与分析平台。对于代码编写之前的阶段提供如敏捷协同的工作协同管理模块,以记录需求、任务分配、需求完成进展等信息,对于代码编写之后的阶段,则提供相对完整的执行记录信息以及必要的通知信息,以构建及时的反馈。

02、协作调度

协作调度是DevOps协作实践中另外一项关键内容。通过CORNERSTONE平台,可实现对于“机与机的活动”全自动协作调度,对于“人与机的活动”简化协作调度,对于“人与人的活动”事件驱动协作调度,进而实现优化协作调度的效率,提升协作效果。

全自动协作调度
全自动的协作调度主要是通过CORNERSTONE平台的流水线引擎实现,通过流水线编排的实现指定作业流自动执行,执行过程中自动完成不同阶段的信息交互,过程无需人工参与。

简化的协作调度
简化的协作调度也是通过CORNERSTONE平台的流水线引擎实现,在流水线作业流中编排需要人工干预的节点,但仅需要人工给出通过/终止等简单的指令型信息即可。

基于事件的协作调度
基于事件驱动的协作调度,主要是用于“人与人的活动”,也可以用于“人与机的活动”,其通过通知、待办等事件方式,实现精准的信息共享与推送,驱动协作的下游方快速接受和推进事务工作。

CORNERSTONE中的协作调度的效果可以通过研发效能来进行初步的评估与衡量,通过衡量,我们可以较为清晰的获知哪个阶段的协调调度是关键阻碍点或可以进一步优化。

三、CORNERSTONE | DevOps效率提升之自动化

自动化是DevOps的核心理念,也是效率提升的最重要手段。通过CORNERSTONE一站式云端DevOps平台,实现软件过程自动化以及软件过程的支撑工作自动化。

CORNERSTONE | DevOps全流程解决方案

01、软件过程自动化

软件过程自动化是指在软件的开发、测试、部署等过程中,引入自动化的手段,从而实现快速的软件质量检查,以及软件应用发布。


开发过程自动化


CORNERSTONE的代码助手可帮助编程人员以最快的速度完成编程工作,比如当需要对外部的某个窗口进行操作时,CORNERSTONE的代码助手可进行探测,获取相关的窗口信息,再对其它进行操作等。

image.png


测试过程自动化

CORNERSTONE平台覆盖完整的测试流程,可进行测试用例的编写,建立用例库,减少重复性操作,让研发团队的协作更高效,产品交付更快速。常用的两个功能为:


1)测试用例管理


通过编写测试⽤例,制定测试计划并执⾏,测试结果可直接关联到缺陷,方便对问题进行跟踪处理,实现对迭代质量的全程把控。


 Clipboard Image.png


2)缺陷管理


强大的缺陷管理与统计功能,通过分组、解决状态、优先级等列表对缺陷进行全方位记录与跟踪,同时明确缺陷责任人,及时跟进解决缺陷;同时支持导入导出功能,导出时支持任意格式,不受模板限制。


Clipboard Image.png


部署过程自动化


CORNERSTONE支持依赖脚本pipeline实现的DevOps,支持持续集成与自动化部署,可直接在可视化的服务器上进行操作,同时满足多种开发语言,彻底解决敏捷开发在运维层面的瓶颈,方便开发人员对项目开发生命周期进行全盘管理。


Clipboard Image.png


通过流水线引擎,实现以上内容的自由、可视化编排,以及按需执行。


02、过程支撑自动化

软件过程支撑主要是指面向软件工程过程的支撑,实现自动化包括:


编译构建环境自动化

编译构建环境包括基于DevOps平台的自管理编译构建环境,按需生成编译构建环境,编译构建完成后自动销毁,以及特定编译构建环境的快速接入等。


测试环境自动化

测试环境自动化是指自动化测试执行所需的能力环境,如接口/UI测试脚本所需的执行环境,可以根据测试任务的需要,实现测试环境的弹性伸缩自管理。


环境部署自动化

环境部署自动化是指对于开发、测试、生产等所需要的基础环境,可以根据流水线自动完成环境的使用前的生成、使用后的回收等,实现资源即代码,无需人工参与。


CORNERSTONE中,通过大量的过程及支撑自动化,可以极大的减少开发、测试、运维等工作的人工参与时间,降低人工成本,并能实现人工无法完成的工作,例如快速对10000台服务器上的应用进行更新。但前期的建设需要涉及的技术点较多,成本也较为巨大,如何建设落地自动化,除了考虑效率之外,还需着重考虑业务平台的自主可控与可持续发展等方面。


四、CORNERSTONE | DevOps效率提升之持续优化

持续优化,是CORNERSTONE效率提升的第三个主要方面,也是践行DevOps理念的重要实践。持续优化需要解决优化什么、如何优化等问题。这些问题的解决,需要应用DevOps精益分析的理念实践。精益分析,本质就是对数据的统计、分析与挖掘。


01、数据获取

精益分析所涉及的数据应从需求提出到用户访问形成一个端到端闭环。数据的获取需要从业务系统本身以及支撑业务系统的CORNERSTONE平台两个方向获取。早期可以以CORNERSTONE平台相关数据的获取为主要来源,后续可持续集成来自业务系统埋点获取的数据。在整个过程中,需要做到数据的及时性、准确性与完整性。

02、数据分析

数据分析需要有明确的目标和针对性,如针对业务需求提出到上线的平均周期、开发返工趋势等,通过数据分析,可以快速找到当前影响效率的关键点,从而实现针对性的改善。

image.png

03、数据呈现

数据呈现即为数据应用,数据呈现可以采用两种方式进行。

协同管理
将数据获取/分析的结果,在CORNERSTONE的协同管理平台实时的反馈和呈现,从而推动PO/开发团队/干系人等根据反馈信息快速推进效率优化,通过量变引发质变,通过团队内自我优化的方式实现效率的提升。

度量分析
针对于与效率相关的重点指标,通过可视化图表等方式,进行专项的度量分析,并在管理与项目团队共享指标信息以及指标的变化趋势,通过全局监督的方式推进效率的提升。

五、结论

文化上的协同打破了流程与部门的屏障,共享了信息,协作了调度;过程中的自动化消除了重复性的工作,降低人为风险;业务系统与CORNERSTONE平台的数据支持精准提供优化的方向。DevOps之所以能为企业提升效率在于DevOps的实践实现软件生命周期的业务流与作业流的一致与顺畅。

写了一个100%Go语言的Web-Term-SSH 堡垒机项目欢迎大家拍砖

回复

jjjjerk 发起了问题 • 1 人关注 • 0 个回复 • 131 次浏览 • 1 天前 • 来自相关话题

Go语言自定义自己的SSH-Server

jjjjerk 发表了文章 • 0 个评论 • 146 次浏览 • 1 天前 • 来自相关话题

原文地址  ...查看全部

Golang-Docker ChromeDP浏览器模拟和截图微服务

jjjjerk 发表了文章 • 0 个评论 • 216 次浏览 • 2 天前 • 来自相关话题

原文地址  ...查看全部

用 Go 語言實作 Job Queue 機制

appleboy 发表了文章 • 0 个评论 • 284 次浏览 • 4 天前 • 来自相关话题

很高興可以在  ...查看全部

很高興可以在 Mopcon 分享『用 Go 語言實現 Job Queue 機制』,透過簡單的 goroutine  channel 就可以實現簡單 Queue 機制,並且限制同時可以執行多少個 Job,才不會讓系統超載。最後透過編譯放進 Docker 容器內,就可以跑在各種環境上,加速客戶安裝及部署。

議程大綱

本次大致上整理底下幾個重點:

  1. What is the different unbuffered and buffered channel?
  2. How to implement a job queue in golang?
  3. How to stop the worker in a container?
  4. Shutdown with Sigterm Handling.
  5. Canceling Workers without Context.
  6. Graceful shutdown with worker.
  7. How to auto-scaling build agent?
  8. How to cancel the current Job?

由於在投影片內也許寫得不夠詳細,所以我打算錄製一份影片放在 Udemy 教學影片上,如果有興趣可以參考底下影片連結:

之前的教學影片也可以直接參考底下連結:

投影片

https://www.slideshare.net/appleboy/job-queue-in-golang-184064840

袋鼠存储 v1.3 正式支持移动端

fabsnail 发表了文章 • 0 个评论 • 260 次浏览 • 4 天前 • 来自相关话题

自袋鼠存储(roostore.com)发布以来,感谢各位的认可,下载使用和积极反馈袋鼠存储致力于为用户提供一种新的存储解决方案,使得用户对 ...查看全部

自袋鼠存储(roostore.com)发布以来,感谢各位的认可,下载使用和积极反馈

袋鼠存储致力于为用户提供一种新的存储解决方案,使得用户对服务可控,对数据可控还有对成本可控

现正式推出 v1.3 版本,该版本包含移动端安卓版,更进一步方便用户使用:

kstore

1. 支持嵌入式提供服务,为移动端提供集成使用
2. 支持跨节点在线查看文件,为移动端提供在线查看图片,播放视频等
3. 提供注册登陆口令控制项,确保公网中的私人节点只允许有口令的用户使用
4. 修复浏览文件夹时滚动条可能不显示问题
5. 修复某些浏览器中点击下载文件无响应问题
6. 修复协程上下文资源未及时释放问题
7. 修复自动登陆或浏览文件夹时可能出现的阻塞问题
8. 修复长时间运行过程中周期性查找更多可用连接节点时可能出现的并发崩溃问题


移动端(安卓版首发)
1. 支持在指定的服务器上进行注册,登陆
2. 支持使用集成服务,满足无自部署 kstore 服务时使用
3. 提供断点上传手机中的文件,支持暂停、恢复,取消和清空(已完成)任务
4. 提供断点下载文件到手机,支持暂停,恢复,取消和清空(已完成)任务
5. 提供将下载的文件分享发送给其他应用
6. 提供文件浏览,创建删除文件(夹)
7. 提供文件剪切,复制,粘贴,重命名以及查看文件详细信息等
8. 支持下拉刷新文件列表
9. 支持查看图片(jpg, jpeg, png, gif, svg等格式),包括查看其他 kstore 节点中的图片(不存储文件到本地)
10. 支持播放视频(mp4, mov),包括查看其他 kstore 节点中的视频(不存储文件到本地)
11. 支持 admin 后台管理(目前仅支持网络管理部分)
12. 支持是否显示目录大小选项设置
13. 提供帮助与反馈渠道
14. 提供将 kstore-app 推荐给好友


感兴趣的朋友,欢迎通过官网 roostore.com 下载使用

注:iPhone 版本正在努力攻关一些关键技术问题,相信很快也会与大家见面

go 学习笔记之解读什么是defer延迟函数

snowdreams1006 发表了文章 • 0 个评论 • 234 次浏览 • 5 天前 • 来自相关话题

Go 语言中有个 defer 关键字,常用于实现延迟函数来保证关键代码的最终执行,常言道: "未雨绸缪方可有备无患".


延迟函数就是这么一种机制,无论程序是正常返回还是异常报错,只要存在延迟函数都能保证这部分关键逻辑最终执行,所以用来做些资源清理等操作再合适不过了.


go-error-about-defer.jpg
go-error-about-defer.jpg

出入成双有始有终


日常开发编程中,有些操作总是成双成对出现的,有开始就有结束,有打开就要关闭,还有一些连续依赖关系等等.


一般来说,我们需要控制结束语句,在合适的位置和时机控制结束语句,手动保证整个程序有始有终,不遗漏清理收尾操作.


最常见的拷贝文件操作大致流程如下:



  1. 打开源文件


srcFile, err := os.Open("fib.txt")
if err != nil {
t.Error(err)
return
}


  1. 创建目标文件


dstFile, err := os.Create("fib.txt.bak")
if err != nil {
t.Error(err)
return
}


  1. 拷贝源文件到目标文件


io.Copy(dstFile, srcFile)


  1. 关闭目标文件


dstFile.Close()
srcFile.Close()


  1. 关闭源文件


srcFile.Close()

值得注意的是: 这种拷贝文件的操作需要特别注意操作顺序而且也不要忘记释放资源,比如先打开再关闭等等!


func TestCopyFileWithoutDefer(t *testing.T) {
srcFile, err := os.Open("fib.txt")
if err != nil {
t.Error(err)
return
}

dstFile, err := os.Create("fib.txt.bak")
if err != nil {
t.Error(err)
return
}

io.Copy(dstFile, srcFile)

dstFile.Close()
srcFile.Close()
}


「雪之梦技术驿站」: 上述代码逻辑还是清晰简单的,可能不会忘记释放资源也能保证操作顺序,但是如果逻辑代码比较复杂的情况,这时候就有一定的实现难度了!



可能是为了简化类似代码的逻辑,Go 语言引入了 defer 关键字,创造了"延迟函数"的概念.



  • defer 的文件拷贝


func TestCopyFileWithoutDefer(t *testing.T) {
if srcFile, err := os.Open("fib.txt"); err != nil {
t.Error(err)
return
} else {
if dstFile,err := os.Create("fib.txt.bak");err != nil{
t.Error(err)
return
}else{
io.Copy(dstFile,srcFile)

dstFile.Close()
srcFile.Close()
}
}
}


  • defer 的文件拷贝


func TestCopyFileWithDefer(t *testing.T) {
if srcFile, err := os.Open("fib.txt"); err != nil {
t.Error(err)
return
} else {
defer srcFile.Close()

if dstFile, err := os.Create("fib.txt.bak"); err != nil {
t.Error(err)
return
} else {
defer dstFile.Close()

io.Copy(dstFile, srcFile)
}
}
}

上述示例代码简单展示了 defer 关键字的基本使用方式,显著的好处在于 Open/Close 是一对操作,不会因为写到最后而忘记 Close 操作,而且连续依赖时也能正常保证延迟时机.


简而言之,如果函数内部存在连续依赖关系,也就是说创建顺序是 A->B->C 而销毁顺序是 C->B->A.这时候使用 defer 关键字最合适不过.


懒人福音延迟函数



官方文档相关表述见 Defer statements[1]



如果没有 defer 延迟函数前,普通函数正常运行:


func TestFuncWithoutDefer(t *testing.T) {
// 「雪之梦技术驿站」: 正常顺序
t.Log("「雪之梦技术驿站」: 正常顺序")

// 1 2
t.Log(1)
t.Log(2)
}

当添加 defer 关键字实现延迟后,原来的 1 被推迟到 2 后面而不是之前的 1 2 顺序.


func TestFuncWithDefer(t *testing.T) {
// 「雪之梦技术驿站」: 正常顺序执行完毕后才执行 defer 代码
t.Log(" 「雪之梦技术驿站」: 正常顺序执行完毕后才执行 defer 代码")

// 2 1
defer t.Log(1)
t.Log(2)
}

如果存在多个 defer 关键字,执行顺序可想而知,越往后的越先执行,这样才能保证按照依赖顺序依次释放资源.


func TestFuncWithMultipleDefer(t *testing.T) {
// 「雪之梦技术驿站」: 猜测 defer 底层实现数据结构可能是栈,先进后出.
t.Log(" 「雪之梦技术驿站」: 猜测 defer 底层实现数据结构可能是栈,先进后出.")

// 3 2 1
defer t.Log(1)
defer t.Log(2)
t.Log(3)
}

相信你已经明白了多个 defer 语句的执行顺序,那就测试一下吧!


func TestFuncWithMultipleDeferOrder(t *testing.T) {
// 「雪之梦技术驿站」: defer 底层实现数据结构类似于栈结构,依次倒叙执行多个 defer 语句
t.Log(" 「雪之梦技术驿站」: defer 底层实现数据结构类似于栈结构,依次倒叙执行多个 defer 语句")

// 2 3 1
defer t.Log(1)
t.Log(2)
defer t.Log(3)
}

初步认识了 defer 延迟函数的使用情况后,我们再结合文档详细解读一下相关定义.



  • 英文原版文档



A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns,either because the surrounding function executed a return statement,reached the end of its function body,or because the corresponding goroutine is panicking.




  • 中文翻译文档



"defer"语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻,这是因为周围函数执行了一个return语句,到达了函数体的末尾,或者是因为相应的协程正在惊慌.



具体来说,延迟函数的执行时机大概分为三种情况:


周围函数执行 return



because the surrounding function executed a return statement



return 后面的 t.Log(4) 语句自然是不会运行的,程序最终输出结果为 3 2 1 说明了 defer 语句会在周围函数执行 return 前依次逆序执行.


func funcWithMultipleDeferAndReturn() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
return
fmt.Println(4)
}

func TestFuncWithMultipleDeferAndReturn(t *testing.T) {
// 「雪之梦技术驿站」: defer 延迟函数会在包围函数正常return之前逆序执行.
t.Log(" 「雪之梦技术驿站」: defer 延迟函数会在包围函数正常return之前逆序执行.")

// 3 2 1
funcWithMultipleDeferAndReturn()
}

周围函数到达函数体



reached the end of its function body



周围函数的函数体运行到结尾前逆序执行多个 defer 语句,即先输出 3 后依次输出 2 1.
最终函数的输出结果是 3 2 1 ,也就说是没有 return 声明也能保证结束前执行完 defer 延迟函数.


func funcWithMultipleDeferAndEnd() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
}

func TestFuncWithMultipleDeferAndEnd(t *testing.T) {
// 「雪之梦技术驿站」: defer 延迟函数会在包围函数到达函数体结尾之前逆序执行.
t.Log(" 「雪之梦技术驿站」: defer 延迟函数会在包围函数到达函数体结尾之前逆序执行.")

// 3 2 1
funcWithMultipleDeferAndEnd()
}

当前协程正惊慌失措



because the corresponding goroutine is panicking



周围函数万一发生 panic 时也会先运行前面已经定义好的 defer 语句,而 panic 后续代码因为没有特殊处理,所以程序崩溃了也就无法运行.


函数的最终输出结果是 3 2 1 panic ,如此看来 defer 延迟函数还是非常尽忠职守的,虽然心里很慌但还是能保证老弱病残先行撤退!


func funcWithMultipleDeferAndPanic() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
panic("panic")
fmt.Println(4)
}

func TestFuncWithMultipleDeferAndPanic(t *testing.T) {
// 「雪之梦技术驿站」: defer 延迟函数会在包围函数panic惊慌失措之前逆序执行.
t.Log(" 「雪之梦技术驿站」: defer 延迟函数会在包围函数panic惊慌失措之前逆序执行.")

// 3 2 1
funcWithMultipleDeferAndPanic()
}

通过解读 defer 延迟函数的定义以及相关示例,相信已经讲清楚什么是 defer 延迟函数了吧?


简单地说,延迟函数就是一种未雨绸缪的规划机制,帮助开发者编程程序时及时做好收尾善后工作,提前做好预案以准备随时应对各种情况.



  • 当周围函数正常执行到到达函数体结尾时,如果发现存在延迟函数自然会逆序执行延迟函数.

  • 当周围函数正常执行遇到 return 语句准备返回给调用者时,存在延迟函数时也会执行,同样满足善后清理的需求.

  • 当周围函数异常运行不小心 panic 惊慌失措时,程序存在延迟函数也不会忘记执行,提前做好预案发挥了作用.


所以不论是正常运行还是异常运行,提前做好预案总是没错的,基本上可以保证万无一失,所以不妨考虑考虑 defer 延迟函数?


go-error-about-lovely.png
go-error-about-lovely.png

延迟函数应用场景


基本上成双成对的操作都可以使用延迟函数,尤其是申请的资源前后存在依赖关系时更应该使用 defer 关键字来简化处理逻辑.


下面举两个常见例子来说明延迟函数的应用场景.



  • Open/Close


文件操作一般会涉及到打开和开闭操作,尤其是文件之间拷贝操作更是有着严格的顺序,只需要按照申请资源的顺序紧跟着defer 就可以满足资源释放操作.


func readFileWithDefer(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
return ioutil.ReadAll(f)
}


  • Lock/Unlock


锁的申请和释放是保证同步的一种重要机制,需要申请多个锁资源时可能存在依赖关系,不妨尝试一下延迟函数!


var mu sync.Mutex
var m = make(map[string]int)
func lookupWithDefer(key string) int {
mu.Lock()
defer mu.Unlock()
return m[key]
}

总结以及下节预告


defer 延迟函数是保障关键逻辑正常运行的一种机制,如果存在多个延迟函数的话,一般会按照逆序的顺序运行,类似于栈结构.


延迟函数的运行时机一般有三种情况:



  • 周围函数遇到返回时


func funcWithMultipleDeferAndReturn() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
return
fmt.Println(4)
}


  • 周围函数函数体结尾处


func funcWithMultipleDeferAndEnd() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
}


  • 当前协程惊慌失措中


func funcWithMultipleDeferAndPanic() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
panic("panic")
fmt.Println(4)
}

本文主要介绍了什么是 defer 延迟函数,通过解读官方文档并配套相关代码认识了延迟函数,但是延迟函数中存在一些可能令人比较迷惑的地方.


go-error-about-question.png
go-error-about-question.png

读者不妨看一下下面的代码,将心里的猜想和实际运行结果比较一下,我们下次再接着分享,感谢你的阅读.


func deferFuncWithAnonymousReturnValue() int {
var retVal int
defer func() {
retVal++
}()
return 0
}

func deferFuncWithNamedReturnValue() (retVal int) {
defer func() {
retVal++
}()
return 0
}

延伸阅读参考文档



  • Defer_statements[2]

  • go 语言的 defer 语句[3]

  • Go defer 实现原理剖析[4]

  • go 语言 defer 你不知道的秘密![5]

  • Go 语言中 defer 的一些坑[6]

  • go defer (go 延迟函数)[7]



如果本文对你有所帮助,不用赞赏,点赞鼓励一下就是最大的认可,顺便也可以关注下微信公众号「 雪之梦技术驿站 」哟!



雪之梦技术驿站.png
雪之梦技术驿站.png

参考资料



[1]

Defer statements: https://golang.google.cn/ref/spec#Defer_statements



[2]

Defer_statements: https://golang.google.cn/ref/spec#Defer_statements



[3]

go语言的defer语句: https://www.jianshu.com/p/5b0b36f398a2



[4]

Go defer实现原理剖析: https://studygolang.com/articles/16067



[5]

go语言 defer 你不知道的秘密!: https://www.cnblogs.com/baizx/p/5024547.html



[6]

Go语言中defer的一些坑: https://www.jianshu.com/p/79c029c0bd58



[7]

go defer (go延迟函数): https://www.cnblogs.com/ysherlock/p/8150726.html



为什么大公司一定要使用 DevOps?

回复

CORNERSTONE 发起了问题 • 1 人关注 • 0 个回复 • 139 次浏览 • 5 天前 • 来自相关话题

Nebula 架构剖析系列(一)图数据库的存储设计

NebulaGraph 发表了文章 • 0 个评论 • 280 次浏览 • 2019-10-15 17:05 • 来自相关话题

摘要在讨论某个数据库时,存储 ( Storage ) 和计算 ( Query Engine ) 通常是讨论的热点,也是爱好者们了解某个数据库不可或缺的部分。每个数据库都有其独有的存储、计算方式,今天就和图图来学习下图数据库 Nebula ...查看全部

摘要

在讨论某个数据库时,存储 ( Storage ) 和计算 ( Query Engine ) 通常是讨论的热点,也是爱好者们了解某个数据库不可或缺的部分。每个数据库都有其独有的存储、计算方式,今天就和图图来学习下图数据库 Nebula Graph 的存储部分。

Nebula 的 Storage 包含两个部分, 一是 meta 相关的存储, 我们称之为 Meta Service ,另一个是 data 相关的存储, 我们称之为 Storage Service。 这两个服务是两个独立的进程,数据也完全隔离,当然部署也是分别部署, 不过两者整体架构相差不大,本文最后会提到这点。 如果没有特殊说明,本文中 Storage Service 代指 data 的存储服务。接下来,大家就随我一起看一下 Storage Service 的整个架构。 Let's go~

Architecture

 图一  storage service 架构图

如图1 所示,Storage Service 共有三层,最底层是 Store Engine,它是一个单机版 local store engine,提供了对本地数据的 get / put / scan / delete 操作,相关的接口放在 KVStore / KVEngine.h 文件里面,用户完全可以根据自己的需求定制开发相关 local store plugin,目前 Nebula 提供了基于 RocksDB 实现的  Store Engine。

在 local store engine 之上,便是我们的 Consensus 层,实现了 Multi Group Raft,每一个 Partition 都对应了一组 Raft Group,这里的 Partition 便是我们的数据分片。目前 Nebula 的分片策略采用了 静态 Hash 的方式,具体按照什么方式进行 Hash,在下一个章节 schema 里会提及。用户在创建 SPACE 时需指定 Partition 数,Partition 数量一旦设置便不可更改,一般来讲,Partition 数目要能满足业务将来的扩容需求。

在 Consensus 层上面也就是 Storage Service 的最上层,便是我们的 Storage interfaces,这一层定义了一系列和图相关的 API。 这些 API 请求会在这一层被翻译成一组针对相应 Partition 的 kv 操作。正是这一层的存在,使得我们的存储服务变成了真正的图存储,否则,Storage Service 只是一个 kv 存储罢了。而 Nebula 没把 kv 作为一个服务单独提出,其最主要的原因便是图查询过程中会涉及到大量计算,这些计算往往需要使用图的 schema,而 kv 层是没有数据 schema 概念,这样设计会比较容易实现计算下推。

Schema & Partition

图存储的主要数据是点和边,但 Nebula 存储的数据是一张属性图,也就是说除了点和边以外,Nebula 还存储了它们对应的属性,以便更高效地使用属性过滤。

对于点来说,我们使用不同的 Tag 表示不同类型的点,同一个 VertexID 可以关联多个 Tag,而每一个 Tag 都有自己对应的属性。对应到 kv 存储里面,我们使用 vertexID + TagID 来表示 key,  我们把相关的属性编码后放在 value 里面,具体 key 的 format 如图2 所示:

 图二 Vertex Key Format

  • Type :  1 个字节,用来表示 key 类型,当前的类型有 data, index, system 等
  • Part ID : 3 个字节,用来表示数据分片 Partition,此字段主要用于 Partition 重新分布(balance) 时方便根据前缀扫描整个 Partition 数据
  • Vertex ID : 4 个字节, 用来表示点的 ID
  • Tag ID : 4 个字节, 用来表示关联的某个 tag
  • Timestamp : 8 个字节,对用户不可见,未来实现分布式事务 ( MVCC ) 时使用

在一个图中,每一条逻辑意义上的边,在 Nebula Graph 中会建模成两个独立的 key-value,分别称为 out-key 和in-key。out-key 与这条边所对应的起点存储在同一个 partition 上,in-key 与这条边所对应的终点存储在同一个partition 上。通常来说,out-key 和 in-key 会分布在两个不同的 Partition 中。

两个点之间可能存在多种类型的边,Nebula 用 Edge Type 来表示边类型。而同一类型的边可能存在多条,比如,定义一个 edge type "转账",用户 A 可能多次转账给 B, 所以 Nebula 又增加了一个 Rank 字段来做区分,表示 A 到 B 之间多次转账记录。 Edge key 的 format 如图3 所示:

 图三 Edge Key Format

  • Type :  1 个字节,用来表示 key 的类型,当前的类型有 data, index, system 等。
  • Part ID : 3 个字节,用来表示数据分片 Partition,此字段主要用于 Partition 重新分布(balance) 时方便根据前缀扫描整个 Partition 数据
  • Vertex ID : 4 个字节, 出边里面用来表示源点的 ID, 入边里面表示目标点的 ID。
  • Edge Type : 4 个字节, 用来表示这条边的类型,如果大于 0 表示出边,小于 0 表示入边。
  • Rank : 4 个字节,用来处理同一种类型的边存在多条的情况。用户可以根据自己的需求进行设置,这个字段可_存放交易时间_、交易流水号、或_某个排序权重_
  • Vertex ID : 4 个字节,  出边里面用来表示目标点的 ID, 入边里面表示源点的 ID。
  • Timestamp : 8 个字节,对用户不可见,未来实现分布式做事务的时候使用。

针对 Edge Type 的值,若如果大于 0 表示出边,则对应的 edge key format 如图4 所示;若 Edge Type 的值小于 0,则对应的 edge key format 如图5 所示

 图4 出边的 Key Format  图5 入边的 Key Format

对于点或边的属性信息,有对应的一组 kv pairs,Nebula 将它们编码后存在对应的 value 里。由于 Nebula 使用强类型 schema,所以在解码之前,需要先去 Meta Service 中取具体的 schema 信息。另外,为了支持在线变更 schema,在编码属性时,会加入对应的 schema 版本信息,具体的编解码细节在这里不作展开,后续会有专门的文章讲解这块内容。

OK,到这里我们基本上了解了 Nebula 是如何存储数据的,那数据是如何进行分片呢?很简单,对 Vertex ID 取模 即可。通过对 Vertex ID 取模,同一个点的所有_出边_,_入边_以及这个点上所有关联的 _Tag 信息_都会被分到同一个 Partition,这种方式大大地提升了查询效率。对于在线图查询来讲,最常见的操作便是从一个点开始向外 BFS(广度优先)拓展,于是拿一个点的出边或者入边是最基本的操作,而这个操作的性能也决定了整个遍历的性能。BFS 中可能会出现按照某些属性进行剪枝的情况,Nebula 通过将属性与点边存在一起,来保证整个操作的高效。当前许多的图数据库通过 Graph 500 或者 Twitter 的数据集试来验证自己的高效性,这并没有代表性,因为这些数据集没有属性,而实际的场景中大部分情况都是属性图,并且实际中的 BFS 也需要进行大量的剪枝操作。

KVStore

为什么要自己做 KVStore,这是我们无数次被问起的问题。理由很简单,当前开源的 KVStore 都很难满足我们的要求:

  • 性能性能性能:Nebula 的需求很直接:高性能 pure kv;
  • 以 library 的形式提供:对于强 schema 的 Nebula 来讲,计算下推需要 schema 信息,而计算下推实现的好坏,是 Nebula 是否高效的关键;
  • 数据强一致:这是分布式系统决定的;
  • 使用 C++实现:这由团队的技术特点决定;

基于上述要求,Nebula 实现了自己的 KVStore。当然,对于性能完全不敏感且不太希望搬迁数据的用户来说,Nebula 也提供了整个KVStore 层的 plugin,直接将 Storage Service 搭建在第三方的 KVStore 上面,目前官方提供的是 HBase 的 plugin。

Nebula KVStore 主要采用 RocksDB 作为本地的存储引擎,对于多硬盘机器,为了充分利用多硬盘的并发能力,Nebula 支持自己管理多块盘,用户只需配置多个不同的数据目录即可。分布式 KVStore 的管理由 Meta Service 来统一调度,它记录了所有 Partition 的分布情况,以及当前机器的状态,当用户增减机器时,只需要通过 console 输入相应的指令,Meta Service 便能够生成整个 balance plan 并执行。(之所以没有采用完全自动 balance 的方式,主要是为了减少数据搬迁对于线上服务的影响,balance 的时机由用户自己控制。)

为了方便对于 WAL 进行定制,Nebula KVStore 实现了自己的 WAL 模块,每个 partition 都有自己的 WAL,这样在追数据时,不需要进行 wal split 操作, 更加高效。 另外,为了实现一些特殊的操作,专门定义了 Command Log 这个类别,这些 log 只为了使用 Raft 来通知所有 replica 执行某一个特定操作,并没有真正的数据。除了 Command Log 外,Nebula 还提供了一类日志来实现针对某个 Partition 的 atomic operation,例如 CAS,read-modify-write,  它充分利用了Raft 串行的特性。

关于多图空间(space)的支持:一个 Nebula KVStore 集群可以支持多个 space,每个 space 可设置自己的 partition 数和 replica 数。不同 space 在物理上是完全隔离的,而且在同一个集群上的不同 space 可支持不同的 store engine 及分片策略。

Raft

作为一个分布式系统,KVStore 的 replication,scale out 等功能需 Raft 的支持。当前,市面上讲 Raft 的文章非常多,具体原理性的内容,这里不再赘述,本文主要说一些 Nebula Raft 的一些特点以及工程实现。

Multi Raft Group

由于 Raft 的日志不允许空洞,几乎所有的实现都会采用 Multi Raft Group 来缓解这个问题,因此 partition 的数目几乎决定了整个 Raft Group 的性能。但这也并不是说 Partition 的数目越多越好:每一个 Raft Group 内部都要存储一系列的状态信息,并且每一个 Raft Group 有自己的 WAL 文件,因此 Partition 数目太多会增加开销。此外,当 Partition 太多时, 如果负载没有足够高,batch 操作是没有意义的。比如,一个有 1w tps 的线上系统单机,它的单机 partition 的数目超过 1w,可能每个 Partition 每秒的 tps 只有 1,这样 batch 操作就失去了意义,还增加了 CPU 开销。 实现 Multi Raft Group 的最关键之处有两点,** 第一是共享 Transport 层**,因为每一个 Raft Group 内部都需要向对应的 peer  发送消息,如果不能共享 Transport 层,连接的开销巨大;第二是线程模型,Mutli Raft Group 一定要共享一组线程池,否则会造成系统的线程数目过多,导致大量的 context switch 开销。

Batch

对于每个 Partition来说,由于串行写 WAL,为了提高吞吐,做 batch 是十分必要的。一般来讲,batch 并没有什么特别的地方,但是 Nebula 利用每个 part 串行的特点,做了一些特殊类型的 WAL,带来了一些工程上的挑战。

举个例子,Nebula 利用 WAL 实现了无锁的 CAS 操作,而每个 CAS 操作需要之前的 WAL 全部 commit 之后才能执行,所以对于一个 batch,如果中间夹杂了几条 CAS 类型的 WAL, 我们还需要把这个 batch 分成粒度更小的几个 group,group 之间保证串行。还有,command 类型的 WAL 需要它后面的 WAL 在其 commit 之后才能执行,所以整个 batch 划分 group 的操作工程实现上比较有特色。

Learner

Learner 这个角色的存在主要是为了 应对扩容 时,新机器需要"追"相当长一段时间的数据,而这段时间有可能会发生意外。如果直接以 follower 的身份开始追数据,就会使得整个集群的 HA 能力下降。 Nebula 里面 learner 的实现就是采用了上面提到的 command wal,leader 在写 wal 时如果碰到 add learner 的 command, 就会将 learner 加入自己的 peers,并把它标记为 learner,这样在统计多数派的时候,就不会算上 learner,但是日志还是会照常发送给它们。当然 learner 也不会主动发起选举。

Transfer Leadership

Transfer leadership 这个操作对于 balance 来讲至关重要,当我们把某个 Paritition 从一台机器挪到另一台机器时,首先便会检查 source 是不是 leader,如果是的话,需要先把他挪到另外的 peer 上面;在搬迁数据完毕之后,通常还要把 leader 进行一次 balance,这样每台机器承担的负载也能保证均衡。

实现 transfer leadership, 需要注意的是 leader 放弃自己的 leadership,和 follower 开始进行 leader election 的时机。对于 leader 来讲,当 transfer leadership command 在 commit 的时候,它放弃 leadership;而对于 follower 来讲,当收到此 command 的时候就要开始进行 leader election, 这套实现要和 Raft 本身的 leader election 走一套路径,否则很容易出现一些难以处理的 corner case。

Membership change

为了避免脑裂,当一个 Raft Group 的成员发生变化时,需要有一个中间状态, 这个状态下 old group 的多数派与 new group 的多数派总是有 overlap,这样就防止了 old group 或者新 group 单方面做出决定,这就是论文中提到的 joint consensus 。为了更加简化,Diego Ongaro 在自己的博士论文中提出每次增减一个 peer 的方式以保证 old group 的多数派总是与 new group 的多数派有 overlap。 Nebula 的实现也采用了这个方式,只不过 add member 与 remove member 的实现有所区别,具体实现方式本文不作讨论,有兴趣的同学可以参考 Raft Part class 里面 addPeer  /  removePeer  的实现。

Snapshot

Snapshot 如何与 Raft 流程结合起来,论文中并没有细讲,但是这一部分我认为是一个 Raft 实现里最容易出错的地方,因为这里会产生大量的 corner case。

举一个例子,当 leader 发送 snapshot 过程中,如果 leader 发生了变化,该怎么办? 这个时候,有可能 follower 只接到了一半的 snapshot 数据。 所以需要有一个 Partition 数据清理过程,由于多个 Partition 共享一份存储,因此如何清理数据又是一个很麻烦的问题。另外,snapshot 过程中,会产生大量的 IO,为了性能考虑,我们不希望这个过程与正常的 Raft 共用一个 IO threadPool,并且整个过程中,还需要使用大量的内存,如何优化内存的使用,对于性能十分关键。由于篇幅原因,我们并不会在本文对这些问题展开讲述,有兴趣的同学可以参考 SnapshotManager  的实现。

Storage Service

在 KVStore 的接口之上,Nebula 封装有图语义接口,主要的接口如下:

  • getNeighbors :  查询一批点的出边或者入边,返回边以及对应的属性,并且需要支持条件过滤;
  • Insert vertex/edge :  插入一条点或者边及其属性;
  • getProps : 获取一个点或者一条边的属性;

这一层会将图语义的接口转化成 kv 操作。为了提高遍历的性能,还要做并发操作。

Meta Service

在 KVStore 的接口上,Nebula 也同时封装了一套 meta 相关的接口。Meta Service 不但提供了图 schema 的增删查改的功能,还提供了集群的管理功能以及用户鉴权相关的功能。Meta Service 支持单独部署,也支持使用多副本来保证数据的安全。

总结

这篇文章给大家大致介绍了 Nebula Storage 层的整体设计, 由于篇幅原因, 很多细节没有展开讲, 欢迎大家到我们的微信群里提问,加入 Nebula Graph 交流群,请联系 Nebula Graph 官方小助手微信号:NebulaGraphbot。

相关阅读

附录

Nebula Graph:一个开源的分布式图数据库。

GitHub:https://github.com/vesoft-inc/nebula

知乎:https://www.zhihu.com/org/nebulagraph/posts

微博:https://weibo.com/nebulagraph

HTTP-Reverse-Proxy反向代理Nginx硬件指纹校验

jjjjerk 发表了文章 • 0 个评论 • 280 次浏览 • 2019-10-15 15:06 • 来自相关话题

原文地址 https://moj ...查看全部

Nebula 架构剖析系列(零)图数据库的整体架构设计

NebulaGraph 发表了文章 • 0 个评论 • 261 次浏览 • 2019-10-14 16:59 • 来自相关话题

Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构。 ...查看全部

Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构。



一个完整的 Nebula 部署集群包含三个服务,即  Query Service,Storage Service 和 Meta Service。每个服务都有其各自的可执行二进制文件,这些二进制文件既可以部署在同一组节点上,也可以部署在不同的节点上。


Meta Service


上图为 Nebula Graph 的架构图,其右侧为 Meta Service 集群,它采用 leader / follower 架构。Leader 由集群中所有的 Meta Service 节点选出,然后对外提供服务。Followers 处于待命状态并从 leader 复制更新的数据。一旦 leader 节点 down 掉,会再选举其中一个 follower 成为新的 leader。


Meta Service 不仅负责存储和提供图数据的 meta 信息,如 schema、partition 信息等,还同时负责指挥数据迁移及 leader 的变更等运维操作。


存储计算分离


在架构图中 Meta Service 的左侧,为 Nebula Graph 的主要服务,Nebula 采用存储与计算分离的架构,虚线以上为计算,以下为存储。


存储计算分离有诸多优势,最直接的优势就是,计算层和存储层可以根据各自的情况弹性扩容、缩容。


存储计算分离还带来的另一个优势:使水平扩展成为可能。


此外,存储计算分离使得 Storage Service 可以为多种类型的个计算层或者计算引擎提供服务。当前 Query Service 是一个高优先级的计算层,而各种迭代计算框架会是另外一个计算层。


无状态计算层


现在我们来看下计算层,每个计算节点都运行着一个无状态的查询计算引擎,而节点彼此间无任何通信关系。计算节点仅从 Meta Service 读取 meta 信息,以及和 Storage Service 进行交互。这样设计使得计算层集群更容易使用 K8s 管理或部署在云上。


计算层的负载均衡有两种形式,最常见的方式是在计算层上加一个负载均衡(balance),第二种方法是将计算层所有节点的 IP 地址配置在客户端中,这样客户端可以随机选取计算节点进行连接。


每个查询计算引擎都能接收客户端的请求,解析查询语句,生成抽象语法树(AST)并将 AST 传递给执行计划器和优化器,最后再交由执行器执行。


Shared-nothing 分布式存储层


Storage Service 采用 shared-nothing 的分布式架构设计,每个存储节点都有多个本地 KV 存储实例作为物理存储。Nebula 采用多数派协议 Raft 来保证这些 KV 存储之间的一致性(由于 Raft 比 Paxo 更简洁,我们选用了 Raft )。在 KVStore 之上是图语义层,用于将图操作转换为下层 KV 操作。


图数据(点和边)是通过 Hash 的方式存储在不同 Partition 中。这里用的 Hash 函数实现很直接,即 vertex_id 取余 Partition 数。在 Nebula Graph 中,Partition 表示一个虚拟的数据集,这些 Partition 分布在所有的存储节点,分布信息存储在 Meta Service 中(因此所有的存储节点和计算节点都能获取到这个分布信息)。


附录


Nebula Graph GitHub 地址:github.com/vesoft-inc/nebula,加入 Nebula Graph 交流群,请联系 Nebula Graph 官方小助手微信号:NebulaGraphbot



Nebula Graph:一个开源的分布式图数据库。




GitHub:github.com/vesoft-inc/nebula



知乎:www.zhihu.com/org/nebulag…




微博:weibo.com/nebulagraph

Open Source v.s. Open Core

NebulaGraph 发表了文章 • 1 个评论 • 399 次浏览 • 2019-10-11 10:27 • 来自相关话题

摘要

本文翻译自 CMSWire 网站的《Open Source vs. Open Core: What's the Difference?》,主要介绍 Open Source 和 Open Core 的区别。Open Source 已广为人知,那么 Open Core 又是什么,在开源软件盛行的今天,二者会怎样影响这个市场呢?

开篇之前,我们先回到一个 2013 年 CMSWire 向行业内专家提出一个问题:专有软件( proprietary software )和开源软件 ( open source),哪个更好?当时就这个问题业内人士没有达成共识,而现在这个问题似乎已经失去其存在价值。

开源无处不在

Constellation Research 副总裁兼首席分析师 Holger Mueller 曾表示——“开源无处不在“,而专有软件供应商过去的经历也证实了这一点。开源代码促进了专有软件的发展,反观专有软件也是开源项目的重要贡献者。许多大厂,如:思科,谷歌,IBM,微软,Pivotal,SAP,SUSE 也都是 Cloud Foundry Foundation 的成员,此外, Red Hat 也被归类到开源公司行列, 拥有 4,550 名员工为开源项目贡献代码的微软也不例外。无独有偶,除微软外,亚马逊,IBM 和 SAP 也位列开源代码贡献榜单的前十名。

尽管 Open Source 盛行,大多数软件供应商并不会给自己贴上“Open Source”的标签。这是为什么呢?此外,还有些公司自称“Open Core” 或附加额外许可证以限制其开源代码的使用,比如,Confluent 使用 Confluent Community 许可证而 MongoDB 使用 SSPL 许可证,背后的原因又是什么呢?

Open Source 和“免费开源软件”(FOSS)的开发者和爱好者对开源以及非开源的讨论充满热情,他们讨论关于“free”的不同含义,比如“免费软件”(free, as in beer)和“开源软件”(free as in libre)。但对于大多数开发者而言,尤其是面向 GitHub 编程的这类人,他们从 Github 上获取需要的代码为他们所用,却不会关注对应软件的许可证。正如 Mueller 所说,“PM 只在意代码运行结果和开销并不在意开发是如何实现的,因此造成开发者对许可证的不敏感”。

但开发者、PM,或正在阅读本文的你,真的应该去关注许可证吗?来,我们研究下企业在听到“开源”时,他们在想什么。

管理者如何看待 Open Source

作为 Host Analytics、Marklogic 的前首席执行官和 Nuxeo 的董事,软件主管戴夫·凯洛格(Dave Kellogg)说过,人们在面对开源时会混淆两件事:源代码和商业模式。在涉及到源代码时,凯洛格指出需要考虑以下方面:

  1. 代码访问:代码是否可见,可获取,可更改等?
  2. 代码作者:它是由谁编写的?是开源社区中的成千上万贡献者共同编写,还是来自软件供应商的工程师编写?

比如 Drupal 有来自社区的 114,702 个贡献者,而 MongoDB 99% 的代码是由其员工编写。

说到商业模式,大多数情况下开源软件是“免费的”,假设不是直接从 Apache Software Foundation 或 Eclipse Foundation 这样机构获取所使用的代码,Kellogg 建议我们直接研究开源项目的供应商是如何赚钱的。

开源软件有如下商业模式:

  1. 纯服务模式,比如,之前的 Hortonworks (现在的 HDP—— Hortonworks 发行版),用户只需为技术支持及咨询服务买单。
  2. Open Core 模式,比如,大家熟悉的 Elastic,部分产品是免费,而高级版本或附加组件则使用商业许可证(参考:社区版和企业版)。正如凯洛格指出的那般,"开源软件供应商最大的竞争对手往往是他们自己的免费社区版"。
  3. SaaS 模式,比如,Databricks,供应商将其开源软件作为服务托管在云上,通过收取每月/每年的托管和服务费获利。

Gartner 分析师 Nick Heudecker 是这样区分 Open Core 与 Open Source 的:"Open Core 是以 Open Source 为基础的商业产品。Open Source 既是一种开发形式,也是一种源代码的许可方式"。

Heudecker 在博客中提出:

Open Source 供应商的核心价值在于不再受供应商的约束。毕竟,产品核心部分是开源的,且由全球社区开发。产品核心部分并不属于某个公司,多数情况是由 Apache Software Foundation(ASF)拥有。在最坏情况下,即使公司倒闭这种最坏的情况发生,核心代码依然安全存在(于) ASF,被 ASF 所支持。

 

这听起来不错。坦白来讲,这不是事实。这是迈出了第一步并在头一年迅速扩张的好方法。

 

在 24 或 48 个月的限期后期阶段,供应商需要增加收入,有时他们甚至会大幅提高软件价格。这会导致我和我的同事要接很多客户打来的咨询电话。他们会询问他们实际所使用及有价值的功能,如果不用开源组件外的其他功能,他们能正常使用产品吗?有些时候,这个问题的答案是肯定的 。此外,客户们还会这些疑问:市面上还有谁家是支持开源组件的?它们更便宜吗?他们和我之前合作过的软件供应商用的同一策略吗?

 

其他软件供应商见机,会咨询我们是否该提供对这些开源组件外的其他组件的简单支持。因为他们的客户也会与他们谈论其他的内部供应商的策略。

凯洛格对这种销售策略有其他的看法,他表示,“从供应商的角度来看,免费/社区版本既是潜在客户的主要来源,也是最大的竞争对手——如果企业版没有提供相较于社区版更棒的功能,那么人们就不会为之买单或再次购买。”

企业级购买者更倾向于 Open Source 还是 Open Core?

关于企业级购买者更倾向 Open Source 而不是 Open Core,还是 仅仅根据他们业务选择软件/服务这个问题,Ovum 分析师 Tony Baer 表示,这是一个复杂的问题。他说:“这是一个难题,答案是‘视情况而定’”。理论上,所有软件决策取决于商业利益,而商业利益又由一系列选项构成,包括:增加收入,提高盈利,员工保留策略(留用希望在简历上体现开源项目经历的开发者),现有 IT 环境的兼容性和并购中的机构。

我们咨询的大多数分析师一致认为,公司应该关注它们正在使用的开源技术,然而,这说起来容易做起来难。首先,开发者从 GitHub 或其他站点获取资源时通常不会征求许可。其次,正如凯洛格提及的那样,在开放源代码计划(OSI)批准的清单上有 82 种不同的许可证类型,公司需要了解哪些组件受哪些许可证约束以及使用这些许可证的后果。

OSI总经理兼董事 Patrick Masson 表示,这正是一些大厂,甚至是那些拥护开源的公司针对许可证采取行动的原因。比如,Google 已彻底禁止了至少七种类型的开源许可证。

有人会说因为产品背后的软件供应商会处理许可证兼容性之类的问题,并且内置了企业所需的管理和安全功能,因此 Open Core 软件可能是一种更安全,更轻松的方法。但是亚马逊,谷歌和微软等大型云提供商可能正在改变游戏规则。

附录

Nebula Graph GitHub 地址:https://github.com/vesoft-inc/nebula ,加入 Nebula Graph 交流群,请联系 Nebula Graph 官方小助手微信号:NebulaGraphbot

Nebula Graph:一个开源的分布式图数据库。

 

GitHub:

https://github.com/vesoft-inc/nebula 

知乎:https://www.zhihu.com/org/nebulagraph/posts

 

微博:https://weibo.com/nebulagraph

beego用户群

回复

astaxie 发起了问题 • 1 人关注 • 0 个回复 • 214 次浏览 • 2019-10-10 11:19 • 来自相关话题

Nebula Graph 技术总监陈恒:图数据库怎么和深度学习框架进行结合?

NebulaGraph 发表了文章 • 0 个评论 • 375 次浏览 • 2019-10-10 10:32 • 来自相关话题

引子Nebula Graph 的技术总监在 09.24 - 09.30 期间同开源中国·高手问答的小伙伴们以「图数据库的设计和实践」为切入点展开讨论,包括:「图数据库的存储设计」、「图数据库的计算设计」、「图数据库的架构 ...查看全部

引子

Nebula Graph 的技术总监在 09.24 - 09.30 期间同开源中国·高手问答的小伙伴们以「图数据库的设计和实践」为切入点展开讨论,包括:「图数据库的存储设计」、「图数据库的计算设计」、「图数据库的架构设计」等方面内容,本文整理于他和开源中国小伙伴对图数据库的讨论内容~

嘉宾·陈恒介绍

陈恒,开源的分布式图数据库 Nebula Graph 技术总监,图数据库领域专家 & HBase Committer。北京邮电大学硕士,曾就职于蚂蚁金服、猿题库、网易等公司,一直从事基础设施相关研发工作。

本文目录

  • 图数据库怎么和深度学习框架进行结合?
  • 图数据库它可以被认为是 MySQL 中的一种数据库引擎,具备特殊的查询功能,以及特殊的数据结构?
  • Nebula 和 Neo4j 的图数据库的优势和劣势?为何要新开发使用 Nebula ?
  • 图数据库目前主要用于哪些应用场景?
  • 图数据库和一般数据库结构相比,优势在哪里?
  • Nebula 的实践问题
  • 存储计算分离
  • Nebula 高度可扩展具体指的是什么?存储层是否还支持其他类型的数据库?
  • 「图数据库」是基于已有数据库衍生出来的产品吗?如何设计图数据库?
  • 图数据库为何没有通用的图查询语言?
  • 图数据库适合存储什么类型数据,比如树形目录?
  • Nebula 的部署安装配置要求是什么?

图数据库怎么和深度学习框架进行结合?

Stiofan:
图数据库打破了关系数据库的这种古老数据存储模式,将图形化特性属性数据存入,但是关于这些特性化属性的数据使用图数据库和将其转换为类型数据放入深度学习框架,两个之间的关系或者说使用场景应如何来规划。

我们见过一些机器学习使用图数据库的 case,最主要的是 feature extraction 阶段,使用图数据库来拿到当前点相关联的点的一些属性作为 feature,或者产生一些随机游走的路径,使用图数据库可以大大加速整个过程。

图数据库它可以被认为是 MySQL 中的一种数据库引擎,具备特殊的查询功能,以及特殊的数据结构?

钛元素:
恒大你好,我对图数据库不是很明白,是否可以这样理解:它可以被认为是 MySQL 中的一种数据库引擎,具备特殊的查询功能,以及特殊的数据结构?谢谢。

不是特别准确, 图数据库是为了网络结构的数据(比如社交网络,资金网络等)而专门设计的一类数据库。 这类的数据库有着自己独特的数据组织形式, 以及自己独特的查询语句。 它并不是 MySQL 中的一种存储引擎, 而是一个独立的产品,就像 HBase 与 MySQL 的关系一样。

开源中国·sixliu 小伙伴补充:你可以这样理解,原先这些数据都是用关系数据库存的,分别为主体表和关系表,但是在应用使用时查询性能,比如查 n 度关系。所以为了提升查询使用图数据库天然符合,节点(主体)和边(关系),比如说要查 A 的 2 度关系,那么通过 id 直接 key 匹配到 A,然后再获取到路径 <=2 的节点就可以获得结果。

Nebula 和 Neo4j 的图数据库的优势和劣势?为何要新开发使用 Nebula ?

5G加ios:
Nebula 和 Neo4j 的图数据库的优势和劣势? 为何要新开发使用 Nebula ??

Neo4j 是目前市面上知名度最高的图数据库, 是一款非常优秀的产品。 但是开源的 Neo4j 最大的问题在于它是一款单机数据库, 扩展能力存在比较大的问题。 Nebula 是在互联网公司的长期实践中诞生的一款产品, 相比于Neo4j, Nebula 最大的特色便是分布式的架构,扩展性要好很多。

图数据库目前主要用于哪些应用场景?

crf1111:
你好,最近在开发分布式任务处理系统,使用到了有向无环图(DAG)的概念。请问,图数据库目前主要用于哪些应用场景。
对于Nebula,目前提供了几种 client 库,是否能兼容 python-networkx 中的 Graph 对象?

图数据库主要应用于网络结构数据的存储与查询, 比如在社交关系中, 查找一个人的 N 度好友(可以带一些过滤条件),用传统的关系数据库来搞,不仅性能不能满足要求, 还会使用很复杂的 SQL 描述, 对于用户十分不友好。 而在图数据库中,这样的查询就是一条语句而已。
当前 Nebula 提供了 Go / Java / C++ / Python 的 client,对于其他语言可以直接使用 thrift 生成相应的接口。而我们的 Python client 能链接 Nebula Graph,执行相应的 nGQL 语句,暂时不支持 python-networkx 中的 Graph 对象。

图数据库和一般数据库结构相比,优势在哪里?

KelvinQ :
请问图数据库和一般数据库结构相比,优势在哪里?

Everything is connected. 图数据库天生适合表达 connection,或者说多对多的关系。 图数据库可以很高效的查询几度关系,而传统关系型数据库不擅长,一般都需要做表连接,表连接是一个很昂贵的操作,涉及到大量的 IO 操作及内存消耗。当然,文档、关系型数据库和图数据库相互可借鉴点还是非常多的。

Nebula 的实践问题

Li_Peng :
您好,最近刚开始注意到 Nebula,有 3 个问题想请教一下:
1、Neo4j 社区版的单节点限制问题,目前看 Nebula 应该不存在类似问题,不知道这样理解是否正确?
2、Nebula 支持类 SQL 查询,是否有相关 JDBC 驱动可以使用?目前看 GitHub上貌似没有,后期是否会支持?
3、官方文档 https://docs.nebula-graph.io/manual-index/ 地址打开有点慢,目前是否有微信或者钉钉群可以交流?

  1. 是的, Nebula 相比于 Neo4j 最大的优势便在于分布式的设计。
  2. 目前我们使用的是 thrift rpc 进行 client 与 server 的通信。对于JDBC 的支持,如果客户的需求比较强烈,会考虑提供支持。
  3. 可以关注我们的微信公众号 NebulaGraphCommunity, 里面有微信交流群,可以添加我们的小助手进群:NebulaGraphbot

存储计算分离

长眉欧巴:
想问个跨界的问题,貌似目前的数据库走存算分离的路线,而硬件方面却走存算一体的路线,比如类脑芯片,参考人类大脑神经系统的功能。神经元是存算一体的(虽然还没定论,但这更可能)。而图数据库的结构天生跟神经系统有异曲同工之妙,到最后是不是更应该也存算一体?

所谓的存储计算分离,也没有说完全分割,比如说在 Nebula 里面,很多的计算其实是在存储层完成的,也就是所谓的计算下推。
之所以采用存储计算分离的架构,主要是为了扩展性和上云的考虑。

开源中国·sixliu 小伙伴补充:可以把它理解成之前 存储过程完成复杂逻辑->应用层完成逻辑。主要就是为了满足高容错和可扩展。存储层只要提供高度抽象的谓词下推即可。

Nebula 高度可扩展具体指的是什么?存储层是否还支持其他类型的数据库?

myw31415926:
陈大,您好。Nebula 的高度可扩展包含哪些,能说明一下吗?存储层是否还支持其他类型的数据库,如 Oracle 和 PostgreSQL?多谢

Nebula 采用了存储计算分离的架构,对于计算层,因为是无状态服务,可以随意扩容。对于存储层, 我们提供了扩容相关的运维语句,可以比较简单的扩容。存储层支持 storage plugin, 目前已经有 HBase 的 plugin,其他的 plugin 也可以根据需求来支持。但是我们并不推荐在关系型数据库上使用图数据库,因为这样的效率会非常低,扩展起来也会很麻烦。

「图数据库」是基于已有数据库衍生出来的产品吗?如何设计图数据库?

海参拉面:
老师,图数据库是基于现在已有的数据库产品衍生出来的吗?怎么设计呢?

图这种关联关系和相应的需求其实很早很早就有了,只是各种技术上的原因。
以前大家只能用关系型数据库来存储,但是这样需要使用者把关联关系适配成表结构,并不直观,所以图数据库也是这样发展出来的。
关于怎么设计,其实参考了很多 SQL,NoSQL 和各种分布式系统的工程实现,欢迎阅读 Nebula 的系列技术文章

图数据库为何没有通用的图查询语言?

JIANGGuo:
你好,请问图数据库作为 NoSQL 中的一类,底层都是图数据结构来存储的,为什么没有通用的图查询语言呢,Nebula Graph 用 nGQL,Neo4j 用 Cypher ?谢谢。

很好的问题。
我觉得最大的原因是图数据库比较新,各家的产品应对的场景也不尽相同,所以到现在也没有产生统一的图查询语言。

图数据库适合存储什么类型数据,比如树形目录?

荒野刀客:
图数据库是否适合存储树形的数据,比如树形目录?  Nebula 和 Neo4j 相比,语法是否兼容,是否容易切换?

数据结构上来说,树是图的子集。只是单纯树的业务场景不多,我碰到过的树的场景主要是数据仓库里面的数据血缘。
Nebula 语法上和 Neo4j 接近,但并不兼容。我们设计时语法更接近 SQL,你可以下个Docker 试试,我觉得花个 15 分钟,应该能熟悉语法了。

Nebula 的部署安装配置要求是什么?

图数据库猫:
数据库 Nebula Graph 可以安装在 Win7 64 上吗?CentOS 的版本有要求吗?

建议安装在 Linux 服务器上。如果是 Windows 环境,可以下载一个 Docker 试用,https://hub.docker.com/r/vesoft/nebula-graph. CentOS 建议版本是 7.5+

附录

最后是 Nebula 的 GitHub 地址,欢迎大家试用,有什么问题可以向我们提 issue。

GitHub 地址:https://github.com/vesoft-inc/nebula ,加入 Nebula Graph 交流群,请联系 Nebula Graph 官方小助手微信号:NebulaGraphbot

Nebula Graph:一个开源的分布式图数据库。

GitHub:https://github.com/vesoft-inc/nebula

知乎:https://www.zhihu.com/org/nebulagraph/posts

微博:https://weibo.com/nebulagraph

操作系统概念知识点复习

PoormaJin 发表了文章 • 0 个评论 • 428 次浏览 • 2019-10-09 09:49 • 来自相关话题

 操作系统概念:https://jinjiangcc.github.io/posts/os_concept/内存相关概念:https://jinjiangcc.github.io/posts/os_mem_conce ...查看全部
  1.  操作系统概念:https://jinjiangcc.github.io/posts/os_concept/
  2. 内存相关概念:https://jinjiangcc.github.io/posts/os_mem_concept/
  3. 进程相关概念:https://jinjiangcc.github.io/posts/os_procoess/