☰
Apache Pulsar Python 3 迁移实践:PIP-56 与镜像运行时升级指南
2026/10/9 1:54:21 网站建设 项目流程
  • 消息队列
  • 流处理
  • 后端
  • 微服务
  • 消息路由

【免费下载链接】pulsar

Apache Pulsar - distributed pub-sub messaging system

项目地址:https://gitcode.com/gh_mirrors/pu/pulsar
点击查看免费下载

PIP-56(Python3 Migration)是 Apache Pulsar 社区提出的将默认 Python 运行时从 2.7 迁移到 3.7 的改进提案。本文以该提案为核心,结合当前仓库中 docker/pulsar/Dockerfile、docker/pulsar/Dockerfile.wolfi 以及 Pulsar Functions Python 运行时源码,讲解迁移的背景、影响面、落地改动与验证方法,帮助你理解 Pulsar 镜像中 Python 运行时的演进逻辑,并掌握自定义 Python 版本镜像的构建思路。

PIP-56 提案背景:Python 2.7 的 End of Life

Python 2.7 于 2020 年 1 月 1 日正式停止官方维护(End of Life)。而在此之前的较长一段时间里,Apache Pulsar 存在两个与 Python 2 深度绑定的现实:

  1. PyPI 上发布的 Python 客户端制品仍是 Python 2.x 兼容的构件,社区持续在 pypi 上分发 python 2 的 wheel 包;
  2. Pulsar 官方镜像中 Python 2.7 是默认运行时,这直接影响两类用户:
    • 依赖 Python 客户端的安装场景;
    • 使用 Python 编写 Pulsar Functions、并直接运行在官方镜像上的函数用户。

PIP-56 正是针对这一现状提出的系统性迁移提案,其核心主张包含三点:

  1. 将 Pulsar 镜像中的默认 Python 版本从 python27 升级到 python37;
  2. 将集成测试(integration test)迁移到 python37 运行时上执行;
  3. 公告 Python 3.7 的弃用节奏,同时承诺在 2020 年底前继续支持 python27 制品。

影响分析:谁会被这次默认运行时变更波及

提案明确指出,变更默认 Python 安装会给两类群体带来直接冲击:

  • 使用 Python 客户端的安装场景:如果默认 Python 解释器从 2 变为 3,依赖旧解释器行为或旧版本依赖树的部署会受到破坏,且不存在简单的自动迁移路径;
  • 运行 Python Functions 的用户:官方镜像内预置的 Python 运行时一旦切换,函数运行环境随之变化,需要用户重新验证函数代码的 Python 3 兼容性。

与此同时,迁移带来的一个必然结果是:python27 的测试覆盖会逐步缩减,因为默认集成测试将显式针对 python37 运行。提案给出的缓解策略是:

  • 通过**明确的发布说明(release notes)**通知受影响用户;
  • 提供构建自定义镜像、以 python27 为默认解释器的操作指引;
  • 在当年年底之前继续发布 python27 制品,为存量用户留出过渡窗口。

需要落地的改动清单

PIP-56 将改动范围圈定在少量 docker 与 pom 文件中,具体包括:

  1. 移除 Python 2 的安装步骤:删除 Pulsar 镜像 Dockerfile 中 python2 的安装行,以及 dashboard 镜像 Dockerfile 中的对应安装逻辑;
  2. 添加符号链接:建立python3 -> python、pip3 -> pip的 symlink,使既有脚本和用户在无感知的情况下使用 Python 3;
  3. 移除 Python 27 wheel 的安装:不再在镜像中安装面向 python27 的客户端 wheel。

需要说明:提案引用的 Dockerfile 行号对应的是提案撰写时的历史版本。当前仓库中的镜像定义已经历多轮演进(Alpine 基础镜像、Wolfi 基础镜像、JDK 25/21、mimalloc 预加载等),但"Python 3 为唯一默认运行时"这一结论已在 docker/pulsar/Dockerfile 与 docker/pulsar/Dockerfile.wolfi 中得到充分落实。

迁移后的镜像现状:源码级验证

Alpine 版镜像:python3 + py3-pip

当前 docker/pulsar/Dockerfile 的基础镜像阶段(FROM alpine:$ALPINE_VERSION)通过apk add安装的 Python 相关包已经完全 Python 3 化:

RUN apk add --no-cache \ bash \ python3 \ py3-pip \ py3-yaml \ gcompat \ libgcc \ libstdc++ \ libuuid \ ca-certificates \ procps \ curl \ bind-tools \ openssl \ coreutils

其中python3、py3-pip、py3-yaml分别是 Python 3 解释器、pip 与 PyYAML 的 Alpine 包。py3-yaml对 Pulsar Functions 尤其重要——Functions 运行时通过 YAML 解析函数配置(对应 conf/functions_worker.yml 等配置文件的使用场景)。

随后,镜像内通过pip3安装一组与 Pulsar Functions Python 运行时严格绑定版本的依赖(docker/pulsar/Dockerfile):

ARG PULSAR_CLIENT_PYTHON_VERSION RUN pip3 install --break-system-packages --no-cache-dir \ --only-binary \ grpcio==1.78.0 \ protobuf==6.33.6 \ pulsar-client[all]==${PULSAR_CLIENT_PYTHON_VERSION} \ kazoo
  • grpcio与protobuf的版本被显式固定,且与仓库内_pb2.py生成的 stubs 保持兼容(详见下文"stubs 生成"小节);
  • pulsar-client[all]==${PULSAR_CLIENT_PYTHON_VERSION}是 Python 客户端全量依赖安装,版本由构建参数注入,构建时可通过--build-arg PULSAR_CLIENT_PYTHON_VERSION=...覆盖;
  • kazoo用于 ZooKeeper 交互,支撑 Functions 运行时的协调逻辑。

Wolfi 版镜像:可参数化的 Python 版本

docker/pulsar/Dockerfile.wolfi 以 Chainguard Wolfi 为基础镜像,Python 版本通过构建参数显式声明(默认 3.12),迁移思路一脉相承:

ARG PYTHON_VERSION=3.12 RUN apk add --no-cache \ bash \ python-${PYTHON_VERSION} \ py${PYTHON_VERSION}-pip \ ...

依赖安装同样使用pip3,并额外补充了pyyaml(docker/pulsar/Dockerfile.wolfi)。可以看到,PIP-56 提出的"python3 为默认、pip3 为默认包管理器"在两条镜像链路上都已固化为事实标准。

构建自定义镜像:如何让 python27 成为默认

对于仍需 Python 2 的存量用户,PIP-56 给出的方向是"构建自定义镜像"。基于当前 Dockerfile 的结构,可采取以下做法(仅作操作说明,仓库本身不提供 python2 支持):

  • fork 或复制docker/pulsar/Dockerfile 到自己仓库;
  • 将apk add中的python3替换为python2(Alpine 老版本仓库)或改用 Ubuntu/Debian 基础镜像中的python2.7;
  • 将py3-pip、py3-yaml替换为对应的 Python 2 版本,并把pip3 install改为pip install;
  • 移除或替换grpcio==1.78.0、protobuf==6.33.6等仅支持 Python 3 的新版本依赖,回退到兼容 Python 2 的历史版本(如 grpcio 1.24.x、protobuf 3.x 早期版本)。

需要注意:当前仓库的 Functions Python 运行时源码(见下文)对 Python 2 仅保留了有限兼容逻辑,且 grpcio/protobuf 已推进到 Python 3-only 的版本线,因此自定义 python2 镜像需要同步回退这些依赖才能实际运行。

运行时源码中的 Python 3 迁移痕迹

PIP-56 的迁移不仅体现在 Dockerfile,Pulsar Functions 的 Python 运行时源码同样记录了从 2 到 3 的兼容与演进过程,集中在 pulsar-functions/instance/src/main/python 目录:

入口脚本显式声明 python3

pulsar-functions/instance/src/main/python/python_instance_main.py 的 shebang 为:

#!/usr/bin/env python3

这是运行时"强制 Python 3"最直接的证据——无论 PATH 中的python指向哪个版本,函数实例进程都会用python3解释器启动。

运行时内的 Py2/Py3 兼容分支

pulsar-functions/instance/src/main/python/python_instance.py 定义了版本判定常量,并在多处使用条件分支:

PY3 = sys.version_info[0] >= 3

例如base64ify()中根据PY3决定字符串是否需要先encode('utf8')再 base64(python_instance.py);模块导入处也保留了try: import Queue as queue / except: import queue的双版本兼容写法(python_instance.py)。

类似的兼容代码还出现在:

  • function_stats.py:int(...) if sys.version_info.major >= 3 else long(...),处理 Python 2 独有的long类型;
  • python_instance.py:指标与状态上报时的int/long转换分支;
  • python_instance.py:自定义 Schema 反射时inspect.signature与inspect.getargspec的双版本回退(# for compatibility with python 2注释)。

从源码结构看,这些分支是迁移过渡期留下的"兼容层":功能上以 Python 3 为主路径,Python 2 仅保留最低限度的可用性——与 PIP-56"python27 测试覆盖缩减、年底停止制品发布"的路线完全一致。

依赖锁定与 stubs 再生成机制

Python 运行时依赖的 Protobuf/gRPC stubs 由仓库内的脚本生成,与镜像中固定的grpcio/protobuf版本严格对应。相关说明见 pulsar-functions/instance/src/main/python/README.md:

  • 若升级镜像中的grpcio/protobuf,必须同步更新 src/update_python_protobuf_stubs.sh 中的PYTHON_GRPCIO_VERSION(当前默认1.78.0,见该脚本第 23 行),并重新生成 stubs;
  • 在项目根目录执行src/update_python_protobuf_stubs.sh(或容器化的src/update_python_protobuf_stubs_with_docker.sh)即可重新生成Function_pb2.py、InstanceCommunication_pb2.py、InstanceCommunication_pb2_grpc.py等文件;
  • 脚本会创建临时 venv 以避免污染全局环境,并使用grpc_tools.protoc从 pulsar-functions/proto/src/main/proto 下的.proto文件生成代码,同时删除生成文件中的严格版本校验代码,以允许跨版本运行。

迁移的验证路径:集成测试与运行时测试

PIP-56 的第二项主张是"集成测试迁移到 python37"。当前仓库中与 Python Functions 相关的测试可从两个层面验证 Python 3 运行时:

  • 运行时单元测试:pulsar-function-go与 Python 运行时各有独立测试(如 pulsar-functions/instance 下的 Python 脚本,以及pf/目录中*_test.go对应的 Go 运行时测试),它们共同覆盖函数实例的启动、消息处理与指标上报;
  • 集成测试链路:tests/integration目录下的 Java 集成测试(如 tests/integration/src 中的 Pulsar Functions 相关用例)负责在真实集群中验证函数端到端行为,默认即运行在带 Python 3 的官方镜像之上。

对于希望本地复现"镜像内 Python 3 可用性"的读者,可执行:

# 构建镜像(在仓库根目录,需先完成完整构建以产出 tarball) ./gradlew -Pdocker -PskipTests -DdockerPull=true docker:docker # 或直接进入镜像验证运行时 docker run --rm -it apachepulsar/pulsar:latest python3 --version docker run --rm -it apachepulsar/pulsar:latest pip3 --version

提示:PULSAR_CLIENT_PYTHON_VERSION与PYTHON_VERSION(仅 Wolfi 镜像)均为可覆盖的构建参数,自定义镜像时可利用--build-arg调整客户端版本。

小结:PIP-56 的落地与演进

PIP-56 以"Python 2.7 停止维护"为背景,提出了默认运行时从 python27 到 python37 的三步迁移方案。回看当前仓库,该提案的目标已全面达成并继续演进:

  • 官方镜像(Alpine 与 Wolfi 两条链路)只安装 Python 3,python3/pip3成为默认命令;
  • Functions Python 运行时入口使用python3shebang,源码中的 Py2 兼容分支仅作为历史兼容层保留;
  • grpcio/protobuf 与生成的 stubs 通过PYTHON_GRPCIO_VERSION脚本化联动,保证运行时依赖与生成代码的版本一致性;
  • Python 版本进一步演进(Wolfi 镜像默认 3.12),客户端版本持续跟随社区发布节奏。

对于依旧依赖 Python 2 的存量部署,唯一的合规路径是参考 docker/pulsar/Dockerfile 自行构建自定义镜像并回退依赖版本,同时关注发布说明中的兼容性公告——这正是 PIP-56 当年为社区规划好的过渡方式。

  • 消息队列
  • 流处理
  • 后端
  • 微服务
  • 消息路由

【免费下载链接】pulsar

Apache Pulsar - distributed pub-sub messaging system

项目地址:https://gitcode.com/gh_mirrors/pu/pulsar
点击查看免费下载
上一篇:终极API安全指南:保护你的API密钥与安全调用最佳实践
下一篇:codeforces-go 题解工程化实战:统计染色格子数(Count Total Number of Colored Cells)的 O(1) 递推公式 f(n)=1+2n(n-1)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询