最终,为什么选择go-kit

前言

工作这些年,先后经历过两家公司,分别参与过php语言框架的设计和主导过golang技术栈的落地工作,在此过程中有一些感悟和总结。我想以之前我主导的golang技术栈为线索,来陈述当时遇到的一些问题,以及分析问题和解决问题的思路。主要目的是想陈述golang技术体系在我们团队中落地过程,分析我们在各个阶段中,遇到的一些问题,并將分析问题的思路和解决问题的方法记录下来,以便让后来的同学了解golang在团队的演进过程,吸取相关的经验,以便在今后的系统设计和开发上少走弯路。

在系统不断演进的过程中,有时候对框架的选型很随意,认为能满足现在功能就行,没有对其扩展性和性能进行考量,是否能够持续的支撑业务的发展——走可持续化发展路线,导致随着业务的发展,发现当时选型有误,但想转又很难。那么现在,我就来谈谈,我们是如何抉择这些事情的。

我们为什么要由php转向golang

最初,大约是在2015年时,平台内所有的业务系统均是由php语言构成的,上线没多久,平台的流量开始爆发性增长,并发量越来越大,当时的最快最有效的优化手段无外乎加机器和增加php-fpm的数量,但是,受限于php本身的网络模型,终究不适合这种高并发,大流量的场景。面对这种棘手的问题,再加上当时人手有限,业务任务重等因素,于是找其它部门借了一批写lua的外援,帮忙把一些逻辑简单且访问量大的接口,换成了lua,暂时扛过了晚高峰,因此,有相当长的一段时间,大部分项目是php+lua共存的一个状态。但由于lua本身的一些局限性,不太适合做一些复杂的业务逻辑,所以最终,在业务有强烈的需求的前提下,同时伴随着技术发展的潮流,在2015年底,我们开始选择转向golang。

我们怎样由php转向golang

由于之前团队全部都是php栈,在golang方面的积累并不多,所以在php转向golang的过程中,面临了在转型过程中都会面临的问题:

1 用什么框架;

2 在业务任务重,人员极其匮乏的情况下如何將php项目重构成golang。

用什么框架

之前团队有人仿造内部php框架开发过一个golang框架,有人提议将其直接拿过来用,有人说找个开源的如beego,gin,martini等这类流行的框架。由于之前用内部的php框架做开发,遇到过不少问题,所以我个人当时还是比较排斥使用自研的框架,主要有以下几点原因:1 文档少,漏洞多;2 需要投入人力去开发和维护,在当时人力极其紧缺的情况下是不现实的。另外,当时社区流行的框架也比较多,但是最终也没有选择那些流行的框架,主要是出于以下考虑:时间短,任务重,没有精力去辨别各个框架的优劣,适用场景以及性能如何。万一冒然使用一个还没有深入了解的框架,线上出问题咋办!尤其在当时系统频繁出问题,顶着各种压力的情况下。

虽说,我无法在短时间内选一个合适的框架,但是我还是比较确定,我们的需求是什么?

1 只做高性能的HTTP 接口;

2 需要完整的单元测试体系;

3 可扩展,组件化;

基于以上三点,可以发现,golang自带的特性就可以满足这些需求。于是,我们开始决定用golang裸写。

裸写不是乱写

裸写不是乱写。众说周知,用框架的其中一个好处就是保证团队代码风格的一致性,当然,目前市面上除了beego外的大多数框架,在代码风格上也并没有做约束。为了保证团队golang代码的规范性和一致性,按照经典的分层架构和过往的经验,我们制定了一套golang编程模版,由上向下:Router层,Service层,Dao层,还有贯穿这三层的Entity层,架构图如图1所示。其中,Router层负责处理与http handler逻辑,请求参数以及response格式相关的处理工作,Service层处理业务逻辑,Dao层处理数据访问逻辑,Entity层负责实体定义相关的逻辑,贯穿Router,Service,Dao这三层。层与层之间不直接进行耦合,高层模块不直接依赖与低层模块,它们都依赖于所定义的抽象接口。Booch曾经说过:“所有结构良好的面向对象构架都具有清晰的层次定义,每个层次通过一个定义良好的,受控的接口向外提供了一组内聚的服务”。除此之外,我们还维护了一套常用的公共组件库,如:日志库,各种数据库driver等。

图1 分层构架

如何重构

当我们制定好编程模版后,我们就开始进行项目重构工作。由于,业务任务重,人手少,所以,重构的基本方向就是:根据业务需求,结合接口重要性进行重构。只有这样,才能保证在业务需求不停的情况下,进行系统重构。所以,在此期间,有相当长的一段时间是处于php+golang混合编程,混合部署的状态,这种状态一直持续了一年。采取混合编程的思路在重构初期,可能会遇到同一份代码,需要用golang写一遍用php写一遍,无疑增加了一定的工作量,当然这也是避免不了的。

最终,我们为什么要引入go-kit

随着业务的发展,请求量越来越大,为了应对更大的挑战,团队有了向grpc,thrift方向发展的趋势,另外我们还是需要标准化一些中间件的使用,来保障系统的稳定性。于是,我又开始陷入了深思,不过现在团队兵强马壮,业务稳定,给我留下了充分思考和调研时间。这次的思考,还是像最初框架抉择的思路一样,首先,要弄清楚我们的需求是什么?

1 需要一个同时支持http,grpc,thrift等协议,具有良好扩展性的框架;

2 框架本身和业务代码保持一种低耦合的状态;

3 需要一套通用的middleware,使之与http,grpc等传输协议无关。

目前市面上流行的框架都是围绕着http协议而展开的,包括gin,beego等。经调研,我发现go-kit能够满足我们的需求。 go-kit本身不是一个框架,而是一套微服务工具集。其设计思想跟我们初期golang模版制定的思想也算是不谋而合——分层设计,组件化,可扩展。go-kit的架构如图2所示,分为三层结构:Transport层,Endpoint层,Service层。Transport层主要负责与传输协议Http,Gprc,Thrift等相关的逻辑,Endpoint层主要负责request/response格式的转换,以及公用拦截器相关的逻辑;Service层则专注于业务逻辑。go-kit除了经典的分层架构外,还在endpoint层提供了很多公用的拦截器,如log,metric,tracing,circuitbreaker,rate-limiter等,来保障业务系统的可用性。它们在设计上有一个共同特点:都是同传输协议无关的。在之前的一些http框架中,这些拦截器同传输协议是紧紧耦合在一起的。因此,借助gokit这套工具集,我们就能很好的对transport协议,middleware进行扩展,且不会影响到业务本身的设计。

图2 go-kit架构图

我们怎样將go-kit集成到我们现有的业务系统中

我们找到了心仪的开源工具后,那么我们怎样以较低的成本将其引入到我们业务系统中呢?之前我们有提到,我们的golang模版是分为三层:router,service和dao。而go-kit也分为三层,我们可以根据每层职责的不同进行重新组合,从上到下依次为:transport层,endpoint层,service层,dao层。这样就能很轻易的將go-kit集成进来,当然你如果哪天因为某种原因,不想再继续使用go-kit这套东西,直接將endpoint层和Transport层移除即可。在集成的过程中,需要注意一点:之前的代码中router层不能包含任何业务逻辑,否则就无法集成。

图3 架构的演进

总结

不论是我之前的一篇文章《浅谈互联网业务系统设计》所讲的系统设计,还是这篇文章所陈述的框架选型。我们首先需要明确的一点就是:需求是什么?如何在满足需求的同时,让框架和系统具有一定的弹性。无外乎使用经典的五大设计原则:单一职责原则,开放封闭原则,依赖倒置原则,接口隔离原则,为你的设计提供坚实的理论基础和方向指引。另外,在做选型的时候不要盲从,别人口中好的东西,不一定适合你,只有明确自身需求后,找到适合自己的才是最好的!

参考书籍

《实现领域驱动设计》

《敏捷软件开发 原则 模式与实践》

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-10-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开源优测

软件测试基本功之ISO9126质量模型

简介 ISO/IEC 9126 (1991) :软件产品评估—质量特性及其使用指南纲要,就是为支援此种需求而发展出来的。在此标准中,定义了六种质量特性,并且描述...

23070
来自专栏韩伟的专栏

论可复用的游戏服务器端开发框架(一)

本文试图以游戏服务器端开发的角度,探讨在需求高度变化的环境下,可重用模块构建的可能性和基本方案。 可复用框架的必要性与可行性 在现代游戏产品的开发中,游戏服务...

68060
来自专栏SDNLAB

混合虚拟化网络,网络性能优化之辩

网络设备在虚拟化后是否依旧可以快速提供良好的性能?这是目前大家最为关注的问题之一。下面就讨论一下传统网络设备和虚拟化后面临的问题以及怎样使用网络设备才能提供实时...

43470
来自专栏程序员互动联盟

你是否有过代码写的太烂不敢开源的经历?

作为一个写了十几年代码的老司机,在入行不久会有这种心理,老是觉得自己写的代码见不得人,主要还是基础不牢固写出来的代码属于见光死的程度,从测试人员那边的感觉就能测...

13220
来自专栏SDNLAB

通用客户端设备(uCPE)详解

通用客户端设备(Universal customer premise equipment,uCPE)正在吸引服务提供商的注意力,AT&T目前已经宣布了其uCPE...

50760

Code2Cloud:不只是瓦解ALM

VMware新发布的Code2Cloud很吸引人。根据公告,开发基础设施将作为一项服务交付,不需要安装,也不需要管理硬件或软件。Code2Cloud会替代编程/...

22560

我们是否应该在物联网上使用无服务器体系结构?

我们正处于前所未有的行业混乱的时代,这是由技术发展过快导致的,特别是在物联网领域。物联网有助于将行业转变为数据驱动的范例,开辟了巨大的机遇。一些公司正通过技术革...

44860
来自专栏测试开发架构之路

《Google软件测试之道》告诉你什么是测试

第一章:Google软件测试介绍 1.Google的测试团队并非雄兵百万,我们更像是小而精的特种部队,我们依靠的是出色的战术和高级武器 2.在Google,写代...

54670
来自专栏Django中文社区

django开发时遇到问题的正确求助姿势

自 django博客教程发布以来,已有超过上万名读者学习了该教程。一些学习者跟随教程顺利地完成了个人博客的搭建,但一直以来也不断地收到读者的评论留言、QQ 留言...

35680
来自专栏IT大咖说

腾讯DevOps体系之研发管理那些事儿

内容来源:2018 年 5 月 05 日,腾讯研发管理部CODE平台产品负责人孙晨星在“2018 DevOpsDays Beijing”进行《腾讯DevOps体...

28620

扫码关注云+社区

领取腾讯云代金券