2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

Kafka 2.0 升级,携程的实战经验有何可借鉴之处?

  • 2018-12-27
  • 本文字数:4477 字

    阅读完需:约 15 分钟

Kafka 2.0升级,携程的实战经验有何可借鉴之处?

AI 前线导读:这是 InfoQ 特别策划《Kafka 的七年之痒》专题系列文章的第三篇,前两篇文章回顾见《Kafka 从 0.7 到 1.0:过去 7 年我们踩过哪些坑?》《杠上Spark、Flink?Kafka为何转型流数据平台》

背景

早在 2014 年,携程的一些业务部门开始引入 Kafka 作为业务日志的收集处理系统。2015 年,基于 Kafka 的高并发、大数据的特点,携程框架研发部在 Kafka 之上设计了 Hermes Kafka 消息系统,作为大规模的消息场景的统一的中间件。随着业务量的迅速增加,以及具体业务、系统运维上的一些误用,Kafka 现有系统变得不稳定,经历了多次 down 机,故障期间完全不可用,持续时间长达 5 小时以上,恢复缓慢。Kafka 还能用多久?成为一个迫切棘手的问题。问题严重又难以解决,必须做出改变。


笔者在携程框架研发部任职,2018 年 5 月起负责 Kafka 消息系统。重点解决 Kafka 运维使用中的关键问题,建设 Kafka 消息系统应用架构体系。本文分享携程的 Kafka 应用实践。

Kafka 0.9.0 => 2.0 升级之旅

升级的紧迫性

2016 年初,携程 Kafka 升级到了 0.9.0 这一里程碑式的版本。在这个版本里,客户端去除了 zookeeper 依赖,大大提升了系统稳定性。自此以后,到 2018 年 5 月,Kafka 经历了 0.10.x,0.11.x,1.x,1.1 4 个大版本。0.9.0 之上的运维工具,如 Kafka Manager、Kafka Offset Monitor、exhibitor 等,要么停止维护,要么不再有新的功能更新。对于运维中暴露出来的问题,缺少解决方案。


  • 消息发送异步变同步: producer 内部使用了一个内存池,消息进来从池上分配 1 块内存,消息发送后回收。一旦 broker 负载过重,写磁盘慢,producer 的内存池消耗快,回收慢,就会使客户端的异步的消息发送变成同步堵塞,严重影响用户的业务。

  • broker 进程 crash 后无法启动: 进程有时会 crash。由于没有优雅关闭,一些磁盘数据会毁坏,导致无法再次启动。必须手工删除毁坏的数据才能启动。

  • broker under replicated:发现 broker 处于 under replicated 状态,但不确定问题的产生原因,难以解决。(其实是 broker 过载,但难以排查是哪些 topic 导致,应迁移哪些 topic 的数据)

  • 单副本:为缓解 under replicated 问题,采用了一个牺牲可靠性的办法,topic 从多副本变为单副本。但又引发了新的问题,broker 重启、crash,都会导致消息丢失,broker 硬件故障,更会导致 broker 相关的 topic 长期无法使用。

  • 缺少历史监控:Kafka Manager 只提供运行时的指标,无历史指标,出问题后,难以分析事故原因。

  • 监控指标不完善:如 topic、partition、broker 的数据 size 指标。

  • 数据迁移困难:topic 一般在多个 broker 上,当某个 broker 负载重时,需要把这个 broker 上的某个(某几个)topic 的分区迁移到其它 broker。无 UI 工具可用,需要到 broker 机器上执行脚本。费力度高,低效。也缺少把 1 个 broker 上的数据整体迁移到新的 broker 上的能力。

  • broker 负载不均衡:有的 broker 负载重,有的负载轻。无法自动调配。有新的工具(如 cruise-control),但由于 Kafka 版本低,无法使用。

  • 新的 feature 无法使用:如事务消息、幂等消息、消息时间戳、消息查询等。

升级方案

Kafka 官网上明确说明高版本兼容低版本,可以从低版本透明升级。鉴于 Kafka 集群数据量大,broker 数目多,升级失败后的影响大,决定从小到大,分批次灰度升级。


  • 测试环境升级:2 个 3 节点小集群,分 2 批次进行,持续 1 周,运行正常。

  • 生产小集群升级:13 台机器,分 2 批次(5 台,8 台)进行,持续 1 周,运行正常。

  • 生产大集群升级:63 台机器,分 5 批次进行(5 台,8 台,10 台,13 台,27 台),持续 3 周,运行正常。


从调研、测试到实施完成,8 月下旬到九月底,共 6 周时间,从 0.9.0 直升 2.0。升级步骤完全按照官方规范进行,感谢 Kafka 产品的优秀的兼容性。

踩到的坑

共踩到 2 个坑,都在测试环境发现。


  • kafka-server-stop.sh 脚本失效问题:2.0 改变了-cp 的格式,从 lib/*变成了/lib/xx.jar:…,由于依赖项很多,导致命令行非常长。在 centos 7.3 上,ps 命令可以正常显示,但在 centos 6.4 和 7.1 上,会被截断,导致 grep 无法抓取到末尾的 kafka.Kafka 特征,无法定位进程。通过修改脚本解决问题。

  • 单副本 partition 全部 offline(leader 为-1)):2.0 改变了配置 unclean.leader.election.enable 的默认值(从 true 变为 false),多副本时,无影响。由于 2.0 与 0.9.0 的 leader 选举的处理机制不同,升级过程中,同时存在 2.0 与 0.9.0 的 broker,对于单副本的 partition,isr 会被清空(leader 为-1)且无法恢复。通过在 server.properties 里加入配置 unclean.leader.election.enable=true 解决。全部 broker 升级完成后,此项配置可以去除。这是一个严重的不兼容变更,如果在生产环境发现,会导致严重事故。


另外,官方文档里特别说明了应保持数据格式为 0.9.0,不要使用 2.0 格式,以免数据格式转换导致 broker cpu 利用率过高。需在 server.perperties 里加入配置:log.message.format.version=0.9.0。

常见问题的解决

  • broker 进程 crash 后无法启动: 升级后未再遇到此问题。并且重启(stop/start)速度更快,部分负载重的机器,升级前重启一次要花 10 分钟左右,升级后重启一般在 3 分钟以内完成。

  • broker under replicated:升级后可通过后文中的监控方案快速定位到流量大的 topic,迁移流量大的 topic 数据到空闲 broker,可快速降低负载。

  • 单副本:由于升级后容易定位和解决 under replicated 问题,单副本再无必要,可恢复为正常的多副本。

  • 缺少历史监控:升级后通过后文中的监控方案解决。

  • 监控指标不完善:2.0 有丰富的监控指标。如关键的 Size 指标。

  • 数据迁移困难:2.0 提供了 Admin Client。基于 Admin Client 和 Kafka Core,自研了 ops service,能方便地进行日常的 topic/partition/broker 数据迁移运维。如降低机器负载(把 1 个 broker 上部分 topic 数据迁移到其它 broker)、下线旧机器(把 1 个 broker 上的全部数据迁移到其它 broker)等。

  • broker 负载不均衡:新的自动 rebalance 开源工具 cruise-control(https://github.com/linkedin/cruise-control)。

  • 新的 feature:事务消息、幂等消息、消息时间戳、消息查询(KSQL)等。

  • 消息发送异步变同步:客户端比较分散,短期难以统一升级。但可通过后文中的服务端多集群架构改善 broker 负载,避免此问题。

基于 Prometheus 和 Grafana 的 Kafka 集群监控方案

Kafka 监控现状

0.9.0 时,broker 端主要使用 kafka-manager 作为监控工具,能看到实时的 metrics,并做了一些聚合。但数据不落地,无法进行历史数据回放。同时缺少 size 指标,无法查看 topic、partition、broker 的数据量情况。其它的工具如 Kafka Offset Monitor 和 trifecta,在数据量大时查询缓慢,基本不可用。


新的运维工具(如 cruise-control、KSQL 等),无法在 0.9.0 上使用。

Kafka JMX Metrics

Kafka broker 的内部指标都以 JMX Metrics 的形式暴露给外部。2.0 提供了丰富的监控指标,完全满足监控需要。后文中的监控截图里有常见的监控指标,完全的指标列表可通过 JConsole 查看 Kafka 的 MBeans。

可用的开源组件

  • Prometheus:Prometheus 是一个云原生的 metrics 时间序列数据库,具备 metrics 采集、查询、告警能力。笔者今年 3 月接触到,非常喜爱。

  • Grafana: metrics 可视化系统。可对接多种 metrics 数据源。

  • JMX Exporter:把 JMX metrics 导出为 Promethues 格式。https://github.com/prometheus/jmx_exporter

  • Kafka Exporter:汇聚常见的 Kafka metrics,导出为 Prometheus 格式。https://github.com/danielqsj/kafka_exporter

监控方案

  • JMX Exporter:部署到每台 broker 上。

  • Kafka Exporter:部署到任意 1 台 broker 上。

  • Prometheus:部署到 1 台独立机器上,采集 JMX Exporter 和 Kafka Exporter 上的数据。

  • Grafana:部署到 1 台独立机器上,可视化 Prometheus Kafka metrics 数据。对于 cluster、broker、topic、consumer 4 个角色,分别制作了 dashboard。

监控截图示例




Kafka 多集群解决方案

为什么要多集群

15 年,生产只搭建了 1 个集群,不到 10 个节点,但随着业务的大量接入和某些业务的不合理使用,以及驾驭能力不足(有问题加机器),生产集群扩大到 63 个节点。全公司业务混杂在一起,部分业务数据量极大。1 个 topic 数据量激增,或某个 broker 负载过重,都会影响到多个不相干业务。甚至某些 broker 的故障导致整个集群,全公司业务不可用。集群节点数目过大,也导致运维、升级过程漫长,风险极大。


迫切需要从多个不同维度把大集群分拆为小集群,进行业务隔离和降低运维复杂度。

多集群架构

原生的单集群架构



引入 1 个 meta service,改造为多集群架构



同时仍然提供统一的 client 给用户,封装多集群相关的配置(如哪个 topic 在哪个集群上),用户仍然以原生的单集群的方式使用。可以通过调整路由规则,动态地把 topic 从 1 个集群迁移到另一个集群,对用户透明。

多集群路由

单机群模式下,只需要 topic 便可进行消息的生产、消费。多集群模式下,需要知道 1 个<cluster, topic>二元组。客户端、topic、consuemer 的元数据,构成了影响路由的因子。根据这些路由因子,可灵活制定路由规则。



寻址过程



当路由规则变化时,client 可以近实时地感知到(2 分钟左右),自动重启使路由规则生效。

实际案例

携程量最大的 topic,流量峰值入口 250m/s,出口 8g/s。出口流量远大于入口流量,写少读多。入口流量稳定,但出口流量经常飙升(消费者增加)。出口流量飙升,导致磁盘利用率升高,反过来大幅降低写入速度,使消息生产异步变同步,严重影响业务。由于业务设计不合理,只消费部分数据的用户,必须消费全量数据,需要把原始的 topic 数据进行处理,分拆为专用的 topic 以减少无效消费。


基于多集群架构,从 1 个集群变为读写分离的 3 个集群,降低数据写入的风险,减少无效消费。2 周左右实施完成。对消费者透明。


企业级 Kafka 应用架构

Kafka 原生的集群模式使用简单,能满足少量业务的需要。但对于大型企业(网站),大量的业务使用 Kafka,数据量、流量极大,必然同时存在多个集群,需要对用户的接入、运行时监控、集群运维提供统一的解决方案。下图是携程正在研发的解决方案,部分架构元素已开发完成并投产。将来会开源出来,回馈社区。



说明


  • Console UI/Service:面向用户。用于 topic/consumer/cluster 注册、配置管理、集群运维的统一的治理系统。数据落地到 DB 持久存储。待开发。

  • Meta Service:面向 client(producer/consumer)。从 console service 加载元数据信息(路由规则等),供 client 寻址用。已投产。

  • Ops Service:基于 Kafka admin client 和 Kafka core,把运维服务化,降低运维复杂度。已开发基本功能,待投产。

  • Kafka Clusters:按多个维度搭建的多个集群。可灵活搭建和运维变更。

  • Monitoring (Prometheus + Grafana):集群监控解决方案。已投产。

作者介绍

赵强,携程框架研发部技术专家。曾负责 SOA 框架,主导携程大规模服务体系架构建设。现负责 Kafka 消息系统。专注于服务、配置、消息、监控等领域。


2018-12-27 08:009069

评论 3 条评论

发布
用户头像
赞了,很多是业务逼出来的;
2018-12-27 22:34
回复
用户头像
很棒
2018-12-27 10:31
回复
没有更多了
发现更多内容

如何预防勒索攻击事件?这份安全自查指南请查收

京东科技开发者

数据安全 数据加密 系统安全

情报合成研判系统开发,智慧警务解决方案

t13823115967

智慧公安

一文教你看懂缓存穿透、击穿、雪崩、降级等异常

鄙人薛某

Java 缓存 后端 缓存击穿 缓存雪崩

安装MySQL后,需要调整的10个性能配置项

Simon

MySQL percona server

《css大法》之使用伪元素实现超实用的图标库(附源码)

徐小夕

CSS css3 大前端 CSS小技巧

《算法导论》.pdf

田维常

原创 | 使用JPA实现DDD持久化-O/R映射元数据:类级映射-实体和值对象

编程道与术

Java hibernate 编程 mybatis jpa

业务中台建设-数据

孝鹏

架构 中台 数据 赋能

Java架构速成笔记:七大专题,1425页考点,挑战P8岗

Java架构追梦

Java 学习 面试 java架构

话题讨论 | 立一个近期的flag,你会想到什么?

xcbeyond

话题讨论

北京奥森小景

小马哥

摄影 美景 奥森 28天写作

Mybatis 中xml和注解映射,这次终于搞明白了

田维常

mybatis

不满意社区的轮子,我们自创了一套 React Hooks 风格的数据加载方案

LeanCloud

API React Hooks

时序数据库DolphinDB与Druid的对比测试

DolphinDB

数据分析 时序数据库 Druid 数据库选择 DolphinDB

关于Kubernetes和Docker关系的八个问题

杨明越

原创 | 使用JPA实现DDD持久化-领域模型:对象的世界

编程道与术

Java hibernate 编程 mybatis jpa

区块链司法存证应用落地应用解决方案

t13823115967

区块链落地开发

原创 | 使用JPA实现DDD持久化-O/R映射元数据:映射注解分组

编程道与术

Java hibernate 编程 mybatis jpa

全球熵ETV系统APP软件开发

系统开发

operator-sdk & kubebuilder

QiLab

k8s operator-sdk kubebuilder crd

P8架构挑战:七大专题1425页考点,你能成功吗?

小Q

Java 学习 程序员 架构 面试

网咯请求中的 connectTimeout 和 soTimeout

不在调上

没有它你的DevOps是玩不转的,你信不?

华为云开发者联盟

容器 DevOps 微服务

人脸识别是如何实现的

anyRTC开发者

ios 音视频 WebRTC 人脸识别 安卓

开发实践丨用小熊派STM32开发板模拟自动售货机

华为云开发者联盟

物联网 小熊派 开发板

话题讨论 | 30 张图解高并发服务模型你必须这些

程序员柠檬

话题讨论

可见性是什么?(通俗易懂)

叫练

volatile JMM 多线程 synchronized

话题讨论 | 选择做一个程序员,你后悔过吗?

xcbeyond

话题讨论

使用JPA实现DDD持久化-O/R映射元数据-特殊属性映射:ID、Version和Transient

编程道与术

Java hibernate 编程 mybatis jpa

甲方日常 65

句子

工作 随笔杂谈 日常

英特尔携手德晟达、游密,发布云会议终端解决方案,打造视听新体验

E科讯

Kafka 2.0升级,携程的实战经验有何可借鉴之处?_语言 & 开发_赵强_InfoQ精选文章