在线支付公司Stripe的服务发现架构设计过程分享

本文介绍Consul如何在Stripe公司扮演服务发现功能的。主要谈论三个方面:
1.什么是服务发现和Consul是什么。
2.Stripe是如何管理关键软件的部署风险。
3.遭遇的挑战和应对措施。

Stripe是一家类似支付宝、Paypal的网上支付平台,Stripe不仅需要处理交易,还需要考虑退款,小费,额外收费,货币汇兑等一系列问题。

什么是服务发现?
负载平衡器将请求分发到任何一个不同的API服务器,在Stripe在成千上万的服务器上运行各种服务。哪一个是API服务器?API运行在哪个端口?关于使用AWS一个令人惊奇的地方是:我们Stripe服务器实例可以在任何时候当机。因此对下面情况有所准备:
1.任何时候API服务器会丢失
2.如果我们需要增加容量,只需要增加额外服务器.

跟踪哪一个盒子(服务器)是否可用,这就是服务发现。我们使用Consul实现服务发现。

其实我们的服务器任何时候都会死机,这还是有好处的,这是对我们基础设施进行定期检验,它们会自动化处理这些问题,当业务真正发生问题,它也很容易处理故障。

Consul介绍
它是个服务发现工具,服务会注册其中以便需要调用时能够发现服务,他是将运行的服务保存在数据库,他有一个客户端软件,专门将信息放入数据库,其他客户端软件则是从数据库中读取。

Consul重要的组件是数据库,数据库包含信息诸如:api-service运行在IP为10.99.99.99的端口12345,目前可用。

独立的盒子(服务器)将信息发送给Consul说: 我运行在api-service的端口12345,我是处于运行状态。

如果你要和api服务交互,你首先向Consul请求1:哪个api-service运行正常?它会给你一串IP地址列表和端口。

Consul是一个分布式系统,使用共识算法Raft进行数据库同步。

Consul在Stripe初期
起初我们只是在服务器启动正常后将数据写入Consul,并没有使用服务发现,编写了一些 Puppet配置设置,不是很难。

这种方式,有助于我们发现数千台带有Consul客户端的服务器运行中潜在的问题,他没有使用它进行服务发现。

这个过程中发现什么问题?
我们发现了Consul存在内存泄漏,现在这个问题已经fix。很庆幸我们没有开始使用它用于服务发现。

一旦我们对Consul运行在我们的基础设施变得更加有信心,开始增加新客户端,用这两种方式降低风险:
1.在少数一些地方使用Consul
2.保持一个后备系统,防止功能中断。

在这个过程中,遭遇了Consul很多坑,当然并不是抱怨,而是强调在使用新技术的时候,重要的是要慢慢的谨慎的推进。

解决了这么多问题以后,开始实现服务发现,但是Consul服务器会响应慢或者没有响应。

大部分是raft故障转移或不稳定时发生这些情况,Consul有强一致性存储,所以它的可用性弱一些。Consul起初这种当机情况可以使用DNS硬编码修改克服,但是随着应用广泛,就不怎么可行了。

询问Consul哪个服务是可用的这个过程是不可靠的,如果不使用Consul的API而需要从其得到哪个服务是否正常,可以吗?

Consul会将名称如monkey-srv翻译成一个或多个IP地址,它是从哪里将名称翻译成IP地址呢?DNS服务器,这样我们使用DNS服务器替代Consul, Consul Template 是一个从Consul数据库中产生静态配置文件的Go程序。

我们开始使用Consul Template为Consul服务产生DNS记录,如果monkey-srv运行在IP 10.99.99.99,产生DNS记录:
monkey-srv.service.consul IN A 10.99.99.99

模版配置有点复杂:


{{range service $service.Name}}
{{$service.Name}}.service.consul. IN A {{.Address}}
{{end}}

但是DNS记录只能提供一个ip地址,你还需要知道服务运行的服务器的端口?DNS SRV 记录则提供服务器端口,使用Consul Template也可产生SRV记录。

如果我们的Consul服务器宕机,我们内部的DNS服务器仍然有其记录!记录可能有点老了,但那可用。关键是我们的dns服务器不是一个花俏的分布式系统,意味着它是一个非常简单的软件,根本不可能自身分裂变得不稳定。这意味着,我可以查询monkey-srv.service.consul获得一个IP地址,并用它来与我的服务交谈!

由于DNS是一个共享的最终一致性的系统,我们可以复制和缓存它,我们有5个DNS服务器,每个服务器都有一个本地DNS缓存和知道如何跟任何5个服务器交谈。因此,它的基本上比Consul更具弹性。

DNS记录更新是每60秒读取一次Consul,但是如果API服务器当机了,我们还是要将请求发到这个IP直到DNS服务器记录更新?使用HAProxy。

HAproxy是一个负载平衡器,对每个服务是发送请求检查健康,它可以确保你的后端正常运行!我们所有的API请求实际上经过HAProxy。这里的它是如何工作:

1. 每60秒,Consul模版会写一个HAProxy配置文件。
2.这意味着HAProxy基本与后端情况精确一致。
3.如果一台机器当机,HAProxy会很快意识到出错1(因为它每2秒进行一次健康检查)

我们是每隔60秒重启一次HAProxy,当我们重启HAProxy时是丢掉它的连接吗?不,使用的是HAProxy的优雅重启特性,虽然可能丢失一些,但是大部分能够保留。

几乎每个服务器都有/healthcheck这个端点用于检查健康,如果正常返回200,有一个标准很重要,因为它意味着我们可以很容易地配置HAProxy检查服务健康。

当Consul当机,HAProxy只会有一个陈旧的配置文件,这将保持继续工作。

开始我们的系统是一个高一致性的数据库,最终我们引人了DNS服务器,数据可能有几分钟的滞后,我们放弃高一致性要求,获得了更高的可用性,Consul当机基本对我们服务发现没有影响、

从中获得一个重要的教训是,高一致性从来不是免费!你必须愿意支付可用性的成本,因此,如果你要使用一个强一致的系统,重要的是要确保这是你真正需要的东西。

总结一下Stripe流程:
当你访问 https://stripe.com/, 请求经过以下步骤:
1.首先请求来到一个公用的负载平衡器,其运行HAProxy

2.Consul Template已经倒入一堆服务器列表在/etc/haproxy.conf配置文件

3.HAProxy 每60秒刷新配置文件

4.HAProxy 发送你的请求到stripe.com一个服务器,确保其运行正常。

当我们开启或关闭服务器,Consul负责从HAProxy自动轮换中删除它们。没有手工工作要做。

Stripe并不需要处理如同Twitter 或 Facebook一样多流量请求, 但我们很关心每笔交易的极端可靠性,部署一个稳定的,优秀的解决方案才是取胜关键,不一定是新技术。

Service discovery at Stripe