Learning Platform
Глоссарий Troubleshooting
Урок 01.03 · 22 мин
Продвинутый
Source codeModule structureFLIP processNavigationRepository tour

Apache Flink — большой проект. На май 2026 в репозитории apache/flink около 2.8 миллиона строк Java и Scala кода, более 200 maven-модулей, около 4 тысяч контрибьюторов в истории. Если вы первый раз открываете этот код, можно растеряться: куда смотреть, чтобы найти, как работает checkpoint? Где живёт RocksDB-интеграция? Что такое модули flink-runtime и flink-runtime-web и в чём разница?

Этот урок — практический tour. К концу вы будете знать структуру репозитория достаточно, чтобы за минуты находить нужный код. Это не разовый навык — это ежедневный инструмент Flink-инженера. Большинство ответов на ваши production-вопросы находятся в коде, а не в документации.

Tour по исходному коду Kafka

Где взять source code

git clone https://github.com/apache/flink.git
cd flink
git checkout release-2.2

Для tour лучше использовать релизный tag, потому что master постоянно меняется. На май 2026 актуальная ветка — release-2.2. Если вы работаете с другой версией — git checkout release-1.20 для предыдущей LTS, и так далее.

Опционально клонируйте параллельно три связанных репозитория:

git clone https://github.com/apache/flink-kubernetes-operator.git
git clone https://github.com/apache/paimon.git
git clone https://github.com/apache/fluss.git

Это не core-Flink, но они важны: K8s operator — рекомендуемый deployment-механизм, Paimon — lakehouse-формат для Flink streaming-tables, Fluss — stream-storage layer (бывший Flink Table Store + новая архитектура).

Структура корня репозитория

После клонирования вы видите много директорий. Не все одинаково важны.

Структура apache/flink — что важно
flink-coreБазовые типы (TypeInformation, Configuration, common utilities). Зависимость почти у всего остального. Здесь нет много runtime-логики — это foundation.
flink-runtimeСамый важный модуль. Дистрибьютед engine: JobManager, TaskManager, scheduler, network stack, checkpoint coordinator, state. Здесь живёт 70% всего, что мы изучаем в курсе.
flink-runtime-webWeb UI и REST API endpoints. Если дебажите проблемы с UI или REST — сюда.
flink-streaming-javaDataStream API. Здесь живут StreamGraph, операторы (AbstractStreamOperator), windowing, watermarks, source/sink API. После 2.0 нет flink-streaming-scala — Scala API удалён.
flink-tableTable и SQL API. Подмодули: flink-table-api-java, flink-table-planner (Calcite integration), flink-table-runtime, flink-sql-client.
flink-librariesCEP, Gelly (graphs, deprecated), Storm compatibility (deprecated). На 2026 — в основном CEP остался жив.
flink-state-backendsHashMapStateBackend, RocksDB state backend. С 2.0+ добавился ForStDB для disaggregated state.
flink-connectorsБольшинство connectors мигрировали в отдельные репозитории (flink-connector-kafka, flink-connector-jdbc и т.д.). Здесь остались базовые: file-systems, kafka legacy, filesystem.
flink-formatsAvro, JSON, Parquet, ORC, CSV, Protobuf serializers. Используется connectors и Table API.
flink-clientsКлиент-сторона: CLI, ClusterClient, как kubectl/flink CLI общается с REST API.
flink-pythonPyFlink: Python API + JVM gateway через Py4J + Beam wrapper для Python UDF.
flink-kubernetesNative K8s integration: Flink самостоятельно может работать как K8s native. Не путать с flink-kubernetes-operator (отдельный repo).
flink-yarnYARN integration. Legacy на 2026 — поддерживается, но новые deployment редко его используют.
flink-testsEnd-to-end и integration tests. Полезно смотреть здесь, когда не понимаете как использовать какой-то компонент — обычно в тестах примеры.
flink-examplesПримерные приложения: WordCount, StateMachine, и т.д. Полезно как точка входа для понимания DataStream API.

Если бы нужно было выбрать три модуля для изучения первыми — это flink-runtime, flink-streaming-java и flink-state-backends. В них живёт основная масса того, что вы будете дебажить в проде.

flink-runtime — самый большой и самый важный модуль. Около 600 тысяч строк кода. Внутри — десятки подпакетов, и навигация в них требует mental map.

Ключевые пакеты flink-runtime
org.apache.flink.runtime.dispatcherDispatcher — точка входа REST API. Принимает job submissions, создаёт JobMaster instances per job.
org.apache.flink.runtime.resourcemanagerResourceManager — управляет TM-ами и slots. Содержит SlotManager как inner component. Standalone, YARN, K8s имеют свои подклассы.
org.apache.flink.runtime.jobmasterJobMaster (per-job) — главный orchestrator конкретного job-а. Содержит ExecutionGraph, общается с TaskExecutor-ами через RPC.
org.apache.flink.runtime.taskexecutorTaskExecutor — это и есть TaskManager-процесс. Регистрируется с RM, исполняет Tasks в Slots.
org.apache.flink.runtime.schedulerScheduler implementations: DefaultScheduler, AdaptiveScheduler, AdaptiveBatchScheduler. Они решают, как и когда запускать ExecutionVertices.
org.apache.flink.runtime.executiongraphExecutionGraph и связанные классы. Главный класс — ExecutionGraph, его части — ExecutionJobVertex, ExecutionVertex, Execution.
org.apache.flink.runtime.jobgraphJobGraph, JobVertex, IntermediateDataSet. Промежуточный граф между StreamGraph и ExecutionGraph.
org.apache.flink.runtime.checkpointCheckpointCoordinator, CompletedCheckpoint, CheckpointMetaData, CheckpointStatsTracker. Здесь живёт алгоритм Чанди-Лэмпорта.
org.apache.flink.runtime.stateБазовые state-классы: StateBackend interface, StateSnapshotStrategy, IncrementalRemoteKeyedStateHandle. Конкретные backends (RocksDB) в flink-state-backends.
org.apache.flink.runtime.io.networkNetwork stack: NetworkEnvironment, RemoteInputChannel, NettyShuffleEnvironment, credit-based flow control живёт здесь.
org.apache.flink.runtime.memoryMemoryManager, MemorySegment, managed memory allocation. Не путать с heap.
org.apache.flink.runtime.rpcRpcGateway, RpcEndpoint, RpcService — RPC абстракция. Раньше это была Akka, сейчас своя обёртка над Pekko (форк Akka после смены лицензии).
org.apache.flink.runtime.highavailabilityHA implementations: ZooKeeperHaServices, KubernetesHaServices. Leader election, JobGraphStore, CompletedCheckpointStore.
org.apache.flink.runtime.metricsMetricRegistry, ReporterFactory. Все метрики, которые видны в JM REST API или экспортируются в Prometheus.
org.apache.flink.runtime.securityAuthentication, Kerberos integration, SSL. Sensitive — изучайте, если работаете с regulated workloads.

Главное правило навигации: большинство классов в flink-runtime имеют имя, по которому можно догадаться, что они делают. CheckpointCoordinator — координирует чекпоинты. TaskExecutor — исполняет таски. SlotManager — управляет слотами. Это упрощает поиск: открыли IDE, Cmd-O / Ctrl-N, набрали Checkpoint, увидели 50 классов, нашли что нужно.

Этот модуль — это то, что вы используете каждый день, если пишете DataStream-программы. Здесь живут:

Ключевые пакеты flink-streaming-java
org.apache.flink.streaming.apiAPI entry points: StreamExecutionEnvironment, DataStream, KeyedStream, WindowedStream — то, что вы используете в job-ах.
org.apache.flink.streaming.api.graphStreamGraph и StreamGraphGenerator. Где DataStream operations превращаются в граф.
org.apache.flink.streaming.api.operatorsAbstractStreamOperator — базовый класс. StreamSource, StreamSink, KeyedProcessOperator, и десятки других.
org.apache.flink.streaming.api.windowingWindowAssigner (Tumbling, Sliding, Session, Global), Trigger, Evictor. Реализация windowing-логики.
org.apache.flink.streaming.api.watermarkWatermark класс — простая структура с timestamp. Сама механика — в WatermarkStrategy и AssignerWithPunctuatedWatermarks.
org.apache.flink.streaming.api.functionsUser-facing function interfaces: MapFunction, FilterFunction, KeyedProcessFunction, AsyncFunction. Здесь то, что implement-ит пользователь.
org.apache.flink.streaming.runtime.tasksStreamTask, OneInputStreamTask, TwoInputStreamTask, SourceStreamTask. Runtime-обёртки операторов в Task. invoke() — главный метод исполнения.
org.apache.flink.streaming.runtime.ioNetwork IO для streaming: StreamInputProcessor, CheckpointBarrierHandler, alignment-механика.
org.apache.flink.streaming.connectorsLegacy connectors. На 2026 большинство мигрировали в отдельные репозитории, но некоторые ещё здесь.

Главный поток понимания: ваш DataStream-код -> StreamGraph (api.graph) -> JobGraph (flink-runtime/jobgraph) -> ExecutionGraph (flink-runtime/executiongraph). На runtime каждая ExecutionVertex становится Task, который запускается через StreamTask#invoke() (runtime.tasks). Внутри StreamTask вызывает operator.processElement() на каждом элементе из input channel.

Это самостоятельный мир. Если вы только DataStream-разработчик, этот модуль для вас второстепенен. Если SQL-инженер — это ваш main фокус.

Структура:

Подмодули flink-table
flink-table-commonБазовые типы: DataType, TableSchema, Schema. Зависимость остальных table-модулей.
flink-table-api-javaJava API: Table, TableEnvironment, TableDescriptor. Без Scala (удалена в 2.0).
flink-table-runtimeRuntime для table-операций: HashAggregateOperator, StreamingJoinOperator, и т.д. Это то, во что компилируется ваш SELECT.
flink-table-plannerCalcite-based planner. Здесь живут RelNode visitors, optimizer rules, физические операторы. Большой модуль — около 200 тыс. строк.
flink-table-code-splitterЕсли сгенерированный код слишком большой (>64KB на метод — JVM лимит), code-splitter разбивает на части.
flink-sql-clientSQL CLI: bin/sql-client.sh запускает интерактивный SQL-shell для Flink.
flink-sql-parserJavaCC-based SQL parser. Расширение Calcite SQL parser для Flink-specific конструкций (WATERMARK FOR, CREATE MODEL).
flink-sql-gatewayREST-based SQL gateway: позволяет внешним клиентам отправлять SQL queries через HTTP. Используется flink-sql-gateway-api.

Главный класс — org.apache.flink.table.planner.delegation.PlannerBase. Сюда уходит ваш SQL. Внутри он использует Apache Calcite для синтаксического анализа, построения логического плана, применения optimizer rules (Calcite Volcano planner) и финального code generation. На выходе — код на Java, который JIT-компилируется в runtime и исполняется.

В модуле 09 разберём этот pipeline до деталей.

Здесь живут конкретные state backend implementations. На 2026 их три основных:

State backends в Flink 2.2
flink-statebackend-rocksdbRocksDB embedded — основной production state backend. LSM-tree, MemTable, SSTable, на disk per TM. Incremental checkpoints.
flink-statebackend-forstForStDB — новый backend для disaggregated state (Flink 2.0+). LSM-tree, но storage на DFS, не на local disk. Async state API.
flink-statebackend-heapHashMapStateBackend (раньше MemoryStateBackend) — state в JVM heap. Только для маленьких state-ов и тестов. В прод не используется.
flink-statebackend-changelogChangelog state backend (FLIP-158, GA 1.17). Дополнительный слой поверх основного backend — async incremental checkpoint через log-структуру.

Главный класс RocksDB-backend — org.apache.flink.state.rocksdb.RocksDBKeyedStateBackend. Снимок (snapshot) — через RocksIncrementalSnapshotStrategy. ForStDB живёт по аналогичному паттерну в flink-statebackend-forst. В модулях 05 и 10 разберём.

Отдельный репозиторий: https://github.com/apache/flink-kubernetes-operator. На 2026 это рекомендуемый способ deployment Flink на K8s. Старая native K8s интеграция (flink-kubernetes в core) считается legacy.

Operator управляет:

  • FlinkDeployment CRD — описывает кластер (JM + TM).
  • FlinkSessionJob CRD — описывает job в существующем session-кластере.
  • Lifecycle: запускает JM/TM как pods, мониторит, рестартит при сбое, делает savepoint upgrades.

Главный controller-класс — org.apache.flink.kubernetes.operator.controller.FlinkDeploymentController в репозитории flink-kubernetes-operator.

В модуле 21 (Capstone) разберём, как построить полноценный production platform на этом operator-е.

FLIP: как читать предложения по дизайну

FLIP (Flink Improvement Proposal) — это форма design document. Каждая значимая фича Flink начинается с FLIP-документа, который обсуждается на dev@flink mailing list, голосуется, и потом имплементируется.

Список всех FLIP: https://cwiki.apache.org/confluence/display/FLINK/Flink+Improvement+Proposals

На 2026 их около 540. Несколько ключевых для нашего курса:

Ключевые FLIP-ы для курса
FLIP-27: Source V2Новая Source API: SplitEnumerator + SourceReader. Заменил SourceFunction. GA в 1.14, SourceFunction удалён в 2.0.
FLIP-191: Sink V2Новая Sink API: Writer + Committer. Заменил TwoPhaseCommitSinkFunction. GA в 1.15.
FLIP-160: Adaptive SchedulerAdaptive Scheduler — может работать с partial resources, ребалансирует parallelism в runtime. Default streaming-scheduler с 2.0.
FLIP-423: Disaggregated StateСамый важный FLIP последних лет. State хранится на DFS, локально только cache. Меняет latency модель и масштабирование state-heavy job-ов.
FLIP-158: Changelog StateChangelog state backend — async incremental checkpoint через log. Уменьшает checkpoint duration на больших state-ах.
FLIP-76: Unaligned CheckpointsUnaligned checkpoints — barrier пересылается без alignment. Сильно ускоряет checkpoints при backpressure.
FLIP-265: Drop ScalaScala API deprecated в 1.18, removed в 2.0. Если у вас был Scala-код — мигрируйте на Java.
FLIP-460: AI Models в SQLCREATE MODEL и ML_PREDICT в Flink SQL. Появилось в 2.1 (preview), стабилизировано в 2.2.

Как читать FLIP: открываете confluence-страницу FLIP-N, видите структуру: Motivation -> Public Interfaces -> Proposed Changes -> Compatibility/Migration Plan -> Test Plan -> Rejected Alternatives. Самая ценная часть — Rejected Alternatives: там описано, какие были обсуждены подходы и почему не выбраны. Это даёт глубочайший контекст для понимания дизайн-решений.

TIP

Каждый раз, когда вы натыкаетесь на странность Flink (“почему так?”), посмотрите, нет ли FLIP-а по этой теме. Часто там лежит ответ — почему API такой, какие альтернативы рассматривались, что в очереди на будущее.

Как навигироваться по коду эффективно

Несколько практических приёмов.

1. IDE setup

Используйте IntelliJ IDEA. Откройте проект как Maven (если IDE не подтянул автоматически — File -> Open -> выберите root pom.xml). Это позволит делать Cmd-O (поиск класса), Cmd-Alt-B (find usages), Cmd-B (go to definition). Без IDE навигация по 2.8M строкам становится мучением.

2. Поиск по конкретным методам

Если знаете, что в логах видели сообщение типа Triggering checkpoint 12345 for job ..., поиск этой строки даст вам класс, который её генерирует:

grep -rn "Triggering checkpoint" --include="*.java" .

Скорее всего вы попадёте в CheckpointCoordinator#triggerCheckpoint.

3. Trace через interfaces

Многие ключевые компоненты Flink — это interfaces с несколькими implementations:

  • Scheduler -> DefaultScheduler, AdaptiveScheduler, AdaptiveBatchScheduler
  • StateBackend -> HashMapStateBackend, EmbeddedRocksDBStateBackend, ForStStateBackend
  • RpcGateway -> много подклассов

Если хотите понять, как что-то работает, начните с interface (он маленький), посмотрите method signatures, потом выберите конкретный implementation для глубокого разбора.

4. Smoke tests как примеры

В flink-tests лежит много end-to-end тестов. Если непонятно, как использовать какой-то API — найдите тест, который его использует. Например, тест для checkpoint API: flink-tests/src/test/java/org/apache/flink/test/checkpointing/CheckpointStorageCheckpointingITCase.java.

5. Git blame для исторического контекста

Когда видите код, который вас удивляет (if (someComplexCondition)), сделайте git blame на соответствующую строку. Найдёте commit, найдёте PR (обычно [FLINK-NNNNN] в commit message), найдёте Jira-тикет, найдёте обсуждение. Это часто отвечает на “почему?”.

Параллельные репозитории

Помимо core apache/flink, есть несколько важных репозиториев, с которыми вы будете работать:

РепозиторийЧто
apache/flink-kubernetes-operatorK8s operator для deployment
apache/flink-connector-kafkaKafka connector (выделен из core в 1.17)
apache/flink-connector-jdbcJDBC connector
apache/flink-connector-elasticsearchElasticsearch sink
apache/flink-cdcChange Data Capture (бывший Ververica CDC)
apache/paimonStream-lakehouse format (бывший Flink Table Store)
apache/flussStream-storage layer (новый проект 2024+)

С 1.17 core-Flink перестал хостить большинство connectors внутри monorepo. Connector-релизы теперь независимы от core-Flink-релизов. Это значит, что у flink-connector-kafka своя версия (например, 3.2.0), и она ставится отдельно как dependency.

Глобальный workflow с source code

Типичный workflow Flink-инженера, который дебажит production:

  1. Видит проблему в production: метрика, лог, ошибка.
  2. Открывает курс, находит соответствующий раздел.
  3. Курс ссылается на класс (CheckpointCoordinator).
  4. Открывает класс в IDE, читает.
  5. Если нужно — find usages на метод, проходит call chain.
  6. Если непонятно — git blame -> PR -> Jira -> дискуссия -> понимание.

Это — норма. Никакая документация не даст такого уровня деталей. Source code — единственная истина.

WARNING

Не бойтесь читать Flink source code. На первый взгляд он выглядит сложным (много interfaces, много шаблонов), но через 2-3 модуля курса вы привыкнете и начнёте чувствовать структуру. Это навык, который пригодится не только в Flink — большинство infrastructure-проектов (Spark, Kafka, Cassandra) построены по похожим принципам.

Что дальше

Это был последний урок модуля 00. Дальше — модуль 01: философия Flink internals. Там разберём:

  • “Stream first, batch is bounded stream” — почему именно так, и как это влияет на runtime-архитектуру.
  • State и time как first-class citizens — историческая перспектива из Storm/MillWheel/Dataflow.
  • Эволюция Flink: что было удалено в 1.x -> 2.x, какие фичи добавлены, почему.

После модуля 01 — фундаментальный блок: архитектура (02), network (03), memory (04), state (05), checkpoint (06), savepoints (07), watermarks (08).

Проверка знанийKnowledge check
Production-инцидент: ваш Flink job (DataStream, parallelism 32, state ~50 GiB, RocksDB backend) показывает в логах JM сообщение типа "Decline checkpoint 47 by task X at TaskExecutor akka.tcp://..." (где X — идентификатор конкретной vertex). Чекпоинт упал, job рестартится, новый чекпоинт через минуту падает с такой же причиной. Опишите ваш source-code-driven workflow для диагностики: куда копать, какие классы открыть, на что обращать внимание.
ОтветAnswer
Workflow: (1) Strings grep по тексту "Decline checkpoint" в flink-runtime — приведёт к CheckpointCoordinator или связанному классу, где формируется это сообщение. (2) Найти, кто посылает Decline в CheckpointCoordinator — это будет TaskExecutor или SubtaskCheckpointCoordinatorImpl на стороне Task. (3) В TaskExecutor найти триггер decline: обычно это исключение в snapshot phase, которое ловится и превращается в DeclineCheckpoint message. (4) Открыть SubtaskCheckpointCoordinatorImpl#checkpointState или подобный — посмотреть, какие фазы snapshot (sync prepare, async snapshot upload to DFS) и где может упасть. (5) Параллельно поднять TM-логи в Kibana/Loki — найти exception stack trace, который привёл к decline. Чаще всего это IOException на upload SSTables в DFS (s3 throttling, network timeout) или OOM в RocksDB pipeline. (6) В flink-statebackend-rocksdb -> RocksIncrementalSnapshotStrategy посмотреть upload logic, конфигурацию retry. Параллельно проверить метрики: lastCheckpointSize, asyncCheckpointDuration, доступность DFS. Этот workflow занимает 30-60 минут, но даёт точный root cause вместо догадок "увеличу timeout".

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Какие три модуля в репозитории apache/flink наиболее важны для изучения первыми, если хотите понимать internals?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 3