Micronaut + GraalVM 是不是真的香

2,318 阅读2分钟

微服务规模大了以后,传统build 的docker image就显得非常臃肿,启动慢,体积大,非常不利于scale, 资源消耗也大。一般提高方法就是使用轻量级模块注入,用什么,加什么, 并且不用大的框架,像Spring, Spring boot就 非常不推荐在为服务使用。。。

经过上面优化,性能会好一些,但没啥惊人变化, 因为base image还是openjdk,依赖注入,反射,注解之类 还是会降低启动速度。

GraalVM(www.graalvm.org/)

GraalVM作为一款新型通用的虚拟机,不废话,单刀直入解决问题,启动快50倍,内存消耗少5倍。

graalvm-1.png

为啥它这么牛,因为它用AOT(ahead-of-time)编译,可以快速启动和低内存消耗。官方列的优点:

  • 高效
  • AOT 编译 (快速启动)
  • 多语言
  • 高级工具(调试,监控,profile等等)

后两项还没有特别感觉,因为公司后台主要用Java/Kotlin/Grrovy,没有多语言问题。高级工具这些,公司有统一的stack,也不准备用。

Micronaut(github.com/micronaut-p…

Micronaut是一款现代, 基于JVM的全栈Java框架,适用于模块化搭建,易于测试的JVM应用,支持Java, Kotlin和Groovy. 它提供了编译时的依赖注入和AOP处理能力,并最小化反射和动态代理的使用。它应用有着更快的启动速度和更低的内存占用。

Micronaut + GraalVM (POC)

  1. 用Micronaut template创建一个App

    • version: 2.3.3
    • language: Java 11
    • build: gradle
    • test: jUnit
    • feature: netty-server
  2. 创建一个简单的API, /hello

    @Controller("/hello")
    public class HelloController {
       @Get("/")
       public String index() {
           return "hello from Micronaut + GraalVM";
       }
    }
    
  3. 添加lib到build.gradle

    annotationProcessor("io.micronaut:micronaut-graal")
    compileOnly("org.graalvm.nativeimage:svm")
    
  4. 新建文件src/main/resources/META-INF/native-image/native-image.properties

    Args= -H:IncludeResources=logback.xml|application.yml \
          -H:Name=mn-graalvm \
          -H:Class=com.sz.App \
          --report-unsupported-elements-at-runtime
    
  5. Dockerfile

    # this image is only used in building, not for runtime
    FROM ghcr.io/graalvm/graalvm-ce:latest as graalvm
    
    # gu = graal updater
    RUN gu install native-image
    
    COPY . /home/app/mn-graalvm
    WORKDIR /home/app/mn-graalvm
    
    RUN native-image --no-server -cp build/libs/mn-graalvm-*-all.jar
    
    FROM frolvlad/alpine-glibc:alpine-3.12
    RUN apk update && apk add libstdc++
    
    EXPOSE 8080
    
    COPY --from=graalvm /home/app/mn-graalvm/mn-graalvm /app/mn-graalvm
    ENTRYPOINT ["/app/mn-graalvm"]
    
  6. Build

    • ./gradlew clean assemble
    • docker build . -t mn-graalvm

提示,这个过程比较消耗时间和资源,建议分配给docker 6~8GB内存,否则容易报错

结果

启动时间比较
  • GraalVM原生 (32 ms) graalvm-startup.png

  • 非原生(961 ms) graalvm-raw-startup.png

镜像大小
  • 原生 81MB, 非原生251MB
    graalvm-size.png
内存使用
  • 原生 (7.64 MB) graalvm-mem.png

  • 非原生 (47.27 MB) graalvm-raw-mem.png

比较总结
原生非原生
启动时间32 ms961 ms
镜像大小81 MB251MB
内存使用7 MB47MB

通过比较一个最简单的web app来看,GraalVM效果性能还是不错,启动时间和内存使用这两项还是很吸引人的。下一步用大项目,可以 对性能进一步的比较和分析。

源码: github.com/shubozhang/…