新闻详情

新闻详情

首页 / 资讯中心 / 详情

Apache Pulsar Functions 打包实战指南:Java、Python、Go 三种语言的完整打包与部署流程

发布时间:2026/11/15 13:43:56来源:尧图网络
Apache Pulsar Functions 打包实战指南:Java、Python、Go 三种语言的完整打包与部署流程
Apache Pulsar Functions 打包实战指南Java、Python、Go 三种语言的完整打包与部署流程【免费下载链接】pulsarApache Pulsar - distributed pub-sub messaging system项目地址: https://gitcode.com/gh_mirrors/pulsar28/pulsar本文围绕 Apache Pulsar 中 Pulsar Functions 的打包方法展开系统讲解 JavaMaven 装配式 JAR、Python单文件 / ZIP / PIP 三种格式与 GoSDK 反射校验三种语言的函数打包流程以及localrun本地运行与create集群模式下pulsar-admin functions命令的完整用法。读完本文你将能够从零编写、打包、部署一个可运行的 Pulsar Function并理解函数运行时ProcessRuntime如何加载你打出的制品。Pulsar Functions 是 Apache Pulsar 内置的轻量级流处理框架允许用户用 Java、Python 或 Go 编写处理函数消费一个或多个输入 topic 中的消息并把处理结果写入输出 topic。无论函数最终运行在本地进程、函数工作节点Function Worker还是 Kubernetes Pod 中第一步都是把函数代码打包成运行时能够加载的制品对 Java 函数来说通常是包含全部依赖的 fat JAR对 Python 函数来说是单.py文件、ZIP 包或whl包对 Go 函数来说则是一个独立的可执行二进制。本文内容以官方文档 functions-package.md 为核心骨架并结合本仓库源码给出底层实现依据。前置条件先启动一个可用的 Pulsar 实例在运行任何 Pulsar Function 之前需要先启动 Pulsar 服务。官方提供两种常用方式在 Docker 中运行 Standalone 模式的 Pulsar参见 getting-started-docker.md在 Kubernetes 中通过 Helm 部署 Pulsar参见 getting-started-helm.md。启动后可以使用docker ps命令确认 Docker 镜像是否正常启动docker ps另外运行本文后续命令前请确认pulsar-admin命令可用位于 Pulsar 安装目录的./bin/pulsar-admin函数的完整命令行参数说明可参考 reference-pulsar-admin.md#functions 或直接执行./bin/pulsar-admin functions打包 Java 函数Maven fat JAR 全流程1. 创建 Maven 项目与 POM 配置新建一个 Maven 项目并创建pom.xml。下面的示例中mainClass的值需要替换为你自己的包名这里是org.example.test.ExclamationFunction?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdjava-function/groupId artifactIdjava-function/artifactId version1.0-SNAPSHOT/version dependencies dependency groupIdorg.apache.pulsar/groupId artifactIdpulsar-functions-api/artifactId version2.6.0/version /dependency /dependencies build plugins plugin artifactIdmaven-assembly-plugin/artifactId configuration appendAssemblyIdfalse/appendAssemblyId descriptorRefs descriptorRefjar-with-dependencies/descriptorRef /descriptorRefs archive manifest mainClassorg.example.test.ExclamationFunction/mainClass /manifest /archive /configuration executions execution idmake-assembly/id phasepackage/phase goals goalassembly/goal /goals /execution /executions /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId configuration source8/source target8/target /configuration /plugin /plugins /build /project关键配置说明pulsar-functions-api依赖提供 Pulsar Function 编程接口对应本仓库的 pulsar-functions/api-java 模块其中包含org.apache.pulsar.functions.api.Function与Context等核心接口。maven-assembly-plugin的jar-with-dependencies将项目自身的类与所有第三方依赖合并打包成一个可独立运行的 fat JAR这是 Pulsar Functions 运行时能够直接加载的前提——运行时通过 JAR 的Main-Class/类路径信息定位用户函数类。appendAssemblyIdfalse使最终产物的文件名不带jar-with-dependencies后缀例如直接生成java-function-1.0-SNAPSHOT.jar。maven-compiler-plugin指定source/target为 8保证字节码兼容性Pulsar Functions 运行环境通常基于 Java 8 构建。2. 编写 Java 函数两种 Function 接口Java 函数可以使用两种函数接口编写Java 8 原生函数式接口java.util.function.FunctionPulsar 自带的函数接口org.apache.pulsar.functions.api.Function使用 Java 8 接口的示例package org.example.test; import java.util.function.Function; public class ExclamationFunction implements FunctionString, String { Override public String apply(String s) { return This is my function!; } }两种接口最核心的区别在于org.apache.pulsar.functions.api.Function接口额外提供了Context上下文。当你需要在函数内与 Pulsar 交互时可以通过context获取 Pulsar Functions 提供的丰富信息与能力例如计数器counter、日志、用户配置、发布消息到其他 topic 等。使用 Pulsar 接口并携带Context的示例一个经典单词计数函数package org.example.functions; import org.apache.pulsar.functions.api.Context; import org.apache.pulsar.functions.api.Function; import java.util.Arrays; public class WordCountFunction implements FunctionString, Void { // This function is invoked every time a message is published to the input topic Override public Void process(String input, Context context) throws Exception { Arrays.asList(input.split( )).forEach(word - { String counterKey word.toLowerCase(); context.incrCounter(counterKey, 1); }); return null; } }该示例中context.incrCounter(counterKey, 1)会对每个单词的 key 累加计数计数状态由 Pulsar Functions 的状态存储State Store持久化这正是 Pulsar 函数接口相对 Java 8 原生接口多出来的能力。仓库中提供了丰富的 Java 函数示例可供参考例如 pulsar-functions/java-examples 目录下的 50 个示例类。3. 执行打包在项目根目录执行mvn package打包完成后项目目录下会自动生成target目录。进入target目录检查是否生成了形如java-function-1.0-SNAPSHOT.jar的 JAR 包该包就是后续要提交给运行时的制品。4. 运行 Java 函数1将打包好的 JAR 复制到 Pulsar 容器内docker exec -it [CONTAINER ID] /bin/bash docker cp path of java-function-1.0-SNAPSHOT.jar CONTAINER ID:/pulsar2使用pulsar-admin functions localrun以本地模式运行函数./bin/pulsar-admin functions localrun \ --classname org.example.test.ExclamationFunction \ --jar java-function-1.0-SNAPSHOT.jar \ --inputs persistent://public/default/my-topic-1 \ --output persistent://public/default/test-1 \ --tenant public \ --namespace default \ --name JavaFunction参数含义--classname函数类的全限定名--jarfat JAR 的路径--inputs输入 topic支持多个逗号分隔--output输出 topic--tenant/--namespace函数所属租户与命名空间默认分别为public与default--name函数的唯一名称。看到如下日志即表示 Java 函数启动成功... 07:55:03.724 [main] INFO org.apache.pulsar.functions.runtime.ProcessRuntime - Started process successfully ...这条日志来自org.apache.pulsar.functions.runtime.ProcessRuntime它表明函数被以独立进程Process Runtime的方式拉起并成功启动。Pulsar Functions 支持多种运行时实现localrun默认使用进程运行时在本地直接拉起函数进程无需额外的容器环境。打包 Python 函数三种格式详解Python Function 支持以下三种打包格式单个 Python 文件one python fileZIP 压缩包ZIP filePIP 包whl 文件仅支持 Kubernetes 运行时注意窗口函数Window Function目前不支持 Python 与 Go仅支持 JavaJava 窗口函数的打包方式与普通 Java 函数完全一致。格式一单个 Python 文件1. 编写 Python 函数。需要继承pulsar.Function类并实现process()方法from pulsar import Function // import the Function module from Pulsar # The classic ExclamationFunction that appends an exclamation at the end # of the input class ExclamationFunction(Function): def __init__(self): pass def process(self, input, context): return input !process()方法主要有两个参数input函数的输入消息contextPulsar Function 暴露的上下文接口基于该 context 对象可以在 Python 函数中获取各种属性消息元数据、用户配置、计数器等。本仓库 pulsar-functions/python-examples/exclamation_function.py 中保存着与该示例完全一致的实现此外该目录下还有wordcount_function.py、logging_function.py、publish_function.py等 11 个可直接参考的官方示例。2. 安装 Python 客户端。Python 函数的实现依赖 Python 客户端库因此在部署前需要安装对应版本的客户端pip install pulsar-client2.6.03. 运行 Python 函数。1将 Python 函数文件复制到 Pulsar 容器docker exec -it [CONTAINER ID] /bin/bash docker cp path of Python function file CONTAINER ID:/pulsar2使用--py参数运行./bin/pulsar-admin functions localrun \ --classname Python Function file name.Python Function class name \ --py path of Python Function file \ --inputs persistent://public/default/my-topic-1 \ --output persistent://public/default/test-1 \ --tenant public \ --namespace default \ --name PythonFunction注意此时--classname的写法是“文件名.类名”例如文件名为exclamation.py、类名为ExclamationFunction则应写为exclamation.ExclamationFunction。同样看到ProcessRuntime - Started process successfully日志即表示启动成功。格式二ZIP 文件1. 准备 ZIP 文件。假设 ZIP 名为func.zip解压后必须包含以下结构func/src func/requirements.txt func/depssrc存放函数源码requirements.txt声明 Python 依赖deps存放预打包的依赖如whl文件在函数启动时被安装/加载。仓库tests/docker-images下的python-examples目录提供了一份exclamation.zip官方示例其内部结构如下. ├── deps │ └── sh-1.12.14-py2.py3-none-any.whl └── src └── exclamation.py2. 运行 Python 函数。1将 ZIP 文件复制到 Pulsar 容器docker exec -it [CONTAINER ID] /bin/bash docker cp path of ZIP file CONTAINER ID:/pulsar2运行命令注意此时--classname只写模块名不写类名./bin/pulsar-admin functions localrun \ --classname exclamation \ --py path of ZIP file \ --inputs persistent://public/default/in-topic \ --output persistent://public/default/out-topic \ --tenant public \ --namespace default \ --name PythonFunction看到ProcessRuntime - Started process successfully日志即表示启动成功。格式三PIP仅 Kubernetes 运行时PIP 方式只在 Kubernetes 运行时下受支持。完整步骤如下1. 配置functions_worker.yml。在 Function Worker 配置文件的 Kubernetes Runtime 段中开启用户代码依赖安装#### Kubernetes Runtime #### installUserCodeDependencies: true该配置项同样存在于本仓库的 conf/functions_worker.yml 中注释中明确说明其作用是 The flag indicates to install user code dependencies. (applied to python package)。当 Python Function 检测到提交的制品是whl且installUserCodeDependencies被置为true时系统会使用pip install命令安装函数所需的全部依赖。2. 编写 Python 函数。除了 Pulsar 客户端外可以引入任意额外依赖from pulsar import Function import js2xml # The classic ExclamationFunction that appends an exclamation at the end # of the input class ExclamationFunction(Function): def __init__(self): pass def process(self, input, context): // add your logic return input !3. 生成whl文件。使用仓库自带的打包脚本$ cd $PULSAR_HOME/pulsar-functions/scripts/python $ chmod x generate.sh $ ./generate.sh path of your Python Function path of the whl output dir the version of whl # e.g: ./generate.sh /path/to/python /path/to/python/output 1.0.0输出会写入指定的输出目录-rw-r--r-- 1 root staff 1.8K 8 27 14:29 pulsarfunction-1.0.0-py2-none-any.whl -rw-r--r-- 1 root staff 1.4K 8 27 14:29 pulsarfunction-1.0.0.tar.gz -rw-r--r-- 1 root staff 0B 8 27 14:29 pulsarfunction.whl从源码看generate.sh 的实际逻辑是把path of your Python Function目录下的所有*.py复制到临时目录的pulsarfunction包中通过sed将 setup.py.template 中的VERSION占位符替换为第三个参数指定的版本号并把requirements.txt一并复制进去随后依次执行setup.py sdist与setup.py bdist_wheel生成tar.gz源码包与whlwheel 包最后在输出目录中touch一个空的pulsarfunction.whl作为 PIP 格式的标识文件。这也解释了为何需要提前在函数目录中准备好requirements.txt——它是 wheel 包install_requires元数据的来源。打包 Go 函数SDK 反射签名校验1. 编写 Go 函数Go 函数只能通过官方 SDK 实现函数接口以 SDK 形式暴露。使用前需要导入github.com/apache/pulsar/pulsar-function-go/pf包对应本仓库 pulsar-function-go/pf 目录import ( context fmt github.com/apache/pulsar/pulsar-function-go/pf ) func HandleRequest(ctx context.Context, input []byte) error { fmt.Println(string(input) !) return nil } func main() { pf.Start(HandleRequest) }可以使用pf.FromContext从 context 中取出函数上下文并访问函数元信息if fc, ok : pf.FromContext(ctx); ok { fmt.Printf(function ID is:%s, , fc.GetFuncID()) fmt.Printf(function version is:%s\n, fc.GetFuncVersion()) }从源码看pf.FromContext定义于 pulsar-function-go/pf/context.go#L192而pf.Start定义于 pulsar-function-go/pf/function.go#L168它负责启动函数实例并与 Function Worker 建立 gRPC 通信。编写 Go 函数时需要注意两个关键约束在main()中只需将函数名注册给Start()且Start()只接收一个函数名参数Go 函数基于传入的函数名使用Go 反射reflection校验参数列表与返回值列表是否合法。参数与返回值组合必须是下列 9 种形式之一func () func () error func (input) error func () (output, error) func (input) (output, error) func (context.Context) error func (context.Context, input) error func (context.Context) (output, error) func (context.Context, input) (output, error)这 9 种签名是 Go 函数运行时反射校验的完整白名单输入可选无或input必须的context.Context可放在最前返回值必须包含error输出output可选。2. 构建 Go 函数在函数目录下直接编译生成可执行二进制go build your Go Function filename.go3. 运行 Go 函数1将编译出的二进制复制到 Pulsar 容器docker exec -it [CONTAINER ID] /bin/bash docker cp your go function path CONTAINER ID:/pulsar2使用--go参数运行./bin/pulsar-admin functions localrun \ --go [your go function path] --inputs [input topics] \ --output [output topic] \ --tenant [default:public] \ --namespace [default:default] \ --name [custom unique go function name]看到如下日志即表示 Go 函数启动成功... 07:55:03.724 [main] INFO org.apache.pulsar.functions.runtime.ProcessRuntime - Started process successfully ...在集群模式下启动函数如果希望以集群模式cluster mode启动函数只需把前面所有命令中的localrun替换为create即可。例如./bin/pulsar-admin functions create \ --classname org.example.test.ExclamationFunction \ --jar java-function-1.0-SNAPSHOT.jar \ --inputs persistent://public/default/my-topic-1 \ --output persistent://public/default/test-1 \ --tenant public \ --namespace default \ --name JavaFunction与localrun不同的是create会把函数提交给 Function Worker 进行调度部署而不是在当前机器上拉起进程返回以下日志表示创建成功Created successfullylocalrun与create的主要区别总结模式命令运行位置适用场景本地模式localrun当前进程环境直接拉起函数进程本地调试、快速验证集群模式create提交至 Function Worker / Kubernetes 调度生产环境部署关于--classname、--jar、--py、--go、--inputs等参数的完整说明可运行./bin/pulsar-admin functions查看帮助或参阅 reference-pulsar-admin.md#functions。小结本文完整覆盖了 Pulsar Functions 三种语言的打包与部署路径Java 函数通过maven-assembly-plugin打出带全部依赖的 fat JARPython 函数可根据运行环境在单文件、ZIP携带src/deps/requirements.txt与 PIPinstallUserCodeDependencies: truegenerate.sh生成 wheel三种格式中选择Go 函数则编译为二进制后通过 SDK 注册并遵循 9 种反射签名白名单。无论哪种语言最终都通过pulsar-admin functions以localrun本地或create集群两种方式提交给 Pulsar Functions 运行时由ProcessRuntime完成进程拉起。掌握这套打包流程后你可以在此基础上进一步探索Context的高级用法计数器、状态存储、用户配置以及窗口函数仅 Java等更复杂的能力。【免费下载链接】pulsarApache Pulsar - distributed pub-sub messaging system项目地址: https://gitcode.com/gh_mirrors/pulsar28/pulsar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/15 4:54:16

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/15 2:04:12

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/14 10:11:15

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/14 17:14:38

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/14 16:35:50

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/15 4:06:36

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉