近日, Oracle 推出了一个新的开源框架 Helidon, 该项目是一个用于创建基于微服务的应用程序的 Java 库集合. 和 Payara Micro,Thorntail(之前的 WildFly Swarm),OpenLiberty,TomEE 等项目一样, 该项目也加入了 MicroProfile 家族.
Helidon 最初被命名为 J4C(Java for Cloud), 其设计以简单, 快速为目标, 它包括两个版本: Helidon SE 和 Helidon MP.Helidon SE 提供了创建微服务的三个核心 API:web 服务器, 配置和安全, 用于构建基于微服务的应用程序, 不需要应用服务器. Helidon MP 支持用于构建基于微服务的应用程序的 MicroProfile 1.1 规范.
Helidon 的架构
下面的架构图显示了 Helidon SE 和 Helidon MP 的关系.
下图说明了 Helidon SE 和 Helidon MP 所属的微服务框架类别.
Web 服务器
受 Node.JS 和其他 Java 框架的启发, Helidon 的 Web 服务器是一个异步, 反应性 API, 运行在 Netty 之上. WebServer 接口包括对配置, 路由, 错误处理以及构建度量和健康端点的支持.
快速入门示例
Helidon 提供了快速入门示例来演示 Helidon SE 和 Helidon MP 之间的区别.
先借用官方示例, 稍后我们手写一个示例.
在 GitHub 上可以找到整个官方 Helidon 项目.
https://github.com/oracle/helidon
构建 Docker 镜像
Helidon SE 示例
docker build -t quickstart-se target
Helidon MP 示例
docker build -t quickstart-mp target
运行 Docker 镜像
Helidon SE 示例
docker run --rm -p 8080:8080 quickstart-se:latest
Helidon MP 示例
docker run --rm -p 8080:8080 quickstart-mp:latest
测试
这两个示例都支持相同的 REST 接口
该示例是一个非常简单的 "Hello World" 问候语服务. 响应使用 JSON 编码. 例如:
- curl -X GET http://localhost:8080/greet
- {
- "message":"Hello World!"
- }
- curl -X GET http://localhost:8080/greet/Joe
- {
- "message":"Hello Joe!"
- }
- curl -X PUT http://localhost:8080/greet/greeting/Hola
- {
- "greeting":"Hola"
- }
- curl -X GET http://localhost:8080/greet/Jose
- {
- "message":"Hola Jose!"
- }
动手写一个示例
环境
Helidon 需要 Java 8(或更高版本) 和 Maven. 如果要构建和部署 Docker 容器, 则需要 Docker. 如果要部署到 Kubernetes, 则需要 kubectl 和 Kubernetes 集群
以下列表显示了最低版本
| Java SE 8 或 Open JDK 8 | | Maven 3.5 | | Docker 18.02 | 使用 Edge 通道在桌面上运行 Kubernetes | | Kubectl 1.7.4 |
Maven 坐标
将以下代码段添加到 pom.xml 文件中
- <dependency>
- <groupId>io.helidon.webserver</groupId>
- <artifactId>helidon-webserver</artifactId>
- <version>0.10.1</version>
- </dependency>
- <dependency>
- <groupId>io.helidon.webserver</groupId>
- <artifactId>helidon-webserver-netty</artifactId>
- <version>0.10.1</version>
- </dependency>
- <!-- WebServer Jersey 依赖 -->
- <dependency>
- <groupId>io.helidon.webserver</groupId>
- <artifactId>helidon-webserver-jersey</artifactId>
- <version>0.10.1</version>
- </dependency>
测试方法
- package com.souyunku.helidon.webserver.examples.jersey;
- import io.helidon.webserver.ServerRequest;
- import io.helidon.webserver.ServerResponse;
- import io.helidon.webserver.jersey.JerseySupport;
- import io.opentracing.SpanContext;
- import javax.inject.Inject;
- import javax.inject.Named;
- import javax.ws.rs.*;
- import javax.ws.rs.core.Context;
- import javax.ws.rs.core.HttpHeaders;
- import javax.ws.rs.core.Response;
- import javax.ws.rs.core.UriInfo;
- import java.util.stream.Collectors;
- @Path("/")
- public class HelloWorld {
- @Inject
- private ServerRequest request;
- @Inject
- private ServerResponse response;
- @Inject
- @Named(JerseySupport.REQUEST_SPAN_CONTEXT)
- private SpanContext spanContext;
- @GET
- @Path("hello")
- public Response hello() {
- return Response.ok("Hello World !").build();
- }
- @POST
- @Path("hello")
- public Response hello(String content) {
- return Response.accepted("Hello:" + content + "!").build();
- }
- @POST
- @Path("content")
- public Response content(String content) {
- return Response.accepted(content).build();
- }
- @GET
- @Path("injection")
- public Response webServerInjection() {
- return Response.ok("request=" + request.getClass().getName()
- + "\nresponse=" + response.getClass().getName()
- + "\nspanContext=" + spanContext.getClass().getName()).build();
- }
- @GET
- @Path("headers")
- public Response headers(@Context HttpHeaders headers, @QueryParam("header") String header) {
- return Response.ok("headers=" + headers.getRequestHeader(header).stream().collect(Collectors.joining(",")))
- .build();
- }
- @GET
- @Path("query")
- public Response query(@QueryParam("a") String a, @QueryParam("b") String b) {
- return Response.accepted("a='" + a + "';b='" + b + "'").build();
- }
- @GET
- @Path("path/{num}")
- public Response path(@PathParam("num") String num) {
- return Response.accepted("num=" + num).build();
- }
- @GET
- @Path("requestUri")
- public String getRequestUri(@Context UriInfo uriInfo) {
- return uriInfo.getRequestUri().getPath();
- }
- }
启动服务
- package com.souyunku.helidon.webserver.examples.jersey;
- import io.helidon.webserver.Routing;
- import io.helidon.webserver.ServerConfiguration;
- import io.helidon.webserver.WebServer;
- import io.helidon.webserver.jersey.JerseySupport;
- import org.glassfish.jersey.server.ResourceConfig;
- import java.io.IOException;
- import java.util.concurrent.CompletionStage;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.TimeoutException;
- import java.util.logging.LogManager;
- /**
- * WebServer Jersey
- */
- public final class WebServerJerseyMain {
- private WebServerJerseyMain() {
- }
- /**
- * 运行 Jersey WebServer 示例.
- *
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException {
- // 配置日志记录, 以避免标准的 JVM 默认设置
- LogManager.getLogManager().readConfiguration(WebServerJerseyMain.class.getResourceAsStream("/logging.properties"));
- // 最简单方法启动在 8080 端口
- startServer(ServerConfiguration.builder()
- .port(8080)
- .build());
- }
- static CompletionStage<WebServer> startServer(ServerConfiguration serverConfiguration) {
- WebServer webServer = WebServer.create(
- serverConfiguration,
- Routing.builder()
- // 在 / jersey 上下文根目录注册 Jersey 应用程序
- .register("/jersey",
- JerseySupport.create(new ResourceConfig(HelloWorld.class)))
- .build());
- return webServer.start()
- .whenComplete((server, t) -> {
- System.out.println("Jersey WebServer started.");
- System.out.println("Try the hello world resource at: http://localhost:" + server.port() + "/jersey/hello");
- });
- // http://localhost:8080/jersey/hello
- }
- }
响应:
- Jersey WebServer started.
- Try the hello world resource at: http://localhost:8080/jersey/hello
测试
浏览器访问
http://localhost:8080/jersey/hello
响应:
Hello World !
带参数访问
http://localhost:8080/jersey/query?a=www.souyunku.com&b=www.ymq.io
响应:
a='http://www.souyunku.com';b='http://www.ymq.io'
更多就不演示了
调用链监控 Zipkin
WebServer 包括 Zipkin 对 OpenTracing 的支持. 启用后, WebServer 会将其跟踪事件发送到 Zipkin.
Maven 坐标
WebServer Zipkin 支持依赖
- <dependency>
- <groupId>io.helidon.webserver</groupId>
- <artifactId>helidon-webserver-zipkin</artifactId>
- </dependency>
配置跟踪支持
要启用 Zipkin 集成, 请 Tracer 在上 配置 ServerConfiguration.Builder.
zipkin 是一个开放源代码分布式的跟踪系统, 由 Twitter 公司开源, 它致力于收集服务的定时数据, 以解决微服务架构中的延迟问题, 包括数据的收集, 存储, 查找和展现. 它的理论模型来自于 Google Dapper 论文.
配置 OpenTracing Tracer
- ServerConfiguration.builder()
- .tracer(new ZipkinTracerBuilder.forService("my-application")
- .zipkin("http://10.0.0.18:9411")
- .build())
- .build()
官方文档:
https://helidon.io/docs/latest/
Helidon 的 GitHub 项目地址:
https://github.com/oracle/helidon
本文测试代码
GitHub:
往期精彩文章
如何找到完美的以太坊区块链开发者 https://mp.weixin.qq.com/s/q4G2iaorMaY9OVURPEGe9g
大数据推荐系统实时架构和离线架构
Elasticsearch 优化会员列表搜索
Rabbitmq 延迟队列实现定时任务
软件做异常测试? 必知的 22 个测试点总结!
Java SQL 注入危害这么大, 该如何来防止呢?
还没用上 JDK 11 吧, JDK 12 早期访问构建版使用
Dubbo 整合 Pinpoint 做分布式服务请求跟踪
Java 并发: 分布式应用限流实践
来源: https://juejin.im/post/5bc540975188255c6b653b8b