我們將食べログ內部的Pub/Sub消息基礎架構替換成Apache Kafka的故事

这篇文章是食之旅2021年日历的第21天的文章。???

首先

你好。我是技术部微服务化团队的@SinceK13。

微服务团队的使命是构建一个系统基础设施,以解决在庞大的单体式服务中进行开发所带来的困难,并使小团队能够自主决策进行开发。

本篇将介绍我们在微服务团队中所进行的工作,将食べログ的内部生产订阅(Pub/Sub)消息基础设施升级为使用 Apache Kafka(以下简称 Kafka)进行的生产订阅(Pub/Sub)消息基础设施的故事。

此外,同一团队的 @weakboson 在12/14日发布了一个标题为”支持食评网餐厅搜索的Debezium和Apache Kafka”的文章,介绍了与本篇文章不同的Kafka应用案例。如果您对此感兴趣的话,欢迎不妨一看^^

Pub/Sub消息传递是一种方式

消息(数据)的发送者被编程为在没有特定接收者的情况下发送消息(数据)。
发送者被称为发布者(Publisher),接收者被称为订阅者(Subscriber),因此被称为“发布-订阅消息模型(Pub/Sub消息模型)”。
调解者被称为“消息代理人”因为其调解消息。
在代表性的基于主题的Pub/Sub消息系统中,消息按照“主题”进行分类,发布者根据主题发送消息,订阅者接收他们感兴趣的主题的消息。

pubsub_1.png

Pub/Sub消息传递的特点

主要有以下三个特点。

非同期:当发布者发送消息后,可以在等待订阅者的响应之前开始下一个处理。
疎結合:只要发布者和订阅者能够与消息代理进行通信,它们便无需了解彼此的存在。
可扩展:无论是发布者还是订阅者,它们之间没有限制为一对一的关系,即使它们增多,也无需互相关注。

pubsub2.png

当面这种特点对于想在微服务之间执行异步处理的情况非常有用。

之前的Pub/Sub消息基础设施的配置

old_architecture.jpg

另外,以前的Pub/Sub消息传递基础设施中有一个功能,即可以跟踪消息的机制。
在Pub/Sub消息传递中,我之前提到发布者和订阅者无需知道彼此的存在,但从业务角度来看,有时需要查询消息的情况,因此需要这样的机制。

具体来说,我们在发布(或试图发布)的消息中都会分配一个在整个系统中唯一的“相关ID(correlation id)”,并且在消息发布者、消息API进行消息中继、订阅者成功处理以及有时的处理失败等不同的节点上,会与时间戳和数据一起将日志输出与相关ID关联起来(称为跟踪日志)。通过这种方式,可以使用相关ID来跟踪消息的流动。

追踪日志将以 JSON 格式输出以下项目。

フィールド名説明例cid相関ID(メッセージごとにユニーク)”04b85967-2ab1-4d3a-8285-ed230c698429″topicトピック”hoge_topic”eventメッセージ発行、中継、処理など”occurred”(メッセージ発行)bodyメッセージのデータ{“hoge_id”:12345}processing処理に要した時間0.009870573occurred_atメッセージが発行された時刻”2021-12-21T08:06:34+09:00″processed_atメッセージがホストで処理された時刻”2021-12-21T08:06:36.939+09:00″hostメッセージを処理したホスト”hoge-server1″

学科
练习
题目
主题
议题

以前的Pub/Sub消息基础设施存在以下问题。

    • 内製 Pub/Sub が不安定でときどきメッセージ消失を起こしてしまう

 

    • メッセージは正常に処理されても即消えてしまい、トレースログは数日間しか保持されない

 

    メッセージの追跡調査や処理に失敗した時のリトライはサーバに入って CLI で行う必要があり大変

根据去年 @tkyowa 在Advent Calendar中提到的“逐步改善食べログ的大规模遗留系统”的努力,正如他所说,这个Pub/Sub消息平台的功能的业务重要性逐年增加,迫切需要尽快改进。

配置新的 Pub/Sub 消息平台

Kafka簡略図_アドベントカレンダー用.jpg

技术选择

为了防止消息消失

Kafka1.png
    • 大量のメッセージを高速に処理できる

 

    • Broker 複数台構成が前提でメッセージを複数台に同期して冗長化する

耐障害性が高い(1台でも稼働していればメッセージを消失しない設定が可能)

メッセージをディスクに書き込む

データの永続化が可能

Consumer Group ごとに独立してメッセージを読み出すことができる

ファンアウトと同等のことができる

根据这些特点,我们可以说它是一个高速且不容易发生消息消失的消息代理。

即使只有一个操作,也可以设置不让消息消失。以三个代理器的配置为例进行说明。

以下是经纪人(Broker)和制片人(Producer)的关键设置。

经纪人设定

項目設定値項目説明備考Broker 数3-最小限冗長性の定番default.replication.factor3Replica の複製数。 Leader Replica と Follower Replica の合計数O’Reilly Kafka でも最小 Replica 数として3台が推奨されているmin.insync.replicas2正常終了と見なすために最低限同期が必要な Replica 数この Replica 数同期を行う必要があるので、1台の故障に対しては問題なく動作を続けることができる。2台故障した場合はメッセージ受付を停止する

制作人的设定

項目設定値項目説明備考acksallProducer が送信成功と見なすタイミングall にすることで、すべての insync.replicas のメッセージ受信完了を待ってから、確認応答またはエラーを返すようになる。複数の Broker がメッセージを保持するので、いずれかがクラッシュしてもメッセージは確実に残る
Frame 4.jpg

此外,“即便消息被正常处理,也会立即消失”这个问题通过 Kafka 的偏移量(offset)这一已读管理概念得以解决。
Kafka 并非像队列一样删除已处理消息,而是通过偏移量这一位置信息进行管理。
已处理消息会被保存一定的时间或容量,因此可以查询过去的消息,也可以回滚偏移量以便重新处理。

为了便于对消息跟踪调查和处理失败时进行重试。

为解决以下问题,即“当消息跟踪调查或处理失败时,需要进入服务器并在CLI中执行重试,这是非常麻烦的”,我们提出了通过GUI可操作的解决方案。

食べログ将Web服务器和AP服务器的日志传输到Google Cloud Platform(以下简称GCP)的Cloud Logging,因此在GCP的日志浏览器上进行日志调查是常见的做法。

因此,通过将Pub/Sub消息传输基础设施的跟踪日志也传送到Cloud Logging,使得可以像其他日志一样进行调查。

此外,通过将跟踪日志导出到BigQuery中,我们可以进行更详细的调查。

另外,我们选择了 Karafka 作为 Ruby 版的 Kafka 库。Karafka 是一个非常全面支持 Consumer 功能的 gem。它提供了与部署相关的 SIGNAL 处理、Graceful 关机以及 CLI 等功能。
此外,Karafka 还提供了一个名为 Karafka Sidekiq Backend 的 gem,可以将 Consumer 的消息处理委托给 Sidekiq。

因为以前的Pub/Sub消息平台也使用了Sidekiq,所以通过使用Karafka Sidekiq后端,订阅方的代码几乎可以直接重用。

此外,还可以使用 Sidekiq WebUI 从 Sidekiq 的图形用户界面中进行进度查看、强制停止以及重试处理失败的消息,这使得调查工作更加容易。由于 Kafka 消费者没有管理界面,所以使用 Karafka Sidekiq 后端也是一个优点。

此外,使用Karafka Sidekiq Backend可以使Sidekiq处理消息,因此可以更容易地处理处理时间长达数十秒至数分钟的重型消息,这也是选择Karafka Sidekiq Backend的理由之一。虽然可以直接使用Kafka Consumer来处理消息,但是如果消息处理时间超过Consumer的生存检查间隔,那么就会被视为消息处理失败,因此当处理时间较长的消息时,推荐使用Karafka Sidekiq Backend。

最终的结果

留言不再消失了。

由于选择了Kafka作为消息中间件,我们成功解决了自研的发布/订阅系统不稳定且偶尔发生消息丢失的问题。从7月开始,我们已经开始在新的发布/订阅消息基础设施上进行正式运营,并且至今从未发生过任何消息丢失,一直保持运行状态。

不久前,我们能够进行几周甚至几个月前的调查了。

在以前的Pub/Sub消息基础设施中存在一个问题,即“即使消息被正确处理,它也会立即消失,并且跟踪日志只会保留几天”,但是Kafka会将消息写到磁盘上以实现持久化。此外,通过将跟踪日志传输到GCP并长期保留,我们现在可以对数周甚至数月之前的调查进行分析。

现在可以通过GUI轻松进行调查,重新尝试处理失败的消息。

使用以前的Pub/Sub消息传递基础设施时,存在一个问题:“当消息调查或处理失败时,需要进入服务器并使用CLI进行重试,非常麻烦”。然而,通过将追踪日志传输到Cloud Logging,现在可以通过GUI轻松进行调查。此外,通过将追踪日志导出到BigQuery,还可以进行更详细的基于SQL的调查。另外一个成果是,现在可以使用与其他日志相同的方法进行追踪日志的调查。

sidekiq_webui_アドベントカレンダー用.jpg

最后

我们正在招募与我们一起推进改进的伙伴加入微服务团队。微服务化团队拥有决策参与权,从系统改进的初期阶段,如战略制定和技术选择等,具有很大的自主权和挑战性的职位。如果您对食べログ的“连接用户和餐厅”概念表示赞同,请务必申请加入我们。

欢迎希望先进行非正式交谈以进行信息交流的人。在申请时,请在自由文本框中注明“希望非正式交谈”。

明天是@sadashi关于“如何应对食评应用上的技术债务”的讲座。敬请期待!

bannerAds