原文 http://peter.bourgon.org/go-kit/
当我们听到 企业 (enterprise)这个词的时候,往往会联想到老派,缓慢, 繁文褥节等名词,就比如 IBM HP 甚至红帽这样的公司,他们已经在长达数十年的时间内成为科技行业的领导者。现在,一些如 Google Amazon Twitter,Netflix,Facebook,Spotify,乃至 SoundCloud 这些公司正成为互联网行业的主流,这些现代的企业通常有以下一些特质:
最后一点尤其关键。
除了少数的例外,绝大多数的现代企业在经历过相似的技术架构演变后,都已经转向了面向服务的架构(或者 microservice):
采用 SOA 可以得到很多好处,但是是有代价的。一个分布式系统天然会比实现同样功能的庞然大物般的单一服务要复杂。解决和管理这些分布式系统代理的复杂性,通常最终会产出一些类库和框架。在现代的企业里,一些久经考验的事实标准会开始进入大家的视野,通常以开源项目的形式。我认为, Twitter 的 Finagle 是最值得一提的一个;Netflix 也维护了一坨这样的开源项目。当然还有很多小公司开源了很多同质的项目。
这些类库通常是用 Scala 写的,和其他的一些 JVM 语言配合使用。Scala 在这个领域有很多好处: 表达力强,某些场景下性能不错。但它并不是银弹,从任何角度上看,它语法都太复杂,工具链巨难用,甚至在语言设计上有些自相矛盾(函数式 vs 过程式)。这意味着很少有人能很好的理解和运用这门语言,这会导致一些不可避免的坏模式的产生:拷贝-粘贴代码;对于一些问题进行错误的抽象,重复造轮。
在这个大环境下,Go 就有机会了。清晰(简洁)高内聚的设计,对开发者友好的工具链,生成原生的二进制代码(不需要平台相关的 runtime), 接近 C 的运行时效率让其非常适合进行 SOA 架构的开发,特别是对比现在的最新的编程语言和相关框架。除此之外,Go 还有一个和它的年纪并不匹配的优秀的生态系统和第三方库,同时还有很多的成功案例可以参考。但是 Go 还(暂时)缺乏一个成熟的综合性的分布式服务框架(工具包)。我认为,这个坑很快就要被填上了 :)
我认为,Go 需要一个类似 Finagle 的工具包, GoKit,让其可以变成一个进行现代 SOA 架构开发的语言(作为 Java / Scala 之外的另一个合格的候选语言)
在我的想法中, Gokit 有一组相互关联的包组成,作为开发大型 SOA 架构的基础框架。这个工具包应该是综合性的,包含实现分布式系统的各种重要部分的组件;它会在自己的框架中包含一些常见的分布式系统模块,比如 Finagle;同时它应该集成一些最常用的基础架构组件来减少开发时候的阻碍,同时加强与现有系统的沟通。
我认为这个工具包应该是只包含核心组件的最小集,我会逐一的介绍我设想中的各个组件,但是目前仅是我自己认为的最小集合,我会在这里发起一个讨论,来收集大家的想法。
package metrics
指标模块,客户端和服务器需要彻底的仪表化(指标可实时度量),这意味着需要收集诸如:系统内存,CPU使用情况,GC信息等等。这也意味着需要收集服务层的指标,如请求响应时间,内部队列长度,每个过程的延迟(比如流水线作业);同样意味着需要包含业务逻辑的指标,如某些业务事件的吞吐,或者上层业务的异常等。
package log
日志模块,不同的公司对于日志有着不同的需求,比如日志级别,schema, log的存储位置等。我认为工具包可以基于标准库的 log 库为核心,然后提供可选的模块,如日志级别,schema 定义和增强,还有不同的log后端,log的后端可以支持输出 stdin/stdout, 也可以输出到 syslog, nsq, kafka 这类的系统。
工具包的 log 模块应该可以服务一切类 log 形式的数据,不仅仅只是应用的诊断信息。
package server
server 包,可能是最大的和最重要的组件了。理想情况下,我们应该可以直接以实现一个 Go 接口的形式来实现一个服务。server 包在内部需要封装服务的一些常见需求,例如服务的监控,请求的 tracing,连接池管理,抗压,节流等工作。对上述任何一个功能点,也需要提供接口,来实现可拔插的策略。server 库还需要集成服务发现模块,同时在不同的 transport 方式下运行良好。可参考的实现是: Fingle, Karyon 等。
package client
client 包是 server 包的一个自然的伴侣,它像 server 包一样也应该封装很多常用的模式如:客户端的限速,断路保护,连接池等。它也应该和服务发现模块整合,在不同的 transports 方式下正常工作。可参考的实现是: Finagle, Ribbon 等。可见,client 和 server 包应该能共享代码,比如连接池,限速, request tracing 什么的,都是可以抽出来的。
服务发现,在一个动态(易变)的网络中连接客户端和服务端是一个庞大的课题。有很多手段可以实现,从静态的配置ip,到动态的拓扑结构变化订阅,还有各种在此之间的方案。这个工具包应该兼容你所在公司的现有的基础服务,至少得支持静态的硬编码配置ip地址,并且支持一些常见的开源解决方案如 consul, etcd, smartstack (zookeeper) 等系统。
package transport
通信模块,service 的实现应该与其的通信方式解耦,一个独立的 service 应该可以支持绑定多种不同的通信格式。这里的通信方式指的是一个广义的概念:请求(回复)数据的序列化(反序列化),支持诸如 json/gob/protobuf, thrift, avro 等格式;同时请求(回复)的信道可以支持 HTTP/RPC/ raw TCP。
如果我们的分布式系统确实只是依赖一组约定,我们可以利用它们作为简化的假设,并建立一个更易于理解和可靠的模式。毕竟,简单性是可靠性的前提条件。更进一步:设想,利用这些约定,得到整个系统的运行时状态的工具。它可能允许我们在对异构的服务实例进行统一的度量。有了这些信息,我们可以创建动态的系统,使系统动态地根据环境的变化作出反应。这将使像基于负载的 auto-scale,或者没有人工参与的安全持续部署等高级的模式。
仅仅是这些好处,就足以把我们交的税补回来的了 :) 同时将这些基础组件转化成了真正的商业价值。而且未来是敞开的,还有很多可能性,我们现在并不知道是什么。
当我把这个 talk 在 FOSDEM 和 Google Campus London 聚会发表后,我收到了许多热情的开发者有类似的想法。我备受鼓舞,我想创建一个工作组,探讨这些想法,并开始实现 Gokit。
促使我做这个工作是因为我希望看到 Go 语言能够更加的成功,并且将 Go 引入这个领域,我相信我会从中大大受益。运气好的话,我认为我们在几个月后会有一个早期的可用于生成环境的版本。一开始,我会创建了一个邮件列表,在这里我们可以开始收集需求和想法,并组织初步的开发工作。我也创建了gokit.io作为官网,以后可能用于host gokit的一些包。 http://gokit.io 如果你对上述这些东西感兴趣,希望你能加入邮件讨论组!