4 29

第一届 Gopher China 大会

前两天去上海参加 Gopher China 2015 大会,见到很多久闻大名的大神和朋友,感觉很好。而且看到许多的企业,尤其是大企业都已经开始成规模的使用 golang,说明 golang 本身的设计和性能,已经受到了大家的认可。当然其实有很多的话题,不局限在 golang 了。

Go 语言核心

最重量级的话题,就是 雨痕 的 《Go 1.4 Runtime》。主要说了 Go 的内存分配器、垃圾回收器和goroutine调度器三块内容。我之前阅读过他的 《Go 语言笔记》 ,非常不错。很详细的阐述了 Go 语言本身的实现设计,同时为更合理的利用 golang 提供一些参考。 再加上他本人也很低调,真的是 隐士高人 的感觉。这次的他的演讲也相当不错。流畅的思路和平和的语言,而且不时的有诙谐幽默,让人听起来很有意思。唯一的遗憾是,他准备的ppt其实可以讲到3个小时,可惜会程只有45min,尽管大家还是争取多听了一些,但还是意犹未尽。

另一个超级话题,是 Robert Griesemer 的演讲。他是 Go 的三位作者之一,也是 Google V8 和 Java Hotspot VM 开发者之一,相当巨大的光环!他的演讲是关于 gofmt 的。 Go语言本身有很多的外围工具,比如 gofmt, godoc。其中格式化工具 gofmt 帮助大家简单直接的就统一了代码风格。Go 本身就带有 parser 包,就能够很好的去解析go源码到语法树。 唯一要吐槽的是 Q&A 环节,提问的童鞋用谁都听不懂的“英语”去问,哈哈哈!

Go 和 高速并发

很多人看上 Go 语言,主要是因为简化的并发模型:很简单地创建轻量级的用户协程goroutine,使用channel进行goroutine之间的通信,runtime本身的调度足够快。当然在演讲的题目里不会少,比如 达达 聊了在游戏中的实践,goroutine(codis的作者) 和 周洋 在分布式系统中的实现,QLeeLuLu(fawave的作者)在广告竞价系统中的应用,以及 月牙寂 的在P2P缓存网络的应用。

总结起来,高速并发时需要考虑的细节:

  • 数据里CPU的距离

达达的游戏项目为了保证很高的速度,很多的数据都直接是内存数据。内存中的大数据会明显的影响GC的效率。因而要做的, 减少内存中的数据对象数量。然后内存数据肯定是要写入物理存储的。达达在内存做了一层数据到mysql的直接映射关系,被称为 内存数据库,而且支持事务处理。我的理解,内存数据库中的实际操作,不是直接对mysql的操作copy过来。它本身的模型并不复杂,所以很多的操作都是单一对象操作的,或者是对象的某些字段的操作。达达也提起内存数据库的调度代码其实是用代码生成的。换句话说就是简单的逻辑描述就可以表示的数据操作。那么事务显然在业务中是必要的,同时操作不同对象,相当于操作多个数据表。

另外这个内存数据库使用了类似传统数据库的日志机制。内存的修改是可以即时完成的,然后同步到mysql用的是自定义的一种事务日志描述。mysql其实也是把当前执行的操作写在binlog中,后续才会真正执行到存储的数据中。

  • 适当的集中处理

集中的反义,就是分散。分散的理解,其实有很多可能。比如反复的io操作,rpc操作等。从go本身的角度,分散的造成的麻烦是 goroutine泄漏 。如果把各种逻辑都放到独立的goroutine中,当逻辑阻塞,goroutine就不停创建且无法结束。这给调度器带来很大的压力,以至于别的逻辑创建的goroutine很久无法被执行,拖慢整个业务的速度。简单的处理方式就是通过channel,将需要处理的逻辑传递给某些goroutine执行。换句话说,创建一些goroutine专门处理某种逻辑,通过channel传递逻辑参数,就可以。

剩下的问题就是对外部资源调度的分散。redis使用时最常见的集中的方法就是用pipeline。rpc也可以使用长链接双工模式的调用。简单地说就是让各种命令一起执行,而不是分别执行。

  • 控制锁和timer

锁在很多排他性的操作的时候是必须的,没有任何办法规避。但是 锁的粒度,是需要控制的关键。如果锁的粒度很大,锁住的数据或者逻辑很多,那别的操作就只能等待。比如说,一个10k对象的全局map修改,需要加锁防止并发冲突。但是只要锁住1W的对象就全部无法操作。因此最简单把这个10k个对象的map拆分成10个1K的map。这样每个小map即使锁住,也只会影响1k数据,而不是原来的10k。但实际中锁的粒度,需要根据业务判断,但是减小粒度是统一的追求。

timer这东西其实就是一个计时的goroutine和到期信号的channel的组合。timer越多显然就是goroutine越多。调度器的消耗明显增长。如果还是需要计时逻辑的操作,可以去看看时间轮算法,减少创建timer。另外就干脆不要用,在自己的逻辑中判断时间是否超出限制的问题。

  • 总结

高并发的服务,Go 本身的一些细节,是有助于提升效率的,但是不是靠 Go 语言本身就足够,还需要和各种手段配合,才能真正满足实际的业务要求。

Go 和 虚拟化

Go 语言最明星的项目是 docker。很多大神在研究和使用docker。作为一种轻量级的虚拟化技术,相比xen有很多优点,受到大家的青睐。我并不熟悉docker的应用,没有在虚拟化上有多少实际经验,所以听听大神们的说法,增长知识。

马全一 是docker社区很有名的朋友。他演讲主要再说DevOps,就是从开发、测试到部署、运维的全程解决方案。为了在开发、测试和部署层面的统一,系统环境需要很好的统一性。直接方法就是虚拟化,如完全类似的虚拟镜像。docker的出现,让虚拟化的成本大大的降低。而且docker镜像的管理非常像git样版本管理的模式,对开发人员非常友善。另外,docker镜像对系统资源的使用很有效率,也可以作为生产部署方式。因而,以后的DevOps的趋势很可能就是ContainerOps。

我不太懂docker,听了很多未来的趋势,以及docker和rocket之间的江湖恩怨。目前较好的使用方式就是用docker虚拟化application,不要虚拟数据存储。就很像nginx代理n个实例,这些实例操作统一数据的感觉。另外,演讲也提到微软Windows对docker的支持。十几天前docker也发布的windows客户端的preview。看来docker在全平台的虚拟化很有希望了。

Go 与各种领域

Go 语言的定位是系统级语言,很多方面都会有深入的应用。

一个演讲是有关在电信领域,网络功能虚拟化(NFV, network functions virtualization)。电信网络设备之间的连接,是网络单元之间的连接,如基站-节点设备-网关设备,各种物理设备组成的网络。物理设备之间的沟通,就需要靠硬件协议交互。网间设备种类越多,交互协议就越多越复杂。Go的使用,就是在普通服务器设备上,实现网络单元的功能,即软件模拟硬件。同时,虚拟后的软件相比硬件设备,可以更快平衡网络的突然变化。不过,电信网络对联通率,联通质量有很严格的要求,目前这个方案还是测试阶段,不知道成功与否。

另外有个金融领域的演讲,补充了很多知识。以前我也以为金融系统,尤其是银行系统是很古老的系统。但是其实他们也在随着新的技术演进。因为金融领域的特殊性,对数据的安全和监管要求很高。而且金融业务的复杂度远超过一般商业业务。金融IT系统本身是完全耦合的,而且架构非常稳定。当然,他们也在尝试使用虚拟化技术,来做架构内部的调整。虽然整体结构是不太可能改变的,但是各种新兴业务也在使用新的技术。

还有一个很有启发的演讲,用 Go 语言写的网络操作系统,类似于 Chrome OS。我们为何要考虑高并发的问题,因为服务和运算都是集中的,比如微博的数据处理就是新浪机房在做。那如果去掉中心,那运算的复杂度显然会降低很多。同时,数据也会分散,分布在各个客户端节点中。这其实很像比特币,没有中心,数据都存在用户的客户端。数据的更新通过客户端的P2P传播。类比的说,新浪的数据其实分布在各个微博用户的电脑上。当你使用微博,就其实连入了微博网路,可以P2P的从别的客户端同步你需要的数据(一般只需要自己时间轴的数据)。这是我的理解,不知道是不是大神真正的意思。目前来思考,其实还有很多问题,比如数据的分散和同步,网络节点同步等等问题。不过这样的一种模式,确实很有开创性。

许多朋友

在 Go 语言圈里混了很久,也算有很多熟人。以前都是网上聊天讨论,这次可以见到本人,非常高兴。达达和月牙寂是厦门本地的朋友,偶尔也见面聊天,还是很熟悉的。不过两个人在线下的感觉和上台演讲不同,达达还是太羞涩啦。

lunny是xorm的作者,看起来是个很温存的大叔。BetaGo好高啊,很认真的样子。毛剑也有点软软的感觉。当然asta谢的观感和照片里差不多,很热情很热心,还辛苦的为提问的童鞋递话筒。大会也一直是他辛辛苦苦,忙前忙后。是个很不错的人。

我只是个普通的程序员,没什么高大上的作品或者名号,也不求成为大家眼中的大神。了解和学习我想要的,做好自己的工作,过好朴素的生活,我就满足了。

Go 语言在中国非常火热。国内大量的 Go 语言开发者在这次 gopher china上聚会,交流技术,结交朋友。我也看到其实还有很多的大神在深入研究 Go 语言的使用。我还只是一个才入门的孩子,需要很多锻炼。希望自己再接再厉,好好学习,天天向上!!!