Google Cloud Dataflow中‘读取字体数据失败’异常原因排查
在Google Cloud Dataflow中使用Java.awt.Font时遇到"Problem reading font data"异常的解决方法
问题重现
Error message from worker: java.lang.Exception:Problem reading font data.
仅在使用DataflowRunner运行Java应用时触发该异常,本地用DirectRunner运行完全正常,问题代码段如下:
Font.createFonts(stream) .first() .deriveFont(fontSize * FONT_SIZE_MULTIPLIER)
问题原因
Dataflow Worker默认使用的基础Docker镜像(如gcr.io/dataflow-templates-base/java11-template-launcher-base)未预装图形渲染依赖和系统字体库,而java.awt.Font的相关操作依赖这些组件;本地开发环境通常自带完整的图形和字体支持,因此不会触发异常。
解决方案
方案1:打包自定义字体到应用Jar(推荐)
将业务需要的字体文件(.ttf/.otf格式)放到项目resources目录下,直接从类路径加载,不依赖系统字体:
try (InputStream fontStream = getClass().getResourceAsStream("/fonts/your-font-file.ttf")) { // 改用createFont确保单字体文件读取,避免集合空指针 Font baseFont = Font.createFont(Font.TRUETYPE_FONT, fontStream); Font targetFont = baseFont.deriveFont(fontSize * FONT_SIZE_MULTIPLIER); } catch (IOException | FontFormatException e) { // 异常处理逻辑 }
注意:如果仍用createFonts,需额外判断返回集合是否为空,避免first()抛出NoSuchElementException。
方案2:自定义Dataflow Worker镜像
若必须依赖系统字体,可构建包含字体依赖的自定义镜像:
- 创建
Dockerfile:
# 以Java11基础镜像为例,根据你的Dataflow版本替换对应镜像 FROM gcr.io/dataflow-templates-base/java11-template-launcher-base:latest # 安装字体和基础图形依赖 RUN apt-get update && apt-get install -y --no-install-recommends \ fonts-dejavu-core \ libfontconfig1 \ && rm -rf /var/lib/apt/lists/*
- 构建并推送镜像到GCR:
docker build -t gcr.io/your-project-id/custom-dataflow-worker:v1 . docker push gcr.io/your-project-id/custom-dataflow-worker:v1
- 提交Dataflow作业时指定自定义镜像:
gcloud dataflow jobs run your-job-name \ --gcs-location gs://your-bucket/path/to/your-template \ --worker-image=gcr.io/your-project-id/custom-dataflow-worker:v1
方案3:禁用AWT图形依赖(仅适用于非渲染场景)
如果仅需解析字体文件、不需要实际渲染,可添加JVM参数禁用图形依赖:
gcloud dataflow jobs run your-job-name \ --gcs-location gs://your-bucket/path/to/your-template \ --worker-jvm-flags="-Djava.awt.headless=true -Dsun.java2d.font.disable=true"
内容的提问来源于stack exchange,提问作者Ahmed Abdelhak
相关产品推荐
相关产品推荐

