代码片段,一个简单的创建服务的例子。
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容器对象。如下示例:
其中的RetryPolicyConfigMapper 实现了配置文件读取的Retry Policies策略。当读取配置文件出现异常时,可以执行Rety策略,预定义的重试策略有两种:
(4)初始 ConfigFilter
看名字就知道是过滤配置参数的,源代码中的描述就是
Filter that can transform elementary configuration ({@code String}) values before they are returned via the {@link Config} API.
(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提供了相当有趣的配置文件管理方式,这一点值得其他微服务框架借鉴。后续继续介绍,其中的一些特性。