当前位置: 首页 > 工具软件 > Helidon > 使用案例 >

Oracle微服务框架 Helidon尝鲜(一)!~

端木存
2023-12-01

前言


晚上下班回家无聊看掘金Gayhub今日热门项目排行,突然瞄到一个有点意思关于微服务的项目。话说微服务框架在后端开发领域早已不是一个新的东西了,尤其是在框架这么多的Java平台,以spring boot为基础的构建的Spring cloud微服务框架基本已经成了不二选择。但是为啥我还会关注这个叫做英文名“Helidon”,中文名 “希利顿”的项目呢?还不是因为对微服务领域有着浓厚的兴趣(ps:很假吧,其实还是被oracle那略显土气红色logo吸引住了!)

框架特性


1.简单迅速

Helidon从设计的角度出发,高效易用,通过简单的Demo例子就能快速上手。由于Helidon它只是一个运行在高性能 Netty内核上的库的集合,所以它并没有其他过多的额外性能开销与设计上的臃肿。

2.支持MicroProfile

HelIdon支持 MicroProfile,并且提供了开发者熟悉的API,如JAX-RS、CDI和JSON-P/B。(ps:不熟悉也没啥关系),官方的MicroProfile实现了在自己的Helidon Reactive WebServer环境上快速运行。

3.Reactive WebServer (响应式web服务)

Helidon Reactive WebServer提供了一个运行在Netty内核上现代的函数式编程模型, HelIDon WebServer具有轻量级、灵活和响应式的提点,为当下流行的微服务提供了一个简单易用与快速构建的基础。如果熟悉的spring web flux 的话应该比较好理解这个了。

Helidon提供如下两种编程模式

  • Helidon MP: MicroProfile 1.1 plus Health Check and Metrics
  • Helidon SE: a small, functional style API

4.可观察性与服务弹性

Helidon提供服务健康检查、应用监控、链路追终与容错,可以通过接入Prometheus(监控)、 Zipkin(链路追踪) 、 Kubernetes来构建Helidon云应用。

快速入门


bb了那么久,不赶紧上手一波怎么行~

1.环境搭建 (Helidon SE)

1.1 创建一个 maven 工程,目录结构如下图:

1.2 在 pom.xml 文件中添加如下依赖:

这是直接采用官方提供的dependencyManagement配置,这样就不需要给每个Helidon组件提供具体的依赖版本了!!

	<dependencies>
		<!-- helidon webserver 依赖 -->
		<dependency>
			<groupId>io.helidon.webserver</groupId>
			<artifactId>helidon-webserver-bundle</artifactId>
		</dependency>
		<!-- helidon 读取配置 少了这个依赖无法读取到yaml中的配置哦!!! -->
		<dependency>
			<groupId>io.helidon.config</groupId>
			<artifactId>helidon-config-bundle</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>8</source>
					<target>8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>io.helidon</groupId>
				<artifactId>helidon-bom</artifactId>
				<version>0.9.1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
复制代码

1.3 创建目录和配置文件:

在src/main/resources 目录下创建application.yaml,logging.properties文件:

  • application.yaml : 用于配置项目运行所需的配置数据 (同spring boot一样,应用启动时会在类路径加载这个配置文件) 同样也支持application.conf、application.json、application.properties这几种格式。(不过还是建议使用yaml吧)
# web server 配置 
server:
    # 服务端口
    port: 8080 
    # 服务主机
    host: 0.0.0.0

# 自定义配置
app:
  greeting: "Hello"
复制代码

具体配置可参考:官方配置指南

  • logging.properties : 日志文件配置

# 控制台输出输出
handlers=java.util.logging.ConsoleHandler

# 定义全局日志级别,可以通过指定的handlers、loggers覆盖
.level=INFO

# Helidon Web Server has a custom log formatter that extends SimpleFormatter.
# It replaces "!thread!" with the current thread name
# Helidon Web Server 有一个自定义的格式化类 :io.helidon.webserver.netty.WebServerLogFormatter 用当前线程名正则表达式替换 “!thread!”

java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=io.helidon.webserver.netty.WebServerLogFormatter
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n

#组件定制日志级别
#io.helidon.webserver.level=INFO
#io.helidon.config.level=INFO
#io.helidon.security.level=INFO
#io.helidon.common.level=INFO
#io.netty.level=INFO

复制代码

1.4.1 创建启动类(其实就是一个主类main):

    /**
     * 防止实例化此类
     */
    private Main() { }

    /**
     * 创建路由
     *
     * @return the new instance
     */
    private static Routing createRouting() {
        return Routing.builder()
                //添加json返回支持
                .register(JsonSupport.get())
                .register("/greet", new GreetService())
                .build();
    }


    public static void main(final String[] args) throws IOException {
		// 加载日志配置
		LogManager.getLogManager().readConfiguration(
				Main.class.getResourceAsStream("/logging.properties"));

		//默认会从类路径加载 application.yaml 配置文件
		Config config = Config.create();

		//获取application.yaml中 “server”部分webserver相关配置
		ServerConfiguration serverConfig =
				ServerConfiguration.fromConfig(config.get("server"));

		//根据配置创建WebServer
		WebServer server = WebServer.create(serverConfig, createRouting());

		// Start the server and print some info.
		// 开启服务时打印一些内容
		server.start().thenAccept(ws -> System.out.println(
				"WEB server is up! http://localhost:" + ws.port()));

		// 服务停止时打印一些内容 ( 可以通过执行server.shutdown()关闭服务触发)
		server.whenShutdown().thenRun(()
				-> System.out.println("WEB server is DOWN. Good bye!"));

	}
复制代码

1.4.2 创建服务类(相当于spring mvc的contoller):


public class GreetService implements Service {
	/**
	 * 读取配置文件中的 “app”字段 部分配置
	 */
	private static final Config CONFIG = Config.create().get("app");

	/**
	 * 读取配置文件中 “app”下层属性“greeting”字段属性值
	 */
	private static String greeting = CONFIG.get("greeting").asString("Hello xs");

	/**
	 * 定义当前Service 路由规则
	 */
	@Override
	public final void update(final Routing.Rules rules) {
		rules
				.get("/", this::getDefaultMessage)
				.get("/{name}", this::getMessage)
				.put("/greeting/{greeting}", this::updateGreeting);
	}
	
	/**
	 * 测试: http://localhost:8080/greet/  (get 请求)
	 */
	private void getDefaultMessage(final ServerRequest request, final ServerResponse response) {
		String msg = String.format("%s %s!", greeting, "World");

		JsonObject returnObject = Json.createObjectBuilder()
				.add("message", msg)
				.build();
		response.send(returnObject);
	}
    
 	/**
	 * 测试: http://localhost:8080/greet/xs          (get 请求)
	 * 测试: http://localhost:8080/greet/xs?age=18   (get 请求)
	 */
	private void getMessage(final ServerRequest request, final ServerResponse response) {
		//获取问号后面的查询参数
		String age = request.queryParams().first("age").orElse("age 未提供!!!");
		//获取路径参数  
		String name = request.path().param("name");
		String msg =  name+": "+age;
		JsonObject returnObject = Json.createObjectBuilder()
				.add("message", msg)
				.build();
		response.send(returnObject);
	}

	/**
	 * 测试: http://localhost:8080/greet/xs?age=18  (put 请求)
	 */
	private void updateGreeting(final ServerRequest request,final ServerResponse response) {
		greeting = request.path().param("greeting");
		JsonObject returnObject = Json.createObjectBuilder()
				.add("greeting", greeting)
				.build();
		response.send(returnObject);
	}
}
复制代码

Helidon SE Restful 服务开发流程

  1. 主类加载配置(日志配置、web server 配置)
  2. 定义路由规则(service级别路由,相当于spring mvc类级别的RequestMapping),同时添加JSON支持
  3. 实现Service接口“update”方法定义当前Service路由规则(相当于spring mvc 方法级别的RequestMapping)
  4. 通过ServerRequest获取请求,ServerResponse响应请求, 进行业务开发。

踩坑系列

  1. 建议使用官方提供的dependencyManagement管理Helidon模块版本,避免之间的依赖问题。
  2. 一定要添加“helidon-config-bundle”相关依赖,否则无法读取yaml配置
  3. http响应方法response.send()入参其实是有限制的,想要返回json数据必须使用“JsonObject”对象,这里不像spring mvc 默认提供了Jackson json转换器,是不会把pojo自动转换成json字符串的。不过这个send方法是可以传String类型的参数的,因此可以通过引入外部库转成json字符串输出吧。(目前还没看到其他有效手段,毕竟大部分人都不会使用javax中的json库吧)

总结

总体来讲Helidon SE开发还算是比较轻松的,跟spring boot + spring web flux 十分类似。需要有一定java 8基础,懂得函数式编程、链式调用上手更快。从几年前android平台带火的 RxJava,到spring 5 提供的webflux,无一不表明以函数式编程为核心,响应式开发大有不断上升的趋势。建议java平台的小伙伴们,多多用用java8 提供的Steam API 配合Lambda 表达式进行一些日常开发吧。毕竟不用多久java 11 就要出来了!

转载于:https://juejin.im/post/5b99300af265da0ace211d22

 类似资料: