Oracle 微服务 Helidon 源代码初探


Helidon 是一个用于编写微服务的 Java 框架,这些微服务运行在由 Netty 提供支持的快速 Web 内核上。
详见: https://helidon.io/docs/latest/#/about/01_introduction

由示例代码为入口由浅入深介绍Helidon一些技术特点

代码片段,一个简单的创建服务的例子。

  	protected static WebServer startServer() throws IOException {
        // load logging configuration
        LogManager.getLogManager().readConfiguration(
                Main.class.getResourceAsStream("/logging.properties"));

        // By default this will pick up application.yaml from the classpath
        Config config = Config.create();

        // Get webserver config from the "server" section of application.yaml
        ServerConfiguration serverConfig =
                ServerConfiguration.fromConfig(config.get("server"));

        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 threads are not demon. NO need to block. Just react.
        server.whenShutdown().thenRun(()
                -> System.out.println("WEB server is DOWN. Good bye!"));

        return server;
 	}

第一步: 读取日志配置

 // load logging configuration
       LogManager.getLogManager().readConfiguration(
                Main.class.getResourceAsStream("/logging.properties"));

第二步 读取配置文件

Helidon提供了灵活的配置文件读取策略,个人认为它对配置文件的读取提供相当强大的能力。下面是配置管理模块的架构图。
在这里插入图片描述

示例中初始化配置的代码:

// By default this will pick up application.yaml from the classpath
      Config config = Config.create();

看下Config源码片段,用的是的BuilderImpl 类的

	static Builder builder() {
        return new BuilderImpl();
	}
	static Config create() {
        return builder().build();
    }

其实就是 new BuilderImpl().build() 来读取默认配置。
BuilderImpl构造函数里提供的参数 可以结合上面的架构图一起来解读。如下图:
在这里插入图片描述

(1) 初始化ConfigSource,和 OverrideSource
一个配置文件就是一个ConfigSource,系统默认读取的配置文件名称如下。
在这里插入图片描述

OverrideSource是一种特殊的ConfigSource.源码中给出的解释为:
	  A config override setting provides an alternate, or overriding, value for a
	  config element based on the element's key. Implementations of this interface  	
	  furnish override settings as {@link OverrideData} objects.

配置文件中的每个配置都是按照类型来解析的,目前配置的类型分为以下几种:
在这里插入图片描述

(2) 初始化ConfigParser
目前支持的ConfigParser 包括PropertiesConfigParser和YamlConfigParser。也可以定制自己的配置解析工具,比如JSONParser.

(3)初始化ConfigMapper。ConfigMapper实体类可以将配置文件中的各种配置信息,映射到一个Java容器对象。如下示例:
在这里插入图片描述

ConfigMapper实例有以下几种。
在这里插入图片描述

其中的RetryPolicyConfigMapper 实现了配置文件读取的Retry Policies策略。当读取配置文件出现异常时,可以执行Rety策略,预定义的重试策略有两种:
在这里插入图片描述

(4)初始 ConfigFilter
看名字就知道是过滤配置参数的,源代码中的描述就是

 Filter that can transform elementary configuration ({@code String}) values before they are returned via the {@link Config} API.

目前支持Filter有以下几种:
在这里插入图片描述

(5)初始化changesExecutor。
使用线程池初始化系统配置,默认如下配置。

static final Executor DEFAULT_CHANGES_EXECUTOR = Executors.newCachedThreadPool(new ConfigThreadFactory("config"));

也可以自己定义一个线程池,用来并发解析配置文件。这也算是Helidon的特点之一,使用线程池解析配置文件,提高系统初始化的效率。这个线程池最终会传递给ProviderImpl,Provider是为配置文件上下环境,执行解析任务提供了一个执行环境。

第三步创建服务

	WebServer server = WebServer.create(serverConfig, createRouting());

(1)服务配置 ServerConfiguration
ServerConfiguration是从application.yaml文件解析出来的配置信息,包括端口号 port和Host。

server:
  port: 8090
  host: 0.0.0.0

从服务配置类ServerConfiguration ,可以看到主要的配置项有以下几个。
在这里插入图片描述
workersCount:处理http请求的线程数。默认是机器CPU 核心数乘以2.
Port:服务端口号,默认是0.这时会随机选择一个空闲的端口号。
这些参数都可以在 ServerConfiguration 类里面找到相应的描述。如果不配这些参数就会使用系统默认值。

(2) 路由信息配置Routing
请求路由信息配置功能都是依赖 Routing内部类Builder。他提供所有请求路由信息配置方式。
下面给出两个例子:

	例一:
	Routing.builder()
         .post("/foo/{}", JsonSupport.get())
         .post("/foo/bar") // It can use JSON structures
         .get("/foo/bar").build();  // It can NOT use JSON structures
	例二:
	Routing.builder()
           .register(JsonSupport.get())
           .register("/greet", new GreetService())
           .build();

JsonSupport 是一个继承了Service 和Handler 接口的实现类。他提供了读写JSON请求和响应的实现方式。
Service 和 Handler 功能是不一样的。Service负责定义各种路由策略。Handler则定义了处理请求和响应的逻辑。Builder 中 post ,get 等HTTP ACTION方法配置路由,需要实现Handler接口。

	@Override
        public Builder post(String pathPattern, Handler... requestHandlers) {
            delegate.post(pathPattern, requestHandlers);
            return this;
    }

Builder 中register 方法配置路由,需要实现Service 接口。

@Override
        public Builder register(Service... services) {
            delegate.register(services);
            return this;
        }

(3)服务实现类
服务类的接口是WebServer,目前只有一个实现类:NettyWebServer
WebServer 接口类内部已经实现了服务配置初始化,和路由初始化。具体服务运行逻辑还是在NettyWebServer中实现的。看下NettyWebServer服务起送接口 start 方法。使用了JDK1.8中提供的异步编程模型CompletableFuture类。关于这个类的功能描述上有许多的帖子可以参考
这里随便列两个。
https://www.jianshu.com/p/547d2d7761db
https://blog.csdn.net/u011726984/article/details/79320004

启动服务有两种方式:
一种是:使用实例代码中方式,WebServer server = WebServer.create(serverConfig, createRouting()) ;
第二种:使用Factory类,如下图:
在这里插入图片描述

第一种方式在创建ServerBootstrap隐式创建NioEventLoopGroup包括bossGroup 和workerGroup。
第二种方式是显示创建NioEventLoopGroup,如下图:NettyWebServer构造函数

在这里插入图片描述

待续

Helidon提供了相当有趣的配置文件管理方式,这一点值得其他微服务框架借鉴。后续继续介绍,其中的一些特性。

猜你喜欢

转载自blog.csdn.net/wenyushu/article/details/90108933