社区编辑申请
注册/登录
云原生Java框架-Micronaut 译文 精选
云计算 云原生
本文先介绍Micronaut的基本特点,然后从一个简单的基于RESTful API的应用开始,将其重构为反应式非阻塞IO(reactive non-blocking IO,NIO),并介绍Micronaut如何支持基于微服务和无服务器架构的云原生开发。

译者 | 陈峻

审校 | 孙淑娟

长期以来,Spring框架一直主导着后端Java的开发,但是以Micronaut、Quarkus、以及Dropwizard为代表的新型云原生Java框架正在不断流行。其中,Micronaut是一种令人耳目一新的替代方案。它是由构建Grails(译者注:Grails是一套用于快速Web应用开发的开源框架)的团队,专为现代化架构而设计开发的。

本文先介绍Micronaut的基本特点,然后从一个简单的基于RESTful API的应用开始,将其重构为反应式非阻塞IO(reactive non-blocking IO,NIO),并介绍Micronaut如何支持基于微服务和无服务器架构的云原生开发。

Micronaut的特征

Micronaut提供了从Spring和Grails等传统框架处继承来的大量优势,其中的一项被称为“原生云原生(natively cloud native)”,即:为云环境从头开始构建。它的云原生能力包括:环境检测、服务发现、以及分布式跟踪等。

同时,Micronaut提供了一个全新的控制反转(inversion-of-control,IoC)容器。该容器能够使用提前(ahead-of-time,AoT)编译,来加快启动速度。此处的AoT是指,启动时间不会随着代码库的增多而增加。这对于无服务器和基于容器的部署来说,是尤其重要的。毕竟,在这些部署中,节点通常会按需进行关闭和启动。

作为一个多语言JVM框架,Micronaut目前支持Java、Groovy和Kotlin,并且即将支持Scala。

此外,Micronaut也支持响应式编程。开发人员可以在该框架内,使用ReactiveX或Reactor。其实,从 2021年7月发布的Micronaut 3开始,Reactor已被推荐使用了。值得注意的是,其新版本并没有将响应式库作为传递式依赖项。

1.开始使用Micronaut  

我们可以通过SDKMan,将Micronaut轻松地安装在包括Linux和macOS在内的任何基于Unix的系统上。如果您使用的是Windows,那么请下载Micronaut的二进制文件,并将其添加到合适的路径中。

在安装完成后,您可以在命令行中看到mn工具的提示符。也就是说,通过打开一个Shell,并定位到合适的位置,您便可以键入:mn create-app micronaut-idg --build maven。

Micronaut通过包装器(wrapper)来支持Gradle和Maven。这免去了自行安装和构建工具的繁琐。注意,如果您喜欢使用Gradle的话,请不要在上述命令中使用--build maven。  

如果您使用mvnw mn:run命令来运行服务器,并在浏览器中输入http://localhost:8080/,那么您可能会看到一个默认为“未找到(not found)”的JSON响应。对此,让我们来研究一下该示例项目的布局。它是一个标准的Maven项目。其main类位于src/main/java/micronaut/idg/Application.java中。请注意,该main类是以一个嵌入式服务器运行的。当您更改代码时,Micronaut开发服务器会自动更新正在运行的应用程序。

2.添加一个Micronaut控制器  

就像在Spring的MVC 中一样,您可以添加各种控制器类(controller class),将URL映射到代码处理器(handler)上。例如,您可以在src/main/java/micronaut/idg/controller/SimpleController上添加一个类。如下面的清单1所示,我们使用该控制器来创建一个文本响应。

清单1. 使用Micronaut控制器

package micronaut.idg.controller; 

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/simple"
public class SimpleController {

@Get(produces = MediaType.TEXT_PLAIN
public String index({
return "A Simple Endpoint";
}
}

如下面的清单2所示,它能够容易地返回一个JSON格式的响应。

清单2. JSON格式的响应

package micronaut.idg.controller; 

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

import java.util.Map;
import java.util.HashMap;

@Controller("/simple"
public class SimpleController {

@Get(produces = MediaType.APPLICATION_JSON
public Map index({
Map msg = new HashMap(;
msg.put("message", "A simple message";
return msg;

}
}

清单2演示了Micronaut针对@Get注解的produces参数所进行的智能处理。在这种情况下,它会发送我们已设置好的JSON格式的响应。

3.添加Micronaut服务层  

由于能够预运行,因此Micronaut的IoC实现在底层是唯一的。当然,它仍然属于CDI(Contexts and Dependency Injection,上下文和依赖注入)规范的完整实现。这就意味着您可以使用从Spring中(如@Inject)获悉的所有类似DI的注释。

在下面的清单3中,我们将连接一个服务层的bean,以提供消息。在实际的应用程序中,这个类可以通过一个数据访问bean,来调用数据存储或其他远程的API。例如,我们可以创建一个src/main/java/micronaut/idg/service文件夹,并添加如清单3所示的两个文件——一个接口(Simple)、及其实现(SimpleService)。

清单3. 创建一个简单的服务层bean

// Simple.java 
package micronaut.idg.service;

public interface Simple {
public String getMessage(;

}

// SimpleService.java
package micronaut.idg.service;

import jakarta.inject.Singleton;

@Singleton
public class SimpleService implements Simple {
public String getMessage({
return "A simple service message";

}
}

现在,您可以通过将服务注入在清单1中创建的SimpleController服务,来使用新的服务层。下面的清单4展示了Constructor的注入。

清单4. 将服务bean注入控制器

@Controller("/simple"
public class SimpleController {

@Inject
private final Simple simpleService;

public SimpleController(@Named("simpleService") Simple simple) { //(1)
thi.simpleService = simple;

}

@Get(produces = MediaType.APPLICATION_JSON
public Map index({
Map msg = new HashMap(;
msg.put("message", simpleService.getMessage());
return msg;
}
}

关键性任务是在注释1处完成的,其中服务bean是按照名称完成了连接。至此,如果您去访问http://localhost:8080/simple,就能够看到来自服务层的响应:{"message":"A simple service message"}。  

4.使用Micronaut的反应式NIO  

接下来,让我们来讨论Micronaut与Reactor的结合使用。在这种情况下,我们将重构当前的应用程序,以使用Reactor和非阻塞IO。该应用程序虽然仍执行相同的任务,但是在后台会使用非阻塞栈——Reactor和Netty。

如前文所述,Micronaut 3默认是不包含响应式库的,因此,正如下面的清单5所示,我们首先需要将Reactor核心添加到Maven的POM处。

清单5. 将Reactor添加到pom.xml

<dependency> 
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.4.11</version>
</dependency>

如下面的清单6所示,您可以对返回的SimpleController进行修改。

清单6. 使控制器非阻塞

import reactor.core.publisher.Mono; 

//...

@Get
public Mono<map> index({
Map msg = new HashMap(;
msg.put("message", simpleService.getMessage());
return Mono.just(msg);
}
}

如您所见,我们只是使用Reactor的Mono类,包装了相同的返回类型(即,string/strin的映射)。

在反应方式中,由于使用远程服务也能够得到类似的支持,因此您完全可以在非阻塞IO上运行应用程序。

5.使用Micronaut的CLI创建新的组件  

您也可以使用Micronaut的命令行工具(CLI),来stub out各种组件。例如,如果你想添加一个新的控制器,那么可以使用命令:mn add-controller MyController。如下面的清单7所示,它将输出一个新的控制器、及其对应的测试。  

清单7. 使用Micronaut命令行创建一个新的控制器

mn create-controller MyController 
| Rendered controller to src/main/java/micronaut/idg/MyControllerController.java
| Rendered test to src/test/java/micronaut/idg/MyControllerControllerTest.java

6.使用Micronaut进行云原生开发  

如前文所述,Micronaut是为云原生微服务和无服务器的开发而构建的。Micronaut支持一种所谓联合(federation)的云原生概念。此处的联合是指,几个较小的应用程序共享相同的设置,并且可以实现串联部署。这听起来像极了微服务架构,其目的就是为了使得微服务的开发更简单,并能够保持可管理性。有关联合服务的更多信息,请参阅Micronaut的相关文档。

此外,Micronaut还可以轻松地针对云环境实现部署。如下面的清单8 所示,您可以部署Google Cloud Platform(GCP)的Docker存储库。  

清单8. 使用GCP的Docker存储库部署Micronaut应用

./mvnw deploy \ 
-Dpackaging=docker \
-Djib.to.image=gcr.io/my-org/my-project:latest

在这种情况下,该项目会被作为Docker镜像,推送到GCP的Docker存储库处。请注意,我们在此用到了Jib Maven插件。它能够将Java项目转换为Docker镜像,而无需您创建实际的Docker文件。  

此外,我们已经将Docker标识为带有-Dpackaging=docker的打包工具,一旦打包完成,您便可以像下面的清单9那样,使用GCP命令行工具,去部署自己的项目。  

清单9. 从命令行处运行Docker镜像

gcloud run deploy \ 
--image=gcr.io/my-org/my-project:latest \
--platform managed \
--allow-unauthenticated

Micronaut支持的另一种云原生功能是:跟踪。例如,Micronaut通过各种注释,使得启用Jaeger的分布式跟踪,变得相当简单。  

如下面的清单10所示,我们可以将Jaeger配置为跟踪微服务应用程序application.xml文件中的所有请求。

清单10. application.xml中的Jaeger配置

tracing: 
jaeger:
enabled: true
sampler:
probability: 1

7.小结  

Micronaut提供了一系列非常适合云原生和微服务开发的功能。同时,该框架更适合让传统的、基于API的开发,变得简单明了。此外,它还可以与反应式NIO的Reactor和Netty进行很好的集成。

原文链接:https://www.infoworld.com/article/3658968/intro-to-micronaut-a-cloud-native-java-framework.html

译者介绍

陈峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式,分享前沿技术与新知;经常以线上、线下等方式,开展信息安全类培训与授课。

责任编辑:武晓燕 来源: 51CTO技术栈

同话题下的热门内容

一篇文章学会什么是KubernetesKubernetes 可观测性:利用四个开源工具风险日益严峻,容器云平台如何做好安全隔离?备份和恢复Kubernetes集群中的Etcd数据为什么应用程序依赖关系映射对于云迁移至关重要对Kubernetes替代方案的需求服务网格到底能做哪些事?一文弄懂Kubernetes集群管理

编辑推荐

Service Mesh真的是云原生应用的绝配吗云原生桌面:虚拟桌面的解构与重新定义解密云原生---看企业云的未来云原生技术及其未来发展趋势展望如何评估云原生NFV中的容器化VNF部署
我收藏的内容
点赞
收藏

51CTO技术栈公众号