Java云原生开发初体验报告
Java云原生开发初体验报告
背景
前段时间在考虑做一款小工具,功能非常简单,调用多个HTTP接口,分析处理返回的数据,生成Excel文件即可。 为了尽量的让这个工具的实用性更高,我首先想到Java的云原生开发方案,直接构建为可执行文件,不需要使用的人再去安装jre运行环境,或者是带着庞大的jre文件发出。再者,我也想试试Java的云原生方案到底好不好用。
技术选型
因为一直在使用Spring开发业务,所以我这次直接使用了Spring Native
开发过程
注:均基于 macOS
开发环境安装
Spring官网的文章写的非常好,直接参考官文就可以了。Spring官方文档 我选择安装了sdk man,然后
1 | sdk install java 22.1.r11-nik |
剩下的就是直接用spring native创建一个项目就可以了,这个非常简单。
编译构建
如果你用了阿里云的maven仓库,请记得切换成apache的原库
macOS默认mvn命令指定的jdk版本可能不是你新安装的GraalVM(像我本地就有七八个不同的JDK版本),会出现一些编译错误,那么你需要创建
~/.mavenrc
文件
1 | // 路径记得自己改成正确的 |
报错集锦
报错1
1 | gu install native-image |
在高版本里面,这个native-image
好像不需要手动安装了(也有可能是我之前安装过)Install fails in 19.2.0 with gu · Issue #1665 · oracle/graal · GitHub 然后我直接运行了一下native-image
发现已经有了
报错2 反射错误
1 | com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.baofeidyz.XXXDTO` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) |
这个报错只有在GraalVM
下运行时才会出现,我最开始以为是因为我用了lombok
然后导致的编译问题,同时我也有注意到,Spring Native
本身是直接带了lombok
的,我觉得不太可能吧。 但是我还是尝试去掉了lombok
,当然并没有什么用。
然后我又开始在网上寻找一些蛛丝马迹,看看有没有其他人也遇到了类似的问题。但是Java Native问题的搜索真的是非常难找,因为这类问题有可能因为其他的原因也会出现,并且由于Spring Native使用人非常的少,你很难在Google的结果中找到真正的答案。我也尝试使用site:github.com
再去Google搜索,仍没有找到答案。 我甚至都想去提issue了 😂 GitHub - graalvm/native-build-tools: Native-image plugins for various build tools
我后来咨询了一位做过Spring Native开发的朋友,他告诉我,可能是因为反射导致的,需要增加配置。 我顺着这位朋友的思路,去看了一下反射配置的问题,正好在这篇文章中给出了一个示例
1 |
|
我顺着这个例子,修改了一下代码
1 |
|
确实解决了这个jackson
反序列化导致的错误,但我又遇到了新的错误。
报错3 缺少字符集
1 | java.nio.charset.UnsupportedCharsetException: CP1252 |
这个看起来像是poi在操作的时候,遇到了一个chartset
问题,spring有一个专门的仓库我在这个仓库里面找到了这个issue,我看到一个人也遇到了这个charset
的问题,但是他是mysql
的时候遇到的,他提到加了一个参数用于解决这个问题。 紧接着,我又找到了几个issue:
了解到说,需要在native-image
编译的时候,增加一个AddAllCharsets
参数 但是我是使用的spring native的maven插件,我的构建命令是mvn -Pnative
,我并没有直接使用native-image
,我不知道怎么增加这个参数才是对的。 此外,我还看了两份文档:
关于这个如何查看堆信息之类的:GraalVM Dashboard
关于
native-image
这个命令如何使用的:https://www.graalvm.org/uploads/quick-references/native-image-quick-reference-v2_A4.pdf 然后我又去查了一下Spring Native自己维护的一个hints项目:spring-native/spring-native-configuration/src/main/java at main · spring-projects-experimental/spring-native · GitHub 然后又去研究了一下Spring Native的脚本:spring-native/compileWithMaven.sh at main · spring-projects-experimental/spring-native · GitHub
终于,我知道如何在Spring Native中增加这个AddAllCharsets
参数了 😄
1 |
|
最佳实践就是加一个@NativeHint(options = "-H:+AddAllCharsets")
当然不可能这么顺利的,很快我又遇到了新的报错
错误4 POI的resource文件未加载
1 | org.apache.xmlbeans.SchemaTypeLoaderException: XML-BEANS compiled schema: Could not locate compiled schema resource org/apache/poi/schemas/ooxml/system/ooxml/index.xsb (org.apache.poi.schemas.ooxml.system.ooxml.index) - code 0 |
我猜测应该是因为资源没有引入导致的,所以我理解应该还是应该用spring native提供的hint去实现。我参考这个代码块 增加了一个@ResourceHint
1 |
|
报错5
1 | java.lang.ClassCastException: org.apache.xmlbeans.impl.values.XmlComplexContentImpl cannot be cast to org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook |
然后我在GraalVM的issue清单中找到了这个issue:Getting following error while generating excel file using native image. · Issue #1929 · oracle/graal · GitHub 基本上错误信息就是一致的。 我试了一下,不行。
我感觉POI和GraalVM配合坑有点多,我不打算一个一个找了,我尝试去找一些大而全的文章,于是,我找到了这篇文章:Graalvm使用采坑 - 行万里路才能回到内心深处,读万卷书才能看得清皓月繁星
可惜还是失败了,我感觉算了吧,POI和GraalVM的路还很长哦…
一些思考
对于这种POI组件的问题,处理起来确实很难。我查了GraalVM的ISSUE清单,5.0之前的POI确实是有一些问题,但与此同时GraalVM可能需要大量的构建参数去配置,然后Spring Native又在其中转了一次。也就是说,我需要知道这个问题不是POI导致的,然后去看native-image对应的解决方案(配置参数)是什么,然后再转成Spring Native的hints。如果我不能确定这个问题是不是POI导致的,我连提ISSUE给谁都不清楚,如果自己尝试去排查编译问题,这就会进入一个更深的坑。
我建议如果Spring Native example下找不到对应的例子之前,不要去趟这个浑水,整个开发过程非常阻塞,问题很难说真正的解决完。
Java云原生的路确实很难走,不管是GraalVM去适配组件,还是组件去适配GraalVM,整个适配时间会拉得很长很长。
GraalVM编译时间很长,我的项目并不大,4核8线程,16G内存,但是每次都需要大概3分钟左右,并且编译的时候,CPU使用率一直都很高。
后续
我后来用GO重写了整个程序,这是我第一次用GO,从0开始学,大概花了20个小时就写完了,并且我还用了协程并发,处理了一些线程安全的问题。相比之下,Spring Native至少花了我四倍的时间,并且没有做完。 GO编译速度非常快,我交叉编译linux或windows也才10s,CPU使用率也不高,相比之下,GO做这类小工具的云原生开发真的是非常好用。
所以我在怀疑,Java云原生是否真的有意义?希望十年后,能被打脸。
以上就是我Java云原生的初步体验报告,如果对你有一点点帮助,希望可以给我的文章点个赞和收藏。