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 лучше использовать релизный tag, потому что master постоянно меняется. На май 2026 актуальная ветка — release-2.2. Если вы работаете с другой версией — git checkout release-1.20 для предыдущей LTS, и так далее.
Опционально клонируйте параллельно три связанных репозитория:
Это не 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-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: сердце Flink
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.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.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 классов, нашли что нужно.
flink-streaming-java: DataStream API
Этот модуль — это то, что вы используете каждый день, если пишете 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.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.
flink-table: Table и SQL
Это самостоятельный мир. Если вы только 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 до деталей.
flink-state-backends: state storage
Здесь живут конкретные 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 разберём.
flink-kubernetes-operator: deployment
Отдельный репозиторий: 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, голосуется, и потом имплементируется.
На 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 ..., поиск этой строки даст вам класс, который её генерирует:
Если хотите понять, как что-то работает, начните с 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-operator
K8s operator для deployment
apache/flink-connector-kafka
Kafka connector (выделен из core в 1.17)
apache/flink-connector-jdbc
JDBC connector
apache/flink-connector-elasticsearch
Elasticsearch sink
apache/flink-cdc
Change Data Capture (бывший Ververica CDC)
apache/paimon
Stream-lakehouse format (бывший Flink Table Store)
apache/fluss
Stream-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:
Видит проблему в production: метрика, лог, ошибка.
Открывает курс, находит соответствующий раздел.
Курс ссылается на класс (CheckpointCoordinator).
Открывает класс в IDE, читает.
Если нужно — find usages на метод, проходит call chain.
Это — норма. Никакая документация не даст такого уровня деталей. 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
Прикладной
Закончили урок?
Отметьте его как пройденный, чтобы отслеживать свой прогресс