转载

支付系统的基础设施建设

基础设施是为了支持支付开发的软件过程。在进入主题之前,先吐槽下软件过程。软件过程在这几年都越来越不受人待见了。在一些互联网公司里面,软件过程的概念往往被等同于拖拉、延期、冗长。他们为自己的软件过程往往都会贴上敏捷的标签,并为各种混乱的管理提供了一个非常好的借口。就算是先写代码再补需求,也能够套上敏捷开发借口。可是这一套路,拿到金融软件,特别是和钱打交道的支付系统开发上,却是行不通的。且不用说混乱的管理滋生的各种漏洞容易吸引各路攻击者,为了对接各个银行渠道,他们也会要求开发商遵守一些底线。事实上,在各大互联网和第三方支付公司,支付系统的开发一直都执行最严格的流程管理。那在公司各个项目之间的巨大的内部竞争压力下,支付系统开发人员也不好意思说,我们执行的是最严格的软件过程,所以系统升级慢。那如何在保证流程质量的前提下,在确保系统不断演化升级的同时,提升系统质量,避免漏洞,降低风险呢?

从案例开始

那支付系统开发过程有别于其它系统的要点在哪?就目前大部分公司而言,一般系统的开发人员是所谓的全栈工程师的:从写前后端代码,测试,上线到运维。线上出现bug,就登陆到服务器上翻日志,找原因,或者直接到数据库上改个数字。可这些行为,对支付系统来说,都是大忌。

介绍一个真实案例,某游戏公司的技术合伙人在开发时,将一些偏远省份的收单账户替换成自己账户。一年多时间无人发现。直到有一天一位投资者去某省出差,使用这个系统执行支付时候,发现收款公司名称与原公司略有不同。这位细心投资者让公司调查一下这事情,才发现其中的猫腻。

开发人员把某个收款账号替换成自己的账号怎么办?会不会修改数据库,把自己账号余额多加几个零?这些都是真实存在的问题,也都有人干过。虽然人与人之间的基本信任还是需要的,可是支付系统的基础向来都不是基于信任的,而是从各个角度来以最大的恶意来揣摩人性,从而出现可以被人利用的漏洞。 所以,对支付系统的开发,通俗的来说,有这个要求: 开发不上线;上线不开发。也就是开发人员不能参与上线和线上系统的运营。 那在这种情况下,如何保证开发的系统能够顺利上线,如何保证线上的系统在有问题的时候能够尽快被诊断出来并解决? 这就需要一系列的基础设施的支持。

微服务和自动化

传统的软件过程一个大问题是各个阶段都需要人工干预。 而微服务架构的引入,其思想是通过降低系统的复杂度来使得过程的自动化成为可能。对此,Martin Fowler首先提出了在极限编程(敏捷)中使用持续集成的观点。在微服务架构之后,由提出了持续交付的概念。 微服务架构如何支撑这些过程,可以参考相关资料,本文不再详细介绍。 而从支付系统的角度,它的基础设施建设有什么不同之处?如果从微服务的角度来考察,和其它业务系统开发并无不同之处。无非是要求更严格罢了。构建的原则也是."人管代码,代码管机器。通过流程自动化,逐步消除软件过程中的人工干预,加快迭代,提升质量。

怎么度量支付系统基础设施建设的成熟度?我们没法从部署了多少个软件,使用了多少台机器这样硬性指标来考察。敏捷开发的一些最新理念可以帮助我们定性地度量这个进度。

软件开发过程包括编码,构建,集成,测试,交付(预发布),部署。我们可以从这流程的自动化程度来度量基础设施建设的阶段。

支付系统的基础设施建设

持续集成、持续交付和持续部署,分别对应自动化软件过程的三个阶段。持续集成实现了编译、发布、集成编译的自动化,并最终自动部署到集成测试环境。在测试完成后,需要人工验证和上线。 而持续交付则更进一步,在实现自动测试基础上,能够实现自动部署到预发布环境。在准线上环境确认达到可以上线的要求后,人工部署到线上环境。 持续部署是自动化的最终目标,开发完成后,能够自动地完成验证并实施到线上的系统。

不管是哪个阶段,都需要自动化的基础设施的支持。这里分头介绍其中主要的基础设施软件,以及他们的选型。

版本控制

版本控制所有自动化工作的基础。国内大部分公司已经完成了从subversion到git的改造,git也成为版本控制的标配了。支付系统在版本控制上和其他系统并无太多的差异。这里需要介绍的是针对微服务架构的版本控制。 我们知道对版本控制来说,代码合并是一个很难避免的噩梦。 而微服务化可以很好的解决这个问题,由于服务的粒度小,每次变更一个人就可以搞定。每个服务有都可以独立上线,避免修改冲突。 这样版本控制就相对来说比较简单:

支付系统的基础设施建设

代码审核

支付系统的每一行代码都要执行审核!代码审核对支付来说意义重大,是避免恶意代码不可缺少的一个环节。 一般来说,支付代码要求至少是2人审核通过。代码需要执行日常审核,而不是到快发布时的统一审核。审核的工具一般是需要和版本控制相集成的。 subversion上用reviewboard, git上用gerrit或者gitlab。虽然说gitlab是比较新的系统,不过还是推荐gerrit,可以强制代码审核以及控制代码审核流程,确保两个人都OK后才能入库。

对于使用gitlab的系统而言,它的优势在于可扩展性强。gitlab默认不支持强制代码评审。但如果不强制执行代码评审,那会出现开发人员未经code view就提交自己merge代码。而reviewer 未能够及时review代码,也会影响进度。此外,开发人员没有执行代码审计(sonar)就提交代码,也是常见的事情。 好在gitlab有非常好的可扩展性,通过webhook可以根据需要实现各种额外功能。 webhook是gitlab的一个扩展点,通过用户提供的回调HTTP请求来监听git的push、comments、merge等事件。比如可以要求必须至少两个LGFM(LooksGoodForMe)才可以merge。通过webhook来监听comments,汇总两个LGFM之后,自动将代码merge到trunk上。

代码审计

或者说是静态代码审查。Apache PMD, FindBugs都是常用的工具,推荐用Codehaus Sonar系统,即可以实现和Maven的集成,也可以有Web UI可以查看代码质量。提供的审核规则也比较全面,并且可以根据公司的需求来定制。

日志搜集与分析

开发同学不碰线上系统,这是支付系统的原则。那线上系统出问题了怎么办?开发人员总是依赖日志来排查问题,一个日志汇总系统是支付平台必备的基础设施。考虑到日志最终都需要归并到一个日志仓库中,这个仓库可以有很多用途,特别是日常维护中的日志查询工作。多数指标可以在日志上完成计算的。 借助这个系统,也可以完成监控:

支付系统的基础设施建设

日志通过Apache Flume来收集,通过Apache Kafka来汇总,一般最后日志都归档到Elastic中。 统计分析工作也可以基于Elastic来做,但这个不推荐。 使用Apache Spark 的 Streaming组件来接入Apache Kafka 完成监控指标的提取和计算,将结果推送到Zabbix服务器上,就可以实现可扩展的监控。

Apache Flume和Logstash都可以用于日志收集,从实际使用来看,两者在性能上并无太大差异。Flume是java系统,Logstash是ruby系统。使用中都会涉及到对系统的扩展,这就看那个语言你能hold住了。

Apache Flume和Logstash都支持日志直接入库,即写入HDFS,Elastic等,有必要中间加一层Kafka吗?太有必要了,日志直接入库,以后分析就限制于这个库里面了。接入Kafka后,对于需要日志数据的应用,可以在Kafka上做准实时数据流分析,并将结果保存到需要的数据库中。

系统监控

现在基本上 Zabbix 成为监控的标配了。 一个常规的 Zabbix 监控实现, 是在被监控的机器上部署Zabbix Agent,从日志中收集所需要的数据,分析出监控指标,发送到zabbix服务器上。

支付系统的基础设施建设

这种方式要求每个机器上部署 Zabbix 客户端,并配置数据收集脚本。Zabbix的部署可以作为必装软件随操作系统一起安装。

持续集成

毫无疑问,Jenkins就是CI的不二之选。 但是这也只是一个工具,怎么用还得结合业务来实现。而上面列出来的这么多工具和使用要求,如何确保开发人员安规范来实现,并且尽可能地自动化,一个解决方案就是用集成工具将这些活动串起来。这里不详细介绍Jenkins的原理或者它和hudson的恩恩怨怨,重点描述如何使用。

Jenkins使用的要点是设置各个Job。而Job的设置,又分为线上和测试的Job。测试环境的Job分为 部署、启动、停止三个群组。线上分为 预部署、部署、启动和停止四个群组。 在每个群组中,每个项目对应一个可执行Job。

在测试环境部署执行如下工作:

  • 获取受控代码。如果有指定版本号,则下载该版本号对应的代码;否则获取最新的Tag分支并下载该代码。集成是必须从代码开始构建,目的是保证线上运行的系统和版本控制服务器上的代码是一致的,而不是从某人机器上修改后的代码直接传上去的。 如果出现问题,只要获取该版本的代码即可定位到出问题的地方;
  • 执行代码审计
  • 执行maven deploy命令,执行编译、单元测试、版本发布等工作。 注意,这个阶段发布的包,都是SNAPSHOT版本的包。
  • 生成javadoc, 接口文档,发布到测试服务器上,测试人员将对这个文档做验证。
  • 生成单元测试覆盖率报告、代码质量报告。
  • 发布系统到测试环境上。

在线上环境部署执行如下工作:

  • 如果有指定版本号,则下载该版本号对应的代码;否则获取最新的Tag分支并下载该代码;
  • 执行mvn setVersion命令, 将所有SNAPSHOT版本依赖修改为正式版本依赖。
  • 执行代码审计
  • 执行maven deploy命令,执行编译、单元测试、版本发布等工作。 注意,这个阶段发布的包,都是RELEASE版本的包。
  • 生成javadoc, 接口文档,这是正式版本的文档。
  • 发布系统到线上环境上。

以上支付系统中涉及的主要的基础设施,欢迎补充完善。

感谢您对本文的关注,如需要及时收到凤凰牌老熊的最新作品,或者有相关问题探讨,请扫码关注“凤凰牌老熊”的微信公众号,在公众号里留言或者回复,可以尽快处理,谢谢。

支付系统的基础设施建设
原文  http://dockone.io/article/1889
正文到此结束
Loading...