并发模型
Go的并发模型提供了跨平台的性能改进。处理分布式数据意味着要与向消费者承诺的保证作斗争。根据CAP定理,不可能同时提供以下三个保证中的两个以上:一致性、可用性、分区容忍。在经济学人的平台上,终的一致性是可以接受的,这意味着来自数据源的读取终是一致的,所有数据源达到一致状态的适度延迟是可以容忍的。缩小这种差距的方法之一是利用Goroutines。
Goroutines是Go运行时管理的轻量级线程,用于防止线程耗尽。Goroutines支持跨平台优化异步任务。例如,该平台的数据存储之一是Elasticsearch。当内容在系统中更新时,在Elasticsearch中引用该项目的内容将被更新并重新索引。通过实现Goroutines,减少了再处理时间,确保项目的一致性更快。这个示例演示了在Goroutine中如何对每个符合再处理条件的项进行再处理。
funcreprocess(searchResult *http.Response) (int, error) {
responses := make([]response,len(searchResult.Hits))
var wg sync.WaitGroup
wg.Add(len(responses))
for i, hit := rangesearchResult.Hits {
wg.Add(1)
go func(i int,item elastic.SearchHit) {
deferwg.Done()
code,err := reprocessItem(item)
responses[i].code= code
responses[i].err= err
}(i, *hit)
}
wg.Wait
return http.StatusOK, nil
}
设计系统不仅仅是简单的编程,工程师必须了解在何时何地使用哪些工具。虽然Go对于内容平台的大多数需求来说是一个强大的工具,但某些局限性需要其他解决方案。
依赖管理
Go发布时没有依赖管理系统,社区内有一些工具来满足这种需求。经济学人使用Git子模块,整个社区与此同时也正在积极推动一个标准的依赖管理工具。虽然社区更建议采用一致的方法进行依赖关系管理,但仍有许多分歧。在经济学人内部使用Git子模块进行依赖管理并没有带来重大的挑战,但对其他Go开发者来说,它是一个需要加以考虑的因素。
还有一些平台需求是Go的功能或设计不太适合的。由于平台增加了对音频处理的支持,Go的元数据提取工具在当时是有限的,因此团队选择了Python的Exiftool。平台服务在docker容器中运行,这也允许了安装Exiftool并从Go应用程序调用它。
funcrunExif(args []string) ([]byte, error) {
cmdOut, err :=exec.Command("exiftool", args...).Output()
if err != nil {
return nil, err
}
return cmdOut, nil
}
该平台的另一个常见场景是从源CMS系统接收损坏的HTML,将HTML解析为有效的,并对HTML进行清洗。Go初用于此过程,但由于Go标准HTML库期望得到有效的HTML输入,因此需要大量定制代码来解析HTML输入。这段代码很快变得不堪重负,对于边缘例外情况无法有效处理。Javascript实现了一种新的解决方案,为管理HTML验证和清洗提供了更大的灵活性和适应性。
Javascript也是平台中事件过滤和路由的常见选择。事件使用AWS Lambdas进行过滤,AWS Lambdas是轻量级函数。一个用例是将事件过滤到不同的通道中,例如快速通道和慢通道。此筛选基于事件包装器JSON对象中的单个元数据字段完成。过滤实现利用Javascript JSON指针包抓取JSON对象中的元素。与Go所需的完整JSON解组相比,这种方法要有效得多。虽然这种类型的功能可以通过Go实现,但是对于工程师来说,使用Javascript更容易,并且提供了更简单的Lambdas。
回顾
在实现了内容平台的实施并生产上线运行之后,对于这一历程回顾如下:
好的地方?
分布式系统的关键语言设计元素
并发模型,相对容易实现
愉快的编码和有趣的社区
不足的地方?
版本控制和标准方面的需要进一步提升
在某些领域缺乏成熟的解决方案
总的来说,使用Go来快速构建系统是一种积极的体验,Go是内容平台扩展项目成功的关键元素之一。经济学人是一个多语言的平台(注:此处指编程语言),在合适的地方使用不同的语言来解决特定问题。例如,在处理文本和动态内容时,Go可能永远不会是,所以团队将Javascript纳入工具集中。然而,Go在支持系统扩展和发展起到主要作用。
在考虑是否要使用Go时,可以考虑一下系统设计的关键问题:
系统目标是什么?
你为你的消费者提供了什么保证与承诺?
什么样的架构体系和模式适合你的系统?
系统需要如何扩展?
如果你正在设计一个旨在解决分布式数据、异步工作流、高性能和可伸缩性挑战的系统,可以考虑使用Go来加速构建并达成系统目标。