在 Java 和 Kotlin 中, 除了使用Spring Boot创建微服务外,还有很多其他的替代方案。
名称 |
版本 |
发布时间 |
开发商 |
GitHub |
Helidon SE |
1.4.1 |
2019年 |
甲骨文 |
链接 |
Ktor |
1.3.0 |
2018年 |
JetBrains |
链接 |
Micronaut |
1.2.9 |
2018年 |
Object Computing |
链接 |
Quarkus |
1.2.0 |
2019年 |
Red Hat |
链接 |
Spring Boot |
2.2.4 |
2014年 |
Pivotal |
链接 |
本文,基于这些微服务框架,创建了五个服务,并使用Consul的服务发现模式实现服务间的 相互通信。因此,它们形成了异构微服务架构(Heterogeneous Microservice Architecture, 以下简称 MSA):
本文简要考虑了微服务在各个框架上的实现(更多细节请查看源代码:https :
//github.com/rkudryashov/heterogeneous-microservices)
技术栈:
- JDK 13
- Kotlin
- Gradle (Kotlin DSL)
- JUnit 5
功能接口(HTTP API):
- — 返回logo信息
- — 返回微服务的一些基本信息(名称、框架、发布年份)
- GET /application-info{?request-to=some-service-name}
- GET /application-info/logo
- 实现方式:
- 使用文本文件的配置方式
- 使用依赖注入
- HTTP API
- MSA:
- 使用服务发现模式(在Consul中注册,通过客户端负载均衡的名称请求另一个微服务的HTTP API)
- 构建一个 uber-JAR
先决条件
- JDK 13
- Consul
从头开始创建应用程序
要基于其中一个框架上生成新项目,你可以使用web starter 或其他选项(例如,构建工具或 IDE):
名称 |
Web starter |
指南 |
支持的开发语言 |
Helidon |
链接(MP) |
链接(SE) 链接(MP) |
Java,Kotlin |
Ktor |
链接 |
链接 |
Kotlin |
Micronaut |
链接 |
链接 |
Groovy、Java、Kotlin |
Quarkus |
链接 |
链接 |
Java、Kotlin、Scala |
Spring Boot |
链接 |
链接 |
Groovy、Java、Kotlin |
Helidon服务
该框架是在 Oracle 中创建以供内部使用,随后成为开源。Helidon 非常简单和快捷,它提供了两个版本:标准版(SE)和MicroProfile(MP)。在这两种情况下,服务都是一个常规的 Java SE 程序。(在Helidon上了解更多信息)
Helidon MP 是 Eclipse MicroProfile的实现之一,这使得使用许多 API 成为可能,包括 Java EE 开发人员已知的(例如 JAX-RS、CDI等)和新的 API(健康检查、指标、容错等)。在 Helidon SE 模型中,开发人员遵循“没有魔法”的原则,例如,创建应用程序所需的注解数量较少或完全没有。
Helidon SE 被选中用于微服务的开发。因为Helidon SE 缺乏依赖注入的手段,因此为此使用了Koin。
以下代码示例,是包含 main 方法的类。为了实现依赖注入,该类继承自KoinComponent。
首先,Koin 启动,然后初始化所需的依赖并调用startServer()方法—-其中创建了一个WebServer类型的对象,应用程序配置和路由设置传递到该对象;
启动应用程序后在Consul注册:
object HelidonServiceApplication : KoinComponent {
@JvmStatic
fun main(args: Array<String>) {
val startTime = System.currentTimeMillis()
startKoin {
modules(koinModule)
}
val applicationInfoService: ApplicationInfoService by inject()
val consulClient: Consul by inject()
val applicationInfoProperties: ApplicationInfoProperties by inject()
val serviceName = applicationInfoProperties.name
startServer(applicationInfoService, consulClient, serviceName, startTime)
}
}
fun startServer(
applicationInfoService: ApplicationInfoService,
consulClient: Consul,
serviceName: String,
startTime: Long
): WebServer {
val serverConfig = ServerConfiguration.create(Config.create().get("webserver"))
val server: WebServer = WebServer
.builder(createRouting(applicationInfoService))
.config(serverConfig)
.build()
server.start().thenAccept { ws ->
val durationInMillis = Syste