极客视点
极客时间编辑部
极客时间编辑部
113245 人已学习
免费领取
课程目录
已完结/共 3766 讲
2020年09月 (90讲)
时长 05:33
2020年08月 (93讲)
2020年07月 (93讲)
时长 05:51
2020年06月 (90讲)
2020年05月 (93讲)
2020年04月 (90讲)
2020年03月 (92讲)
时长 04:14
2020年02月 (87讲)
2020年01月 (91讲)
时长 00:00
2019年12月 (93讲)
2019年11月 (89讲)
2019年10月 (92讲)
2019年09月 (90讲)
时长 00:00
2019年08月 (91讲)
2019年07月 (92讲)
时长 03:45
2019年06月 (90讲)
2019年05月 (99讲)
2019年04月 (114讲)
2019年03月 (122讲)
2019年02月 (102讲)
2019年01月 (104讲)
2018年12月 (98讲)
2018年11月 (105讲)
时长 01:23
2018年10月 (123讲)
时长 02:06
2018年09月 (119讲)
2018年08月 (123讲)
2018年07月 (124讲)
2018年06月 (119讲)
时长 02:11
2018年05月 (124讲)
时长 03:16
2018年04月 (120讲)
2018年03月 (124讲)
2018年02月 (112讲)
2018年01月 (124讲)
时长 02:30
时长 02:34
2017年12月 (124讲)
时长 03:09
2017年11月 (120讲)
2017年10月 (86讲)
时长 03:18
时长 03:31
时长 04:25
极客视点
15
15
1.0x
00:00/05:54
登录|注册

一个每秒超过3万请求的微服务开发经历

讲述:丁婵大小:8.10M时长:05:54
你好,欢迎收听极客视点。
ifood 是一家巴西外卖平台公司,平均每天送出 100 多万份订单,每年增长 110% 左右。作为一家外卖平台,访问峰值大多出现在午餐和晚餐前后,周末的时候会更高一些。
在一些特殊的日子里(比如由于营销活动),访问量曾打破记录,平台获得了历史最高峰值,比如一个微服务达到了每分钟 200 万请求的峰值。
最近,ifood 的一名工程师介绍了他们的微服务开发案例,公众号“高可用架构”对其进行了翻译,如下。

故事背景

在内部,我们把这个微服务称为账号元数据。尽管这是一个通用的名字,但它也解释了这个服务的目的:它处理账号的元数据。什么是账号元数据?主要是指那些非关键的用户信息。它就像一个通用的存储,把不同地方的数据汇总起来,方便地服务于客户端调用,同时也服务于其他微服务,这样开发者们只需要调用一个微服务,而不是 10 个微服务。
最早在 2018 年时,账号元数据的建立主要是为了放一些杂乱的信息。我们需要一点结构和查询能力,而且很容易扩展,所以我们选择了 AWS 提供的 DynamoDB。在这里要说明一下,我们明白系统可能会增长,当时公司也已经相当大了,平均负载是有挑战的。但是,我们还是没有预估到,我们会从每分钟 1 万个请求增长到 20 万,然后最终达到了 200 万。
这个微服务刚发布后,并没有多少人使用。然而,几周后做出的一些新的架构调整,让这个系统变得非常重要。现在,账号元数据除了用户每次打开应用的时候都会被调用,而且被很多团队在很多其他不同的场景下访问。所以现在的问题是,我们需要能够稳定地每分钟处理 200 万个请求。

深入技术

正如前面所说,这个微服务存储了账号的元数据。在数据库中,我们将这些元数据分割成不同的上下文,在代码中称之为 namespace(命名空间)。一个客户(customer_id 作为分区键)可以有 1 到 N 个 namespace(作为排序键),而且每个 namespace 都有一个固定的、强制性的 schema,插入前通过 jsonschema 来定义和检查。有了它,我们就可以确保无论如何将数据插入到哪个 namespace 中,都会遵从它的模式和正确的用法。
我们使用这种方法,是因为这个系统中,读和写是由不同的团队来完成的。
插入工作是由数据科学团队完成的,他们每天都会从内部工具中导出数百万条记录到这个微服务中,并通过 API 将这数百万条记录分割成每次 500 条进行批量调用。所以,一天中的某个特定时间,这个微服务会收到数百万次的调用(间隔 10 到 20 分钟),将数据插入到 DynamoDB 中。如果接收 API 直接将数据写入数据库,就会碰到 Dynamo 扩展的一些问题,而且响应时间过慢也是个问题。解决这个瓶颈的方法是数据团队直接将数据写入数据库,但是,我们必须检查这些记录是否符合命名对应空间的 jsonschema,这是此微服务的责任。
所以解决方案是,API 接收这批记录,并将它们发布在 SNS/SQS 消息队列上,而 SNS/SQS 将被另外一个模块来消费,然后验证这些记录,如果没问题,就保存在 Dynamo 上。通过这种方式,接收到这批记录的接口可以非常快速地响应,我们不依赖 HTTP 连接进行写入,因为与 Dynamo 的通信可能会失败,再次尝试可能会使 HTTP 响应时间变得非常慢。另一个好处是,我们可以通过调整队列消费程序,来控制从 SQS 读取数据以及在 Dynamo 上写入数据的快慢。
在这个流程之外,账号元数据也会被另一个服务调用,每当平台收到一个新订单就会调用它,并更新这个订单的一些信息。鉴于 ifood 每天订单量超过 100 多万,微服务也会接受到这个数量的调用。
在这样的调用量下,出现一些异常的情况也是很正常的。在我们的案例中,我们看到 Dynamo 中的一些查询耗时超过 2 - 3 秒,而 99.99% 的调用都在 17ms 以下。尽管这些慢查询每天只有几千次,但我们希望为团队提供更好的 SLA。所以我们决定如果碰到 Dynamo 超时就进行重试。也和相关团队也讨论过,让他们在调用我们的 API 时配置一个低超时。他们大多数 HTTP 客户端的默认时间是 2s,所以我们改成了大约 100ms。如果他们碰到超时(比方说微服务对 dynamo 做了重试,但又失败了),他们可以重试,并且很可能会马上得到响应。
为了部署它,我们使用 k8s(达到 70 个左右的 pod),并随着每秒请求的增长而进行扩展。DynamoDB 被设置为供应(provision)而非按需。
一个重要的步骤是确保系统能够在真正高吞吐量的情况下健康地工作,我们每天对它进行负载 / 压力测试,以确保新版本部署没有降低性能。通过这个负载测试的结果,我们可以跟踪一个接口是随着时间的推移和它的发展而变好还是变坏。
最后总结一下,本文简单描述了一个高性能微服务工作方式。虽然微服务还包括一些其他的工作流程,跟主题无关就不展开赘述。希望今天的内容对你有所帮助。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
该免费文章来自《极客视点》,如需阅读全部文章,
请先领取课程
免费领取
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
26
沉浸
阅读
分享
手机端
快捷键
回顶部