Q新闻丨谷歌或将 Swift 编程语言纳入安卓平台;Go语言编程模式经验;GitHub DGit改进平台可靠性性能以及可用性
Posted InfoQ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Q新闻丨谷歌或将 Swift 编程语言纳入安卓平台;Go语言编程模式经验;GitHub DGit改进平台可靠性性能以及可用性相关的知识,希望对你有一定的参考价值。
自从去年年末备受瞩目的 Swift 开源后,消息不断,最近互联网巨头们-Google、Facebook、Uber 齐聚伦敦,共同就 Swift 相关问题展开了讨论。The Next Web 称,据可靠消息,Google 意欲在其 Android 平台下采纳应用开发编程语言 Swift为其首要开发语言,这可能和他们备受和 Oracle 的官司之争有关吧。但 Swift 的魅力亦是重要因素,Facebook 和 Uber 均表态,未来会将 Swift 作为主要的开发语言。
众所周知,Google 的 Android 平台的首要开发语言是 Java,而且整个框架都是基于 Java 实现的。这次 Google 称,纳入 Swift 并非是能够替代 Java,这可能和他们备受和 Oracle 的官司之争有关吧。Google 希望 Swift 能够成为超过 Java 的应用开发语言。
Swift 是通过Apache 2.0 许可下发布的,这也就意味着 Google 无需修改现有的开源结构和策略,就可直接无缝使用 Swift。
Swift 是苹果公司开发的一款替代 ObjectiveC 的全新的编程语言。在 WWDC 2014 会议上发布,很快就得到了开发者的青睐,也得到了一些应用开发厂商的支持,如 IBM、Lyft等。
但是 Swift 并非能够在其它平台上直接运行,也就是说 Android 需要 Swift 的运行时环境方可,而且这还仅仅只是一个开始。Google 必须移植 Swift 的整个标准库,以及支持的 API 和 SDK。其中一些 Android 底层的 API 是 C++ 实现的,目前来说,Swift 无法实现连接转换,必须整个地重写!Swift 也无法连接转换应用层的 java 的 API,所以这些也需要重写。
当然,以 Google 的技术实力,这些都不是什么大的问题,只要有足够的动力,Google 大不了就是将原来 Java 做的事情换一下而已。
话说回来, Swift 增长的速度很快,尤其是在开源以后,在 GitHub 上的编程语言排名已经是第11名了。更何况 Google 和 Oracle 纠缠不清的关系,已经迁移到 OpenJDK 上了,所以也该考虑这之后的一些事情了。虽然 Google 暂时还没有推进 Java 以外的编程语言,但是他们已经在考虑 Swift了,Swift 意味着速度和安全,而且以 Swift 的发展来看在将来移植到其它平台不会有太多的困难,尤其是以 C++ 实现的会更加的容易。
在2016年伦敦举办的QCon大会上,Peter Bourgon做了《六年Go语言设计经验》的报告,重点探讨了在使用Go进行开发时的编程模式和反模式。在这里,我们将他给Go开发者的建议进行了简单的总结。
GOPATH:将GOPATH/bin添加到“PATH”这个环境变量中,以便Go应用可以访问所需要的二进制文件。在绝大多数场景下,Bourgon建议使用全局唯一的GOPATH。有些开发者希望严格区分自己的代码和外部依赖代码,这些人更倾向于创建两个GOPATH条目。开发者也可以选择不设置环境变量,并针对每个工程都使用gb构建。
代码仓库的结构:代码仓库的结构依赖于项目结构。如果是私人项目,开发者可以选择自己喜欢的任何结构。如果是开源项目,开发者最好遵循Remote Packages的建议,以便go get命令引用该项目的包。Bourgon建议创建一个基础目录,其中要包含程序的主要构件,以及放置帮助包的子目录,具体如下图所示:
代码格式化:Bourgon强调开发者需要重视Go的权威的代码格式化风格,一旦开发者习惯这种风格,他的代码的可读性将大大提高。按照Bougron的观点,Go开发者社区会认为非格式化的代码出自计算机新手。每次保存之前,可以使用gofmt工具格式化代码。他认为Go代码审核指南为开发者和代码审核者提供了一套通用的实践规则。他还支持Andrew Gerrand关于Go开发的建议,包括如何为变量、函数和exports等元素命名,如果你能够遵循这些建议,阅读你代码的人将会非常感激你。
配置:Bourgon建议配置管理应该有“清晰的定义和良好的文档支持。”他仍旧在使用来自标准库的flag包,不过也希望这个包能够更简单易懂。他强调了明确定义配置项的重要性。通过环境变量传递配置项并没有为应用的使用者提供足够的信息去理解应用的参数使用,他建议在help中提供必要的配置信息。
包名:应该根据某个模块提供的服务而不是它的内容来定义包名。如果一个包含有HelloWorld消息,那么它不应该被称为common或consts,而是greetings。包名应该表明它所做什么,而不是它有什么。
点导入:Bourgon建议不要使用“点导入”,这个特性通过设置点号来代替包名,使得开发者不需要明确的包名就可以访问相应包中的变量。这个特性降低了项目的可读性,尤其对于新手,新来的开发人员容易弄错哪个变量属于哪个包。Go——显式声明优于隐式声明。
Flags:Bourgon并不认为在init()方法而不在main()方法中初始化flags是一个好主意,因为这使得这些flags无法在全局领域使用,而某些测试用例要用到这些flags。
构造函数:在谈到构造函数时,他建议将初始化的struct以内联方式直接作为参数传入,从而避免传入无效或者未完成的状态,例如:
foo := newFoo(*fooKey, fooConfig{
Bar: bar,
Baz: baz,
Period: 100 * time.Millisecond,
})
有意义的默认值:不要使用nil初始化某个变量,这使得每次在使用该变量的时候都需要进行空值检查,最好使用一个无操作值(no-operation value)进行变量初始化。例如,使用ioutil.Discard初始化一个output变量。
模块的交叉引用:有些情况下会出现两个互相引用的模块。在构建其中的一个时,同时需要构建另一个模块,在构建后一个时又需要第一个先构建,下列两个structs的定义就属于这种情况:
type bar struct {
baz *baz
}
type baz struct {
bar *bar
}
Bourgon提供了三种方法处理这种情况:
整合:两个关系如此密切的对象应该整合成一个,在这种情况下应该整合成一个barbaz结构体。
分割:如果这两个模块必须保持分割,那么可以应用下列代码中采取的策略:
type bar struct {
a *atom
monad
}
type baz struct {
atom
m *monad }
a := &atom{...}
m := newMonad(...)
bar := newBar(a, m, ...)
baz := newBaz(a, m, ...)
通信:当上述两种方法都不适用时,可以考虑在两个模块之间发送消息。
type bar struct {
toBaz chan<- event
}
type baz struct {
fromBar <-chan event
}
c := make(chan event)
bar := newBar(c, ...)
baz := newBaz(c, ...)
依赖:Bourgon还提出了”明确依赖关系“的建议,例如:
func (f *foo) process() {
log.Printf("bar: %v", result) // ...
}
应该写成下面这样:
func (f *foo) process() {
f.Logger.Printf("bar: %v", result) // ...
}
log.Printf实际上调用了Logger模块,这么写的话就隐去了这层依赖关系。为了明确这层依赖关系,开发者应该在构造过程中创建一个Logger对象,并使用ioutil.Discard代替空值nil。
通道(Channel):Bourgon建议,当多个协程(goroutine)之间共享内存时应使用mutex,并通过通道对协程进行协调。
日志打印:日志记录的代价很高,有可能成为应用的性能瓶颈。因此,建议只在绝对必要的地方记录日志,包括给开发者阅读或者供机器调用的信息。仅仅需要记录info和debug级别的日志。
监控工具:Bourgon认为Go应用的监控代价很小,推荐开发者使用Prometheus监控自己应用使用的各种资源。
全局状态:消除隐式的全局依赖和全局状态。
测试:执行包级别的测试。为了测试而设计:使用函数式编程风格——使用参数表明依赖关系、使用接口以及避免依赖全局状态。
依赖管理:将所有依赖项都拷贝到项目的仓库中用于构建二进制代码。Bourgon建议开发者根据自己的需要从gvt、vendetta、glide或gb这几个工具中选择。
构建:不要使用go build,要使用go install,因为后者可以缓存依赖关系,并把这些依赖关系放在GOPATH/bin下以便于调用。
这些建议已经被应用于开发Go Kit,一款用于构建微服务的分布式编程工具。
2009年以来,Bourgon在SoundCloud和Weaveworks两家公司都使用Go语言开发,开发了几款产品,包括:Roshi——一款基于时间序列的事件数据库,以及Go Kit。
英文原文
GitHub最近悄悄地发布了DGit,全称为“分布式Git”。这是一种基于Git创建的分布式存储系统,其目标是改进使用GitHub时的可靠性、可用性以及性能。
DGit是一个应用层面的协议,它利用了Git分布式的特性,将每个仓库在三台不同的、独立选择的服务器上保留三个备份。按GitHub所说,这个简单的架构在可靠性、可用性和性能方面带来了许多直接的好处。
考虑到托管某个仓库的三台服务器是互相独立的,那么他们同时变得不可用的可能性非常低。
用户的请求可在这三台服务器之间进行负载均衡处理,由于这些请求大部分是读请求,因此可以立即响应,而无需在这三台服务器之间进行同步,这将带来直接的、接近于3倍的性能提升。
多个仓库之间出现“命运共享”(fate sharing)的情况大大减少了。命运共享这种情况会造成一个或多个仓库的性能下降,其原由是这些仓库与另其他非常流行的或者过于庞大的仓库共享了相同的服务器。在DGit的实现中,由于这些仓库在独立的服务器中进行分发,因此这种情况同时发生在三台服务器上的可能性少之又少。这也使某个请求可以在负载相对较小的服务器中进行处理。
分发服务器之间无需保持一个很近的距离,他们可以分布在不同的可用区域或是数据中心之间。这种方式显然能够改进可用性,并且对于在地理位置上更接近的用户也能够带来性能上的改进。
DGit使GitHub能够废除之前所使用的基于备份的模式(由于DGit的发布过程还在进行中,因此目前仍在使用这一模式)。对于每个活动的服务器来说,这种模式要求设置一个专用的备用服务器,以交叉线连接,数据将通过DRDB进行同步。
对于GitHub的整体功能来说,废除这种模式能够带来一些额外的好处:
当某一台服务器发生故障时,唯一必须要做的一件事就是将等待中的请求重新路由至一台新的服务器,并重启发生故障的服务器。
此外,替换一台有故障的服务器变得不再那么紧迫了,因为至少还有两台服务器能够运行,他们可将数据迅速地分发至第三台服务器。
由于新的方式不再需要使用一台专用的备用服务,这意味着GitHub能够更好地利用每个CPU以及所有的可用内存,以处理用户的请求。
DGit极大地简化了GitHub基础设施的管理,例如添加新的服务器、应对某些仓库变得非常庞大或非常流行等情况。
正如之前所说,DGit是基于Git本身所打造的,它并没有利用RAID、DRBD或其他分发技术。GitHub选择实现自己的算法,以处理序列化、加锁、故障检测以及重新分发等操作。在与InfoQ的一次对话中,GitHub表示他们使用了三阶段提交(3PC)协议以处理分布式事务。“DGit基本已经消除了在Git层由于单一托管或整个机架不可用所造成的服务故障”。
如上文所说,GitHub近几个月来正在逐步部署DGit,首先从他们自己的仓库开始部署。当他们对于新的系统具备了充分的信心之后,就会开始迁移受欢迎的公共仓库。在今年二月,GitHub开始批量地迁移仓库。目前大约有60%的仓库、98%的Gist,总计约67%的GitHub数据已经运行在DGit上了。GitHub向InfoQ表示:“我们正在日夜不停地通过导入作业将数据从之前的存储架构中迁移至DGit”。
英文原文
扩展阅读:
送书彩蛋!
感谢人邮出版社异步社区和图灵教育的大力支持!每天为InfoQ读者免费送出5本好书,一直送到世界读书日!书籍是人类进步的阶梯,跟小Q一起好读书,读好书吧!
参与规则:很简单!请于本文评论区留下足够打动小Q的真知灼见,对书的或是对文章的均可。评论被赞最多的5个人,即是中奖用户。书籍将于活动结束后统一放送,大家不要着急!
本文系InfoQ原创首发,未经授权谢绝转载。
以上是关于Q新闻丨谷歌或将 Swift 编程语言纳入安卓平台;Go语言编程模式经验;GitHub DGit改进平台可靠性性能以及可用性的主要内容,如果未能解决你的问题,请参考以下文章
Q新闻丨谷歌广告彻底放弃Flash,100%转向HTML5;将在.NET Core中被废止的技术;Angular发布1.5正式版
43亿欧元罚款后,谷歌警告安卓可能不再免费;JDK 12早期试用版发布;微软正为Linux用户改进Windows命令行丨Q新闻