graal java_使用SparkJava和Graal的本机微服务

graal java

使用SparkJava编写的微服务只是使用标准Java库的普通Java代码。 没有注释魔术,只有代码。 这种简单的编程风格的优点在于,它很简单。 非常简单,以至于Graal本机编译器只需编译就不会闪烁 ,这对于例如Spring之类的更复杂的框架而言,目前是非常困难的。

SparkJava / Graal组合本身就很有趣,人们对此的体验也开始 出现 。 此外,作为Java库,应该可以从其他基于JVM的语言中使用它,我想知道Graal将如何应对。 实际上,事实证明这很简单,在本文中,我们将看到为Java,Kotlin甚至Clojure构建本机微服务二进制文件非常容易。

入门

如果您还没接触过Graal,我建议您访问他们的网站 ,看看它提供了什么。 在这里,我们使用的是本机编译功能,但实际上这只是在摸索。

要首先使用Graal,您需要安装最新版本的Graal SDK。 撰写本文时为1.0.0-rc9 。 我使用SdkMan做到了 :

sdk install java 1.0.0-rc9-graal

从那时起

sdk use java 1.0.0-rc9-graal

然后创建一个基本的Gradle项目并添加最小依赖项:

dependencies {compile "com.sparkjava:spark-core:2.7.2"compile "org.slf4j:slf4j-simple:1.7.13"
}

(我假设您已经熟悉Gradle,如果愿意的话,可以使用Maven进行 。请注意,选择的Slf4j实现与SparkJava所需的版本匹配非常重要。)

在SparkJava中,微服务端点本质上是lambda表达式形式的路径或回调之间的绑定或route 。 这是我们将用作基础的标准“ hello world”示例。 当然,现实世界中的服务将利用请求和响应对象。 请参阅文档以获取更多详细信息。

import static spark.Spark.*;public class HelloWorld {public static void main(String[] args) {get("/sayHello", (req, res) -> "Hello world!");}
}

要将其作为命令行程序运行,将所有依赖项一起复制到同一目录中非常方便。 我们也可以使用Gradle做到这一点。

task copyDependencies(type: Copy) {from configurations.defaultinto 'build/libs'shouldRunAfter jar
}assemble.dependsOn copyDependencies

生成服务并运行它以检查其是否有效。

> ./gradlew clean assemble
> java -cp "build/libs/*" HelloWorld
...
[Thread-0] INFO org.eclipse.jetty.server.Server - Started @363ms
> curl localhost:4567/sayHello
Hello World!

让我们使用Graal将其编译为本地二进制文件。 幸运的是,该命令与java命令非常相似:

> native-image -cp "build/libs/*" HelloWorld
...
Build on Server(pid: 31197, port: 52737)*
[helloworld:31197]    classlist:   2,142.65 ms
[helloworld:31197]        (cap):   2,154.21 ms
...
...
[helloworld:31197]        write:     443.13 ms
[helloworld:31197]      [total]:  56,525.52 ms

现在,我们应该在当前目录中拥有本机二进制文件。 让我们运行它:

> ./helloworld
...
[Thread-2] INFO org.eclipse.jetty.server.Server - Started @2ms
> curl localhost:4567/sayHello
Hello World!

可执行文件为14Mb,但看该启动时间2ms基本上是瞬时的! 从内存角度讲,过多地关注top是不明智的,但是很明显,从运行时删除JVM具有其优势。 这在部署大量独立进程的微服务系统中尤其重要。

Kotlin呢?

Kotlin是一种JVM语言,正在Swift发展并且并非没有道理。 它结合了功能样式和OO功能,无缝的Java互操作性和简洁的语法,使其成为通用的良好语言,并且是Java的明显替代。 首先要使用Kotlin构建我们的服务,我们将Kotlin库依赖项添加到Gradle(撰写本文时版本为v1.3.10)。

dependencies {
...compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.10"
}

并使用Kotlin编译器插件。

plugins {id 'org.jetbrains.kotlin.jvm' version '1.3.10'
}

使用Kotlin,我们荒唐的简单微服务变得更加简单。

import spark.Spark.*fun main(args: Array<String>) {get("/sayHello") { req, res -> "Hello World!" }
}

生成服务并运行它以检查其是否有效。

> ./gradlew clean assemble
> java -cp "build/libs/*" HelloWorldKt
...
[Thread-0] INFO org.eclipse.jetty.server.Server - Started @363ms
> curl localhost:4567/sayHello
Hello World!

让我们本地编译它。 因为它 Java,所以命令几乎与Java版本相同(Kotlin编译器会自动将Kt后缀添加到生成的类中)。

> native-image -cp "build/libs/*" HelloWorldKt
Build on Server(pid: 53242, port: 51191)
[helloworldkt:53242]    classlist:     783.03 ms
[helloworldkt:53242]        (cap):   2,139.45 ms
...
[helloworldkt:53242]        write:     591.88 ms
[helloworldkt:53242]      [total]:  53,074.15 ms

并运行它:

> ./helloworldkt
...
[Thread-2] INFO org.eclipse.jetty.server.Server - Started @2ms
> curl localhost:4567/sayHello
Hello World!

可执行文件的大小和启动速度几乎与Java版本相同,这是可以预期的,因为它实质上是相同的代码。

这是一个基本示例,但Kotlin实现简化SparkJava简化 实现 微服务Graal简化部署相结合,对于微服务开发而言是一个非常诱人的主张。

尽管如此,除了更好的语法外,Kotlin与Java非常相似。 我们还可以使用其他JVM语言,这些语言可能会进一步推动Graal。

需要Clojure

使用Clojure构建微服务是一个有趣的想法。 服务本质上是自然的功能,实际上服务一种功能,语言的动态特性可能使其成为某些以数据为中心的情况的理想选择。

而不是使用Gradle,我们将从一个新的Leiningen项目开始:

lein new hello-clojure

依赖关系放在main project.clj文件中,以及我们将用来启动服务器的主类的名称。

:dependencies [[org.clojure/clojure "1.9.0"][com.sparkjava/spark-core "2.7.2"][org.slf4j/slf4j-simple "1.7.13"]]:main hello_clojure.core)

Clojure可与Java互操作,但程度不及Kotlin。 为了克服这些差异,我编写了一些适配器,以允许惯用的clojure代码使用SparkJava的类。

(ns hello_clojure.core(:gen-class)(:import (spark Spark Response Request Route)))(defn route [handler](reify Route(handle [_ ^Request request ^Response response](handler request response))))(defn get [endpoint routefn](Spark/get endpoint (route routefn)))

(后来我发现了一篇不错的文章 ,其中提供了使用Clojure和SparkJava的完整服务。它们的适配器比我的适配器稍好,因此我在后面的文章中结合了一些想法。)

然后,我们准备创建从main方法执行的控制器,以便可以从命令行轻松调用它。 还要注意,在上面我们使用gen-class指令来确保在清单中指定了主类:

(defn -main [](get "/sayHello" (fn [req resp] "Hello World!!")))

为了简化服务的生成,我们可以使用Leiningen构建一个自包含的jar。

> lein clean && lein uberjar

和以前一样,我们首先检查该服务是否可以正常运行Java:

$ java -cp target/hello-clojure-0.1.0-SNAPSHOT-standalone.jar hello_clojure.core
...
[Thread-0] INFO org.eclipse.jetty.server.Server - Started @1033ms
> curl localhost:4567/sayHello
Hello World!

编译为本地映像就像使用Java和Kotlin的先前示例一样简单。

> native-image -cp target/hello-clojure-0.1.0-SNAPSHOT-standalone.jar hello_clojure.core
Build on Server(pid: 35646, port: 53994)*
[hello_clojure.core:35646]    classlist:   2,704.82 ms
[hello_clojure.core:35646]        (cap):     909.58 ms
...
[hello_clojure.core:35646]        write:     647.23 ms
[hello_clojure.core:35646]      [total]:  54,900.61 ms

并运行它:

> ./helloworld_clojure
...
[Thread-2] INFO org.eclipse.jetty.server.Server - Started @2ms
> curl localhost:4567/sayHello
Hello World!

本地二进制文件再次大约为15M,并且启动时间几乎是瞬时的。

结论

将Graal与其他基于JVM的语言结合使用是一个非常诱人的主张,值得进一步研究,但是我确实对生产用途存在一些担忧。 主要是如果出现问题,公共领域中几乎没有什么信息可以为您提供帮助,而纯Java之外的信息则更少。 另一方面,这些都是开源项目,所以什么都没有隐藏:)

另一个限制是,许多库根本无法与Graal一起使用。 这并不是完全消极的,因为它会鼓励我们回到简单的编码实践中,但是您可能会遇到无法更改的依赖关系,这可能会造成很大的麻烦。 我认为最初的主要缺点是反射驱动的映射,无论是序列化还是ORM品种。 为了使许多库和框架与Graal 兼容 ,已经进行了很多工作,但是还处于初期。

第三,主要是实际的考虑是对原始映像的编译非常慢。 即使是这个非常简单的示例,也几乎需要花费一分钟的时间来构建。 当然,您可以仅将开发编译为字节码,但是兼容性问题可能会消失。 持续的构建流程和全面的测试将是减轻这种风险的一种方法。

显然,要使它成为一个功能齐全的服务还有许多工作要做,并且在投入生产使用之前要进行适当的考虑,但是如果我们选择继续使用简单的代码,那么问题将被最小化。

翻译自: https://www.javacodegeeks.com/2019/01/native-microservices-sparkjava-graal.html

graal java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332816.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python消息订阅_python实现发布订阅

订阅者&#xff1a;import redisrc redis.StrictRedis(host‘127.0.0.1‘, port‘6379‘, db0)ps rc.pubsub()ps.subscribe(‘lbky‘) # 从lbky订阅消息for item in ps.listen(): # 监听状态&#xff1a;有消息发布了就拿过来print(item)if item[‘type‘] ‘message‘:prin…

使用JDBC连接数据库时,SQL语句中提示:Unable to resolve table...(原因:数据源未配置)

文章目录方法一、添加数据源方法二、输入全限定表名在 IDEA 中的 Java 代码中写 SQL 语句时&#xff0c;出现如下图所示的错误提示&#xff1a;方法一、添加数据源 要解决上面红色警告的问题&#xff0c;只需要添加数据源就可以解决。 方法二、输入全限定表名 前提&#xff1…

测试反模式冰激凌模式的不足_单元测试反模式,完整列表

测试反模式冰激凌模式的不足我前段时间写过有关OOP中的反模式的文章 。 现在该写单元测试反模式了&#xff0c;因为它们也存在&#xff0c;并且有很多。 我将尝试在列表中包括我知道的每个示例。 如果您认识其他任何人&#xff0c;请通过请求请求将其添加&#xff0c;或在下面发…

mysql导入三个基本表_mysql 基础导入导出

导入导出mysqldump导出&#xff1a;mysqldump -u root -p --databases 数据库1 数据库2 > xxx.sql导入&#xff1a;系统命令行&#xff1a; MySQL -u用户名 -p密码 常见选项&#xff1a;--all-databases, -A&#xff1a; 备份所有数据库--databases, -B&#xff1a; 用于备份…

Java代码中方法的特殊修饰符/修饰词/关键字

文章目录nativesynchronizednative 用该修饰符定义的方法在类中没有实现&#xff0c;而大多数情况下该方法的实现是用C、C编写的。 synchronized 多线程的支持。用该修饰符定义的方法被调用时&#xff0c;没有其它线程能够调用该方法&#xff0c;其它的 synchronized 方法也…

aws dynamodb_带有AWS DynamoDB的React式Spring Webflux

aws dynamodbAWS已经发布了Java版本2的AWS开发工具包 &#xff0c;该开发工具包现在支持针对不同AWS服务的API调用的非阻塞IO。 在本文中&#xff0c;我将探讨如何使用AWS开发工具包2.x的DynamoDB API以及如何使用Spring Webflux堆栈公开响应式端点-这种方式&#xff0c;应用程…

centos6.5 rpm安装mysql_CentOS6.5系统下RPM包安装MySQL5.6(转)

1.查看操作系统相关信息。[rootlinuxidc ~]# cat /etc/issueCentOS release 6.5 (Final)Kernel \r on an \m[rootlinuxidc ~]# uname -aLinux linuxidc 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux2.创建需要下载rpm软件包的目…

对象作为参数示例java_功能Java示例 第6部分–用作参数

对象作为参数示例java这是称为“ Functional Java by Example”的系列文章的第6部分。 我在本系列的每个部分中开发的示例是某种“提要处理程序”&#xff0c;用于处理文档。 在前面的部分&#xff0c;我们试图通过移动尽可能多的副作用&#xff0c;如IO&#xff0c;该系统的外…

为什么Java在后来的版本中,给接口增加了默认方法、静态方法、私有方法?

在业务发展过程中&#xff0c;发现某个功能是所有子类都需要的&#xff0c;那么我们该怎么办&#xff1f;给接口增加抽象方法吗&#xff1f;如果直接在接口增加抽象方法&#xff0c;那么所有已经写好的具体实现类就会报编译错误。因为具体类必须实现接口的全部抽象方法。这样就…

linux 源码包安装mysql_LINUX下源码包安装mysql

tar xvfz mysql-5.1.50-linux-i686-glibc23.tar.gz -C /usr/local/解压到的目录cd /usr/local/[rootdrbd2 local]# ln -sv mysql-5.1.50-linux-i686-glibc23 mysql(创建连接)groupadd mysql 添加mysql的用户组useradd -g mysql mysql 增加mysql用户并把其加入mysql组cd mysql[r…

jdk 安全属性_系统属性的JDK 12 Javadoc标记

jdk 安全属性JDK 12 Early Access Build 20 &#xff08; 2018/11/15 &#xff09;可用&#xff0c;可以用来试用新的Javadoc标签{systemProperty} 。 新的{systemProperty} Javadoc标记在core-libs-dev邮件列表消息“ FYI&#xff1a;用于记录系统属性的新javadoc标记 ”中进行…

Lambda表达式的学习

文章目录函数式编程思想函数式接口Lambda 的使用前提Lambda 的标准格式Lambda 极简特性演示代码函数式编程思想 与面向对象编程思想的区别&#xff1a; 1.面向对象的思想是做一件事情&#xff0c;找一个能解决这个事情的对象&#xff0c;调用对象的方法来完成事情 2.函数式编程…

公证服务信息_使用多个公证员提高网络吞吐量

公证服务信息您是否需要高吞吐量的Corda网络&#xff1f; 网络的吞吐量是否稳定&#xff1f; 您是否已经从其他领域挤出了所有可能的表现&#xff1f; 如果您对这些问题的回答是“是”&#xff0c;那么我可能会为您提供一些有用的信息。 我列出了这些问题&#xff0c;以减少您过…

java判断手机号_java使用正则表达式判断手机号的方法示例

本文实例讲述了java使用正则表达式判断手机号的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;要更加准确的匹配手机号码只匹配11位数字是不够的&#xff0c;比如说就没有以144开始的号码段&#xff0c;故先要整清楚现在已经开放了多少个号码段&#xff0c;国家号…

Spring JDBC的学习

文章目录介绍使用步骤常用方法示例代码介绍 所谓 Spring JDBC&#xff0c;是 Spring 框架对 JDBC 的简单封装。提供了一个 JdbcTemplate 对象简化 JDBC 的开发。 使用步骤 步骤&#xff1a; 1.导入相关的 jar 包 2.创建 JdbcTemplate 对象&#xff0c;依赖于数据源 DataSo…

编写脚本电脑怎么编写界面_在任何无法理解的情况下,请编写脚本

编写脚本电脑怎么编写界面脚本编写是使您的应用程序在运行时就可根据客户需求进行调整的最流行的方法之一。 与往常一样&#xff0c;此方法不仅带来好处&#xff0c;例如&#xff0c;在灵活性和可管理性之间存在众所周知的折衷方案。 本文不是从理论上讨论优缺点的文章之一&…

stack java实现_Stack (堆栈)使用JAVA实现

代码如下&#xff1a;import java.util.AbstractList;import java.util.Arrays;import java.util.Iterator;import java.util.List;import java.util.RandomAccess;public class Stack extends AbstractListimplements List, RandomAccess, Cloneable, java.io.Serializable{pr…

HTML特殊符号/特殊字符

注&#xff1a;实体名称大小写敏感 点击查看更多特殊字符

访客模式 无痕模式 区别_旧访客设计模式的新生活

访客模式 无痕模式 区别介绍 访客 [1、2]是众所周知的经典设计模式。 有很多资源对其进行了详细说明。 在不深入研究实现的情况下&#xff0c;我将简要提醒一下该模式的概念&#xff0c;解释其优点和缺点&#xff0c;并提出一些可以使用Java编程语言轻松应用于其的改进。 古典…

HTML的图片标签img的图片地址

使用相对路径&#xff0c;例如&#xff0c;当前目录中的子目录 image 中的图片 1.jpg&#xff0c;可以写成 ./image/1.jpg&#xff0c;其中 ./ 表示当前目录&#xff0c;可以省略不写。 <img src"image/1.jpg"/>实际上HTML文档数据写入到 Response 中时&#…