精华内容
下载资源
问答
  • graalvm 使用
    千次阅读
    2021-08-02 11:10:27

    翻译自https://medium.com/graalvm/graalvm-at-facebook-af09338ac519

    Facebook正在使用GraalVM来加速其Spark的工作负载,并减少内存和CPU的使用。请继续阅读,了解它们的迁移故事、性能改进结果和未来计划。

    image.png

    Facebook背后的技术

    拥有28亿月活跃用户的Facebook是世界上访问量最大的平台之一。为了保证在这种负载下的可靠性和高性能,工程团队采用了多种技术,包括Java、JavaScript、Flow Hack、PHP、Python、c++等。

    Facebook在一些关键领域使用了Java,如大数据(Spark、Presto等)、后端服务和移动设备。在迁移到GraalVM之前,该团队在Java 8和Java 11上使用了Oracle JDK和OpenJDK。

    在这种规模下,任何性能改进都会带来显著的价值——它们改善了用户体验并降低了基础设施成本。这就是为什么工程团队一直在寻找改进应用程序性能的方法,并决定评估GraalVM,以确定它是否是一个更快的Java运行时。

    为什么是GraalVM

    • 由于性能是一个主要考虑因素,Facebook团队决定评估GraalVM作为他们的Java运行环境,看看它是否会提高他们的Java应用程序的性能。GraalVM提供了高级优化,比如部分转义分析和内联启发式。多亏了这一点,许多Java/JVM应用程序只要切换到GraalVM,就能立即获得性能提升。Facebook团队还观察到,与C2相比,GraalVM在SpecJVM2008和DaCapo等基准测试中显示出了显著的年进步。
    • 此外,GraalVM编译器是以模块化和可扩展的方式使用Java从头开始编写的。这使得维护变得很容易,同时还增加了增量改进。这对Facebook来说很重要,因为该团队正在考虑对GraalVM进行长期投资。
    • 社区。GraalVM项目拥有一个充满活力的开源社区,许多组织和个人都为该项目做出了贡献,并形成了它的路线图。在社区中也很容易找到帮助和支持。

    在GraalVM上运行Java和Spark

    Facebook团队使用了GraalVM社区作为OpenJDK的替代品。在这个场景中,迁移到GraalVM非常简单——只需要切换运行环境,不需要更改应用程序代码。这种转换使得应用程序运行得更快,这得益于GraalVM的高级性能优化,无需任何手动调优。

    Apache Spark是一个统一的大数据处理分析引擎,内置流、SQL、机器学习和图形处理模块。它处理数据的速度非常快,但许多团队正在寻找进一步优化其性能的方法。最简单的方法之一是在GraalVM上运行Spark工作负载。多亏了一组特定的编译器优化(我们稍后将详细讨论),GraalVM可以显著加快Spark的工作负载。Renaissance基准测试套件的Apache Spark基准测试显示,社区的平均加速速度为1.1倍,企业的平均加速速度为1.42倍,有些基准测试的速度高达4.84倍。

    image.png

    对于Facebook来说,Spark是其数据仓库中最大的SQL查询引擎,运行在聚合计算存储集群上。由于数据量巨大,效率和成本的降低是当务之急。

    他们从2020年初开始进行评估。由于最初的基准测试显示了良好的结果,团队将gralvm推向了生产,并一直监控其性能和可靠性。

    image.png![image.png](https://img-blog.csdnimg.cn/img_convert/a2eb859a2fe03b6653189e15e12f5c04.png#align=left&display=inline&height=381&margin=[object Object]&name=image.png&originHeight=381&originWidth=683&size=39756&status=done&style=none&width=683)

    在性能方面,他们观察到CPU使用减少了约10%,而且自推出以来,CPU的减少一直保持一致。

    GraalVM如何加速Spark工作负载

    对Spark性能提升贡献最大的一些优化是:

    • 多态内联。只有当编译器能够确定方法调用的目标方法时,传统内联才能工作。GraalVM通过收集额外的分析信息(允许也内联抽象方法),使内联超越了这一点。
    • 部分逸出分析。部分转义分析的思想是通过在对象没有转义的分支中执行标量替换来删除不必要的对象分配,并确保对象存在于必须转义的分支中的堆中。这既减少了应用程序的内存占用,又减少了GC引起的CPU负载。这种优化在Spark这样的数据密集型应用程序中更加重要。特别是,根据Facebook的观察,GraalVM在java/lang/Double.valueOf等方法中减少了5倍的CPU消耗。
    • GraalVM中的高级推测性优化通过利用动态运行时反馈产生更快的机器码。通过推测程序的某些部分不会在程序执行期间运行,GraalVM编译器能够专门化代码并使其更高效。对于Spark,通过消除分支(如长if-then-else链)、简化控制流、减少循环体中的动态检查数量以及建立别名约束,这种优化工作得特别好,从而实现进一步的优化。

    根据评估结果,Facebook团队将大部分cpu密集型的大数据服务迁移到了GraalVM。他们还观察到,在切换到GraalVM后,Presto的>5%的CPU和GC暂停时间提高了。接下来,该团队计划将GraalVM推到其他内存绑定服务,以从escape分析优化中获益。该团队还计划为项目和社区做出贡献。

    他们还在探索使用其他gralvm特性的机会,如Native Image和Truffle Framework。

    结论

    多亏了高级编译器优化,GraalVM可以显著加快许多Java和Scala工作负载。特别是,通过将GraalVM转换为JDK发行版,Spark的工作负载有望提高10%-42%。

    有趣的是,另一个流行的社交媒体平台Twitter的工程师也分享了类似的旅程和观察结果。在将Scala的工作负载转移到GraalVM之后,他们观察到显著的性能改进,例如,多亏了GraalVM编译器,P99延迟降低了19.9%。对于像Twitter或Facebook这样的平台,这种性能改进会随着平台规模的扩大而进一步扩大。

    要开始在您的应用程序中使用GraalVM,请访问graalvm.org/docs/getting-started/。

    更多相关内容
  • 节点JVM 该工具以允许您访问正版NodeJS实例的方式启动GraalVM。 是OpenJDK的变体,具有快速,现代JavaScript引擎,能够运行所有NodeJS...为什么要使用Java中的NPM模块? 可以访问独特JavaScript模块,如示例中所示的DAT
  • 使用GraalVM在Java项目中运行JavaScript 使用GraalVM进行Java和JavaScript代码互操作性的示例项目有关更多信息,如何运行的说明和详细说明,请访问
  • 使用GraalVM EE加速Apache Spark大数据流程介绍在本教程中,我们将使用GraalVM EE加速大数据处理。 正在使用以下软件。 装置GraalVMHadoop设置单节点Hadoop集群。 我们将不涉及创建apache Hadoop / Spark cluser的...
  • jdk11环境下使用graal vm 搭建native-image环境

    native-image的构建

    第一步,安装graalvm

    下载graalvm,可以直接去官网下载

    https://www.graalvm.org/downloads/

    github地址

    https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.1.0

    这里以jdk11为例

    在这里插入图片描述

    https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.1.0/graalvm-ce-java11-windows-amd64-22.1.0.zip

    native-image的jar

    https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.1.0/native-image-installable-svm-java11-windows-amd64-22.1.0.jar

    第二步,install native-image

    首先配置环境变量

    在这里插入图片描述

    注意:如果之前安装过jdk,为了防止不必要的麻烦,直接将标记的变量放在第一位

    在这里插入图片描述

    使用命令查看是否安装graal vm成功

    java -version
    

    在这里插入图片描述
    安装成功后,接下来安装native-image

    gu install -L native-image-installable-svm-java11-windows-amd64-22.0.0.2.jar
    

    可以使用命令查看,已经安装的功能

    gu list
    

    在这里插入图片描述

    第三步,配置环境变量

    在这里插入图片描述

    因为native-image直接生成了二进制文件,以加快执行速度。所以这里需要导入C库

    一开始如果没有装过visual studio,这里需要装一下,选择C++和组件
    在这里插入图片描述
    在这里插入图片描述

    接下来分别配置INCLUDE和LIB,Microsoft Visual Studio的位置是自己安装的位置,其他的除去版本号之外几乎一致

    INCLUDE的参数

    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\include
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared
    

    LIB参数

    C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64
    C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64
    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\lib\x64 
    

    最后path新增

    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
    

    第四步,测试

    public class Hello {
        public static void main(String[] args) {
            System.out.println("Hello native image");
        }
    }
    

    在这里插入图片描述
    到这里就是大功告成了!

    展开全文
  • 我还将向您展示如何使用 GraalVM 准备 Spring Boot 应用程序的本机映像。然后我们将使用 Skaffold 和 Jib Maven 插件在 Kubernetes 上运行它。 在 Knative 上,您可以运行任何类型的应用程序——不仅仅是一个函数。...

    在本文中,您将学习如何在 Knative 上运行相互通信的 Spring Boot 微服务 。我还将向您展示如何使用 GraalVM 准备 Spring Boot 应用程序的本机映像。然后我们将使用 Skaffold 和 Jib Maven 插件在 Kubernetes 上运行它。

    在 Knative 上,您可以运行任何类型的应用程序——不仅仅是一个函数。在这篇文章中,当我写“微服务”时,其实我在思考的是服务到服务的通信。

    源代码

    如果您想自己尝试一下,可以随时查看我的源代码。为此,您需要克隆我的 GitHub 存储库 。

    作为本文中的微服务示例,我使用了两个应用程序callme-service和caller-service. 它们都公开了一个端点,该端点打印了应用程序 pod 的名称。caller-service应用程序还调用应用程序公开的端点callme-service。

    在 Kubernetes 上,这两个应用程序都将部署为多个修订版的 Knative 服务。我们还将使用 Knative 路由在这些修订中分配流量。下面可见的图片说明了我们示例系统的 架构 

    1.准备Spring Boot微服务

    我们有两个简单的 Spring Boot 应用程序,它们公开一个 REST 端点、健康检查和运行内存 H2 数据库。我们使用 Hibernate 和 Lombok。因此,我们需要在 Maven 中包含以下依赖项列表pom.xml。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.16</version>
    </dependency>

    每次我们调用ping端点时,它都会创建一个事件并将其存储在 H2 数据库中。REST 端点返回 Kubernetes 内的 pod 和命名空间的名称以及事件的 id。该方法在我们对集群的手动测试中很有用。

    @RestController
    @RequestMapping(<font>"/callme"</font><font>)
    <b>public</b> <b>class</b> CallmeController {
    
        @Value(</font><font>"${spring.application.name}"</font><font>)
        <b>private</b> String appName;
        @Value(</font><font>"${POD_NAME}"</font><font>)
        <b>private</b> String podName;
        @Value(</font><font>"${POD_NAMESPACE}"</font><font>)
        <b>private</b> String podNamespace;
        @Autowired
        <b>private</b> CallmeRepository repository;
    
        @GetMapping(</font><font>"/ping"</font><font>)
        <b>public</b> String ping() {
            Callme c = repository.save(<b>new</b> Callme(<b>new</b> Date(), podName));
            <b>return</b> appName + </font><font>"(id="</font><font> + c.getId() + </font><font>"): "</font><font> + podName + </font><font>" in "</font><font> + podNamespace;
        }
    
    }
    </font>

    这是我们的模型类 - Callme。应用程序中的模型类caller-service非常相似。

    @Entity
    @Getter
    @Setter
    @NoArgsConstructor
    @RequiredArgsConstructor
    <b>public</b> <b>class</b> Callme {
    
        @Id
        @GeneratedValue
        <b>private</b> Integer id;
        @Temporal(TemporalType.TIMESTAMP)
        @NonNull
        <b>private</b> Date addDate;
        @NonNull
        <b>private</b> String podName;
    
    }

    另外,让我们看一下ping. CallerController稍后我们将在讨论通信和跟踪时对其进行修改。现在,重要的是要了解此方法还调用 ping 暴露的方法callme-service并返回整个响应。

    @GetMapping(<font>"/ping"</font><font>)
    <b>public</b> String ping() {
        Caller c = repository.save(<b>new</b> Caller(<b>new</b> Date(), podName));
        String callme = callme();
        <b>return</b> appName + </font><font>"(id="</font><font> + c.getId() + </font><font>"): "</font><font> + podName + </font><font>" in "</font><font> + podNamespace
                + </font><font>" is calling "</font><font> + callme;
    }
    </font>

    2. 使用 GraalVM 准备 Spring Boot 原生镜像

    Spring Native 支持使用 GraalVM 本机编译器将 Spring 应用程序编译为本机可执行文件。有关此项目的更多详细信息,您可以参考其文档。这是我们应用程序的主要类。

    @SpringBootApplication
    <b>public</b> <b>class</b> CallmeApplication {
    
       <b>public</b> <b>static</b> <b>void</b> main(String args) {
          SpringApplication.run(CallmeApplication.<b>class</b>, args);
       }
    
    }

    Hibernate 在运行时做了很多动态的事情。因此,我们需要让 Hibernate 在构建时增强应用程序中的实体。我们需要将以下 Maven 插件添加到我们的构建中。

    <plugin>
       <groupId>org.hibernate.orm.tooling</groupId>
       <artifactId>hibernate-enhance-maven-plugin</artifactId>
       <version>${hibernate.version}</version>
       <executions>
          <execution>
             <configuration>
                <failOnError><b>true</b></failOnError>
                <enableLazyInitialization><b>true</b></enableLazyInitialization>
                <enableDirtyTracking><b>true</b></enableDirtyTracking>
                <enableExtendedEnhancement>false</enableExtendedEnhancement>
             </configuration>
             <goals>
                <goal>enhance</goal>
             </goals>
          </execution>
       </executions>
    </plugin>

    在本文中,我使用的是 Spring Native 的最新版本——0.9.0。由于 Spring Native 正在积极开发中,后续版本之间会有较大的变化。如果您将其与其他基于早期版本的文章进行比较,我们不必禁用proxyBeansMethods、排除SpringDataWebAutoConfiguration、添加spring-context-indexer到依赖项或创建hibernate.properties。凉爽的!我也可以使用 Buildpacks 来构建原生镜像。

    所以,现在我们只需要添加以下依赖项。

    <dependency>
       <groupId>org.springframework.experimental</groupId>
       <artifactId>spring-native</artifactId>
       <version>0.9.0</version>
    </dependency>

    Spring AOT 插件执行提高本机图像兼容性和占用空间所需的提前转换。

    <plugin>
        <groupId>org.springframework.experimental</groupId>
        <artifactId>spring-aot-maven-plugin</artifactId>
        <version>${spring.native.version}</version>
        <executions>
            <execution>
                <id>test-generate</id>
                <goals>
                    <goal>test-generate</goal>
                </goals>
            </execution>
            <execution>
                <id>generate</id>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    3. 使用 Buildpacks 在 Knative 上运行原生镜像

    使用 Builpacks 创建原生镜像是我们的主要选择。虽然它需要一个 Docker 守护进程,但它在每个操作系统上都能正常工作。但是,我们需要使用最新的稳定版 Spring Boot。在这种情况下,它是2.4.3。您也可以在 Maven pom.xml 中使用spring-boot-maven-plugin. 由于我们需要在 Kubernetes 上一步构建和部署应用程序,因此我更喜欢在 Skaffold 中进行配置。我们paketobuildpacks/builder:tiny用作构建器图像。还需要使用BP_BOOT_NATIVE_IMAGE环境变量启用本机构建选项。

    apiVersion: skaffold/v2beta11
    kind: Config
    metadata:
      name: callme-service
    build:
      artifacts:
      - image: piomin/callme-service
        buildpacks:
          builder: paketobuildpacks/builder:tiny
          env:
            - BP_BOOT_NATIVE_IMAGE=<b>true</b>
    deploy:
      kubectl:
        manifests:
          - k8s/ksvc.yaml

    Skaffold 配置是指我们的 KnativeService清单。这是非常不典型的,因为我们需要将 pod 和命名空间名称注入到容器中。我们还允许每个 pod 最多有 10 个并发请求。如果超过,Knative 会扩大一些正在运行的实例。

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: callme-service
    spec:
      template:
        spec:
          containerConcurrency: 10
          containers:
          - name: callme
            image: piomin/callme-service
            ports:
              - containerPort: 8080
            env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: POD_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace

    默认情况下,Knative 不允许使用 KubernetesfieldRef功能。为了启用它,我们需要更新命名空间knative-features ConfigMap中的knative-serving。所需的属性名称是kubernetes.podspec-fieldref。

    kind: ConfigMap
    apiVersion: v1
    metadata:
      annotations:
      namespace: knative-serving
      labels:
        serving.knative.dev/release: v0.16.0
    data:
      kubernetes.podspec-fieldref: enabled

    最后,我们可以使用以下命令在 Knative 上构建和部署 Spring Boot 微服务。

    $ skaffold run

    4. 使用 Jib 在 Knative 上运行原生镜像

    与我之前关于 Knative 的文章一样,我们将使用 Skaffold 和 Jib 在 Kubernetes 上构建和运行我们的应用程序。幸运的是,Jib Maven Plugin 已经引入了对 GraalVM “native images”的支持。Jib GraalVM Native Image Extension 希望 能够完成生成“原生图像”( 目标)native-image-maven-plugin 的繁重工作 。native-image:native-image然后扩展只是简单地将二进制文件复制到容器映像中并将其设置为可执行文件。

    当然,与 Java 字节码不同,本机映像不可移植,而是特定于平台的。Native Image Maven Plugin 不支持交叉编译,因此 native-image 应该构建在与运行时架构相同的操作系统上。由于我在 Ubuntu 20.10 上构建了我的应用程序的 GraalVM 映像,因此我应该使用相同的基础 Docker 映像来运行容器化微服务。在这种情况下,我选择了镜像ubuntu:20.10,如下所示。

    <plugin>
       <groupId>com.google.cloud.tools</groupId>
       <artifactId>jib-maven-plugin</artifactId>
       <version>2.8.0</version>
       <dependencies>
          <dependency>
             <groupId>com.google.cloud.tools</groupId>
             <artifactId>jib-native-image-extension-maven</artifactId>
             <version>0.1.0</version>
          </dependency>
       </dependencies>
       <configuration>
          <from>
             <image>ubuntu:20.10</image>
          </from>
          <pluginExtensions>
             <pluginExtension>
                <implementation>com.google.cloud.tools.jib.maven.extension.nativeimage.JibNativeImageExtension</implementation>
             </pluginExtension>
          </pluginExtensions>
       </configuration>
    </plugin>

    如果你使用 Jib Maven 插件,你首先需要构建一个原生镜像。为了构建应用程序的本机映像,我们还需要包含一个native-image-maven-plugin. 你需要使用 GraalVM JDK 构建我们的应用程序。

    <plugin>
       <groupId>org.graalvm.nativeimage</groupId>
       <artifactId>native-image-maven-plugin</artifactId>
       <version>21.0.0.2</version>
       <executions>
          <execution>
             <goals>
                <goal>native-image</goal>
             </goals>
             <phase><b>package</b></phase>
          </execution>
       </executions>
    </plugin>

    因此,本节的最后一步只是运行 Maven 构建。在我的配置中,native-image-maven-plugin需要在native-image配置文件下激活一个。

    $ mvn clean package -Pnative-image

    Skaffold 的配置是典型的。我们只需要启用 Jib 作为构建工具。

    apiVersion: skaffold/v2beta11
    kind: Config
    metadata:
      name: callme-service
    build:
      artifacts:
      - image: piomin/callme-service
        jib: {}
    deploy:
      kubectl:
        manifests:
          - k8s/ksvc.yaml

    最后,我们可以使用以下命令在 Knative 上构建和部署 Spring Boot 微服务。

    $ skaffold run

    5. Knative 上微服务之间的通信

    我在 Knative 上部署了每个应用程序的两个修订版。只是为了比较,部署应用程序的第一个版本是使用 OpenJDK 编译的。只有最新版本基于 GraalVM 原生镜像。因此,我们可以比较两个版本的启动时间。

    让我们看一下部署我们应用程序的两个版本后的修订列表。流量分为 60% 到最新版本,40% 到每个应用程序的先前版本。

    在底层,Knative 创建了 KubernetesServices和多个Deployments. Deployment每个 Knative总是有一个Revision。此外,有多种服务,但始终其中一项服务是针对所有修订版的。那Service是一种ExternalName服务类型。假设您仍想在多个修订版之间拆分流量,您应该在通信中准确使用该服务。服务的名称是callme-service。但是,我们应该使用带有命名空间名称和svc.cluster.local后缀的 FQDN 名称。

    我们可以使用 SpringRestTemplate来调用callme-service. 为了保证对整个请求路径的跟踪,我们需要在后续调用之间传播 Zipkin 标头。对于通信,我们将使用具有完全限定的内部域名 ( callme-service.serverless.svc.cluster.local) 的服务,如前所述。

    @RestController
    @RequestMapping(<font>"/caller"</font><font>)
    <b>public</b> <b>class</b> CallerController {
    
       <b>private</b> RestTemplate restTemplate;
    
       CallerController(RestTemplate restTemplate) {
          <b>this</b>.restTemplate = restTemplate;
       }
    
       @Value(</font><font>"${spring.application.name}"</font><font>)
       <b>private</b> String appName;
       @Value(</font><font>"${POD_NAME}"</font><font>)
       <b>private</b> String podName;
       @Value(</font><font>"${POD_NAMESPACE}"</font><font>)
       <b>private</b> String podNamespace;
       @Autowired
       <b>private</b> CallerRepository repository;
    
       @GetMapping(</font><font>"/ping"</font><font>)
       <b>public</b> String ping(@RequestHeader HttpHeaders headers) {
          Caller c = repository.save(<b>new</b> Caller(<b>new</b> Date(), podName));
          String callme = callme(headers);
          <b>return</b> appName + </font><font>"(id="</font><font> + c.getId() + </font><font>"): "</font><font> + podName + </font><font>" in "</font><font> + podNamespace
                         + </font><font>" is calling "</font><font> + callme;
       }
    
       <b>private</b> String callme(HttpHeaders headers) {
          MultiValueMap<String, String> map = <b>new</b> LinkedMultiValueMap<>();
          Set<String> headerNames = headers.keySet();
          headerNames.forEach(it -> map.put(it, headers.get(it)));
          HttpEntity httpEntity = <b>new</b> HttpEntity(map);
          ResponseEntity<String> entity = restTemplate
             .exchange(</font><font>"http://callme-service.serverless.svc.cluster.local/callme/ping"</font><font>,
                      HttpMethod.GET, httpEntity, String.<b>class</b>);
          <b>return</b> entity.getBody();
       }
    
    }
    </font>

    为了测试我们的微服务之间的通信,我们只需要caller-service通过 Knative调用Route。

    GET /caller/ping让我们对调用者服务端点执行一些测试调用。我们应该使用 URL http://caller-service-serverless.apps.cluster-d556.d556.sandbox262.opentlc.com/caller/ping。

    在第一次请求 caller-service 时调用最新版本的 callme-service(用 GraalVM 编译)。在第三个请求中,它与旧版本的 callme-service(使用 OpenJDK 编译)进行通信。让我们比较同一应用程序的这两个版本的启动时间。

    使用 GraalVM,我们有0.3s而不是5.9s。我们还应该记住,我们的应用程序会启动一个内存中的嵌入式 H2 数据库。

    6. 使用 Jaeger 配置跟踪

    为了启用 Knative 的跟踪,我们需要更新命名空间knative-tracing ConfigMap中的knative-serving。当然,我们首先需要在我们的集群中安装 Jaeger。

    apiVersion: <b>operator</b>.knative.dev/v1alpha1
    kind: KnativeServing
    metadata:
      name: knative-tracing
      namespace: knative-serving
    spec:
      sample-rate: <font>"1"</font><font> 
      backend: zipkin 
      zipkin-endpoint: http:</font><font><i>//jaeger-collector.knative-serving.svc.cluster.local:9411/api/v2/spans </i></font><font>
      debug: </font><font>"false"</font><font>
    </font>

    你也可以使用 Helm chart 来安装 Jaeger。使用此选项,您需要执行以下 Helm 命令。

    $ helm repo add jaegertracing https:<font><i>//jaegertracing.github.io/helm-charts</i></font><font>
    $ helm install jaeger jaegertracing/jaeger
    </font>

    Knative 会自动创建 Zipkin span headers。我们唯一的目标是在caller-service和callme-service应用程序之间传播 HTTP 标头。在我的配置中,Knative 向 Jaeger 发送 100% 的跟踪信息。让我们看一下GET /caller/pingKnative 微服务网格中端点的一些跟踪。

    我们还可以查看每个请求的详细视图。

    结论

    在 Knative 上运行微服务时,需要考虑几件重要的事情。我专注于与通信和跟踪相关的方面。我还展示了 Spring Boot 不必在几秒钟内启动。使用 GraalVM,它可以在几毫秒内启动,因此您绝对可以将其视为 无服务器 框架。

    原文链接:https://www.jdon.com/58816

    展开全文
  • GraalVM使用Graal作为其JIT编译器,将频繁执行的代码片段编译为机器代码。我们实现了PHP语言的一个子集,以运行“计算机语言基准游戏”中的综合基准。我们比较了与PHP 7以及其他实现(例如HHVM,JPHP和PHP 8的早期...
  • 使用GraalVM Gradle和Docker创建Java应用程序的本机映像的示例 首先创建图像: docker build -t graalvm-demo . 然后运行它: docker run -p 4567:4567 graalvm-demo 最后去: 查看build.gradle和Dockerfile...
  • 建造首先,确保你已经安装了cargo-make ,GRAAL_HOME环境变量指向你安装 GraalVM 的根目录,并且安装了 GraalVM LLVM 工具链:export GRAAL_HOME=[PATH_TO_GRAAL] cargo install cargo-make${GRAAL_HOME} /bin/gu ...
  • GraalVM入门到精通

    千次阅读 2021-12-26 21:06:41
    GraalVM入门到精通 JavaFX转exe Java转exe GraalVM

    介绍

    GraalVM是一个类似于JVM的虚拟机,但还可以编译和运行多种语言,如C++, JS, Python。当然这里我们介绍它最特别之处:可以把Java应用直接转换成最精简的本地二进制应用(exe, elf等),然后可以脱离JVM直接在本地平台运行。此处重点介绍exe


    安装

    1. 安装VS环境(这里是VS2022),需要安装的组件如下
      VS截图

    2. Github下载GraalVM解压包,我这里用的是graalvm-ce-java17-windows-amd64-21.3.0.zip。下载完解压到某个路径下,我这里是 D:/OK/GraalVM

    3. 添加环境变量D:\OK\GraalVM\bin

    4. 打开控制台,运行gu install native-image(需要科学上网),这个包能提供创建本地镜像的能力。(native-image 命令)


    用法


    控制台应用

    1. 编写一个java文件
      我这里路径为 D:/OK/test-se/Main.java,内容如下:
    import java.util.*;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            System.out.println("Hello World!");
            System.in.read();
        }
    }
    
    1. 编译这个java文件(javac),得到Main.class

    2. 打开X64 Native Tools Command Prompt for VS 2022,如图:
      VS CMD
      这个命令行集成了C++的编译环境,用来生成目标exe文件。

    3. 在这个命令行中cd到Main.class的文件夹,输入
      native-image Main
      稍等片刻,即可看到生成了main.exe
      main.exe

    4. main.exe大小只有14.5MB,比JLink生成的还小。双击打开效果如下,相当成功!
      open exe

    JavaFX应用

    这次我们难度加大点,来启动一个JavaFX应用。
    我们都知道,从JDK11开始JavaFX就被移出了,使用时需要我们自己导入对应的jar包。

    1. 构建项目
      注: 这里我们需要生成单jar包(fat jar),所以要求项目必须写单独的启动类,不能在继承Application的类中直接写Main方法,否则会因为使用非模块的启动方式而报错:
      错误: 缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序

    2. 生成单独的jar包
      pom.xml加入以下内容

    <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>17</source>
                        <target>17</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>3.3.0</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <archive>
                            <manifest>
                                <mainClass>单独启动类的全类名</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    

    然后执行maven package,执行完毕后把项目目录的target/*-jar-with-denpendencies.jar(单jar文件)复制出来,重命名备用。(我这里复制到D:/OK/test-fx/fx-demo.jar

    1. 生成配置文件
      注:因为GraalVM是在编译时把所有用到的类都放在最后的二进制文件中,而它却无法觉察到反射jni等操作,所以需要我们编写配置文件告诉它,让他把反射用到的class文件,jni调用的dll文件等也都加进来,这样才能正确运行JavaFX应用。


      在VS控制台中,我们先cd到jar文件的目录,然后执行以下命令:
      D:\OK\GraalVM\bin\java -agentlib:native-image-agent=config-output-dir=./config -jar fx-demo.jar
      这个命令会运行jar包,然后在运行时记录它调用的资源到config文件夹的一些json文件中。


      执行成功以后,试用一下被打开的JavaFX应用(方便配置文件的记录,防止少记录反射等信息),然后关闭应用,就在资源管理器中就能看到在jar文件的旁边生成了一个config文件夹,打开以后出现这些文件:
      config
      其中reflect-config.json记录了反射的类,jni-config.json记录了jni的方法,resource-config.json记录了调用的dll资源,其他的还有动态代理调用情况等等。

    2. 生成exe文件
      在刚刚的VS控制台执行以下命令:
      native-image -H:ConfigurationFileDirectories=./config -jar fx-demo.jar
      该命令会根据jar文件和刚刚生成的config文件夹中的配置文件生成最终的exe可执行文件。

    结果竟然报错了:
    error

    不过我们在jar文件的目录下看到生成了以下文件:
    exe result

    其实这个错误应该是GraalVM的一个bug,不影响exe生成。

    然后我们删除目录下多余的文件:awt.dll, java.dll, fx-demo.build_artifacts.txt

    1. 打开exe
      生成的exe只有37.3MB!打开fx-demo.exe,可以看到以下内容:
      javafx result
      测试成功!!!

    注:黑框暂时不知道怎么去除。


    总结

    GraalVM可以把java应用程序直接转换为本地应用,运行时不再依赖JVM,并且最终的成品还比JLink更小,是个相当不错的工具。



    展开全文
  • clj-graal-docs 目录JDK11和clojure.lang.Reflector 与本机库接口JNI API错误在macOS上的启动性能定位最低的macOS版本GraalVM开发构建测试策略外部资源执照 基本原理这个小仓库的目标是收集有关使用GraalVM本地编译...
  • 徽标RRR LogoRRR是一个简单的实用程序,用于显示...先决条件您必须下载最新的GraalVM安装程序包(我已经在21.0.0.r11中对其进行了测试)和maven发行版(从3.6.3版开始的所有程序都可以使用)。 当前,该应用程序可以分
  • 我们开发用于Windows的GraalVM Installer的主要原因是为了帮助使用Windows操作系统的任何人在其计算机上安装快速,可靠且完全免费的Java虚拟机。 Oracle宣布,自2019年1月起,没有商业许可证的Java SE 8公共更新将...
  • 调用Rust库的Clojure程序示例使用GraalVM组合成一个可执行文件。 它通过库获取可用内存量,并以EDN格式打印。 此仓库是Rust 库的自述文件中描述的改编示例。 在clojure/src-java有一个Java静态方法可通过JNI调用...
  • 使用GraalVM的本机映像生成的即时Netty启动 该存储库的目的是使用 工具从简单的应用程序生成本机可执行映像。 搭建开发环境 要设置您的开发环境,您首先需要 。 就此示例而言,无论是Community Edition还是...
  • GraalVMgraalvm-ce-java17-linux-amd64-21.3.0.tar.gz适用于Linux (amd64) ), GraalVM 是一个高性能 JDK 发行版,旨在加速用 Java 和其他 JVM 语言编写的应用程序的执行,并支持 JavaScript、Ruby、Python 和...
  • setup-graalvm

    2021-04-30 00:43:48
    该操作设置了GraalVM环境以供在GitHub操作中使用。 它下载(如果尚未缓存)所需的GraalVM Community Edition版本 将GraalVM发行版提供的执行器添加到环境中 注册问题匹配器以输出错误 笔记: 从19.3.0版开始,每...
  • scala-graalvm-docker:使用GraalVM构建和生成本机工件的Docker映像
  • GraalVM到Quarkus系列-A002篇-GraalVM中的动态代理系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器...
  • 使用GraalVM扩展名在系统上选择或安装基于Java 11的GraalVM 20.3或更高版本。 通过运行“使用GraalVM Updater(gu)安装Live组件”命令。 在GraalVM扩展名的设置中禁用“语言服务器:在进程服务器中”选项: 首选项...
  • 在这个项目中,我将向您演示如何准备要使用GraalVM进行编译的应用程序。 入门 此回购在几篇文章中使用,这些文章利用了快速的应用程序启动。 带有Spring Boot和GraalVM的Knative上的微服务-即将推出! 它显示了...
  • 使用 GraalVM 将纯 JavaFX 项目打包成 exeGraalVM 的环境搭建使用 GraalVM 打包不含 FXML 的纯 JavaFX 项目使用 GraalVM 打包含 FXML 的纯 JavaFX 项目测评在 IntelliJ IDEA 中直接运行生成 JAR 包后运行GraalVM ...
  • 使用 GraalVM 将基本的 Java 项目打包成 exeGraalVM 的环境搭建使用 GraalVM 将基本的 Java 项目打包成 exe使用 GraalVM 将 JAR 转化为 exe GraalVM 的环境搭建 GraalVM 有两种版本,Community 和 Enterprise。...
  • clj.native-cli:使用Clojure和GraalVM创建本机CLI工具的模板
  • 使用GraalVM,将Clojure作为本机可执行文件的速度提高了100倍您好,GraalVM使用GraalVM的Clojure本机可执行文件。 100倍加速! 概述GraalVM是另一种编译器,可以将Clojure(和许多其他语言)编译成本地的,静态...
  • 目前在各个语言的性能基准上还不能统一,语言之间互操作的协议还需要完善,甚至还要牺牲特定编程语言的一些特性,比如Java Native Image目前无法使用动态加载,另外GraalVM也还没有经过大规模的生产实践,还有一个...
  • 什么是GraalVM呢? 这个东西好啊,这个东西是一个超级虚拟机,可虚可实,怎么说呢,它可以运行脚本代码,可以运行跨平台代码,最牛B的是,它TM还能把这些代码编译成机器码,你说上哪说理去,执行效率CUA的一下就...
  • cljfmt-graalvm:一种使用graalvm构建的cljfmt的Clojure代码格式化程序
  • 此示例演示了一个使用GraalVM中运行的corda rpc-3.1库的nodejs服务器。 Node.js服务器提供API以创建IOU,获取类似于IOU 先决条件 设置GraalVM环境 请遵循官方文档,了解如何为Linux或osX设置Graal。 要了解有关...
  • 这个示例项目展示了如何使用GraalVM本机映像将基于Webflux的Spring Boot应用程序编译成本机应用程序 该项目在这里展示了当前可行的技术演示- 有望获得对Spring Boot的稳定GraalVM Native Image支持,Spring Boot ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,058
精华内容 823
关键字:

graalvm 使用