使用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

使用SparkJava和Graal的本机微服务相关推荐

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

    graal java 使用SparkJava编写的微服务只是使用标准Java库的普通Java代码. 没有注释魔术,只有代码. 这种简单的编程风格的优点在于,它很简单. 非常简单,以至于Graal本机编 ...

  2. 监控服务器怎么增加碟机,微服务业务监控方法及服务器专利_专利申请于2017-12-15_专利查询 - 天眼查...

    1. 一种微服务业务监控方法,其特征在于,包括: 生成多个调用请求信息,每个所述调用请求信息对应多个微服务,并将各个所述调用 请求信息发送给对应的微服务;每个所述调用请求信息用于使得对应的微服务生成与 ...

  3. 在一台win10系统的电脑里安装虚拟机运行CentOS7并实现nginx反向代理从而用域名访问本机的微服务项目

    在虚拟机里的CentOS7安装配置nginx,之前需要一些依赖库作为编译安装的条件,具体作用和命令详情跳转我之前的博客. 安装并使用VMware-workstation-full-15.5.0安装Ce ...

  4. 五款最优秀的java微服务框架

    微服务被广泛用于创建多功能的应用程序,通过组合每个功能部分并将它们逐层放在一个单元中.许多人可能没有意识到微服务是一组小型服务中制作单个应用程序的方法,每个服务都独立运行(进程). 换句话说,微服务更 ...

  5. 怒江java培训班_Graal VM:微服务时代的Java

    互联网之于JavaScript.人工智能之于Python,微服务风潮之于Golang,在原生云微服务时代到来时Java能否还长期占据编程语言榜单第一位位置呢?Oracle Labs新公开了一项黑科技: ...

  6. Java 云原生微服务框架 Quarkus 入门实践

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...

  7. spring cloud微服务分布式云架构--hystrix的使用

    hystrix主要作用在服务消费者,进行应用的保护,当请求的服务请求超时时,做出相应的处理,避免客户端一直进行请求等待,避免在高并发的情况出现服务器死机(请求过多,内存不足) 接下来的通过一个案例对h ...

  8. 传统行业转型微服务的挖坑与填坑

    原文:传统行业转型微服务的挖坑与填坑 一.微服务落地是一个复杂问题,牵扯到IT架构,应用架构,组织架构多个方面 在多家传统行业的企业走访和落地了微服务之后,发现落地微服务是一个非常复杂的问题,甚至都不 ...

  9. 在微服务架构下基于 Prometheus 构建一体化监控平台的最佳实践

    欢迎关注方志朋的博客,回复"666"获面试宝典 随着 Prometheus 逐渐成为云原生时代的可观测事实标准,那么今天为大家带来在微服务架构下基于 Prometheus 构建一体 ...

最新文章

  1. 《微软的软件测试之道》(How We Test Software at Microsoft)
  2. 技术大牛养成指南,一篇不鸡汤的成功学实践
  3. 【ssh从零单排】eclipse和tomcat整合配置
  4. thymeleaf 中select下拉回显
  5. Vmware vSphere5.0网络连接服务器配置常见问题
  6. 线接触和面接触的区别_接触器是啥?跟继电器有啥区别,6大常见故障怎么处理...
  7. HIT计算机系统大作业——hello的一生
  8. SpringBoot整合CXF框架实现Webservice服务端
  9. java 线程 假死_JVM假死问题如何定位?
  10. mysql计算连续天数,mysql连续登录天数,连续天数统计
  11. 系统架构师—软件架构设计(二)CS/BS/SOA/DSSA/ABSD
  12. Python爬取《哆啦A梦-伴我同行2》影评,这部的寓意是啥?词云来剧透!
  13. 如何将Processon中画好的图转为Visio可以打开并编辑的vsdx格式
  14. 壹度婚礼邀请函请帖小程序免费制作
  15. 第五天 01-ftp服务器使用及arp欺骗获取ftp账号密码
  16. 机器学习第四篇----MAB(多臂老虎机)一次失败的尝试
  17. Cesium聚簇实现-kdbush类实现
  18. opencv识别图像红色区域,并输出红色区域中心点坐标
  19. [声纹识别]“说话人识别”基本概念
  20. 矩阵的翻转与旋转()(另附代码)

热门文章

  1. 【树形区间DP】加分二叉树(ssl 1033/luogu 1040)
  2. [XSY] 简单的博弈题(博弈+dp+组合数+容斥)
  3. 线段树-Chossing Ads-分治,主元素思想,神题
  4. 5、mysql中的库操作
  5. 3、数据库中的字符集和校对集
  6. K8S Learning(2)——集群环境搭建
  7. Dubbo(八)之API 配置
  8. Java GC系列(2):Java垃圾回收是如何工作的
  9. Mybatis-plus 思维导图,让 Mybatis-plus 不再难懂
  10. (十四)消息中间件MQ详解及四大MQ比较