Ktor服务
该框架是为 Kotlin 编写和设计的。和 Helidon SE 一样,Ktor 没有开箱即用的 DI,所以在启动服务器依赖项之前应该使用 Koin 注入:
val koinModule = module { single { ApplicationInfoService(get(), get()) } single { ApplicationInfoProperties() } single { ServiceClient(get()) } single { Consul.builder().withUrl("https://localhost:8500").build() } } fun main(args: Array<String>) { startKoin { modules(koinModule) } val server = embeddedServer(Netty, commandLineEnvironment(args)) server.start(wait = true) } ———————————————— 版权声明:本文为CSDN博主「Java技术栈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/youanyyou/article/details/127651963
应用程序需要的模块在配置文件中指定(HOCON格式;更多配置信息参考Ktor配置文档 ),其内容如下:
ktor { deployment { host = localhost port = 8082 environment = prod // for dev purpose autoreload = true watch = [io.heterogeneousmicroservices.ktorservice] } application { modules = [io.heterogeneousmicroservices.ktorservice.module.KtorServiceApplicationModuleKt.module] } } application-info { name: "ktor-service" framework { name: "Ktor" release-year: 2018 } }
在 Ktor 和 Koin 中,术语“模块”具有不同的含义。
在 Koin 中,模块类似于 Spring 框架中的应用程序上下文。Ktor的模块是一个用户定义的函数,它接受一个 Application类型的对象,可以配置流水线、注册路由、处理请求等:
fun Application.module() { val applicationInfoService: ApplicationInfoService by inject() if (!isTest()) { val consulClient: Consul by inject() registerInConsul(applicationInfoService.get(null).name, consulClient) } install(DefaultHeaders) install(Compression) install(CallLogging) install(ContentNegotiation) { jackson {} } routing { route("application-info") { get { val requestTo: String? = call.parameters["request-to"] call.respond(applicationInfoService.get(requestTo)) } static { resource("/logo", "logo.png") } } } }
此代码是配置请求的路由,特别是静态资源logo.png。
下面是基于Round-robin算法结合客户端负载均衡实现服务发现模式的代码:
class ConsulFeature(private val consulClient: Consul) { class Config { lateinit var consulClient: Consul } companion object Feature : HttpClientFeature<Config, ConsulFeature> { var serviceInstanceIndex: Int = 0 override val key = AttributeKey<ConsulFeature>("ConsulFeature") override fun prepare(block: Config.() -> Unit) = ConsulFeature(Config().apply(block).consulClient) override fun install(feature: ConsulFeature, scope: HttpClient) { scope.requestPipeline.intercept(HttpRequestPipeline.Render) { val serviceName = context.url.host val serviceInstances = feature.consulClient.healthClient().getHealthyServiceInstances(serviceName).response val selectedInstance = serviceInstances[serviceInstanceIndex] context.url.apply { host = selectedInstance.service.address port = selectedInstance.service.port } serviceInstanceIndex = (serviceInstanceIndex + 1) % serviceInstances.size } } } }
主要逻辑在install方法中:在Render请求阶段(在Send阶段之前执行)首先确定被调用服务的名称,然后consulClient请求服务的实例列表,然后通过循环算法定义一个实例正在调用。因此,以下调用成为可能:
fun getApplicationInfo(serviceName: String): ApplicationInfo = runBlocking {
httpClient.get("http://$serviceName/application-info")
}
Micronaut 服务
Micronaut 由Grails框架的创建者开发,灵感来自使用 Spring、Spring Boot 和 Grails 构建服务的经验。该框架目前支持 Java、Kotlin 和 Groovy 语言。依赖是在编译时注入的,与 Spring Boot 相比,这会导致更少的内存消耗和更快的应用程序启动。
object MicronautServiceApplication { @JvmStatic fun main(args: Array<String>) { Micronaut.build() .packages("io.heterogeneousmicroservices.micronautservice") .mainClass(MicronautServiceApplication.javaClass) .start() } }
主类如下所示:
object MicronautServiceApplication { @JvmStatic fun main(args: Array<String>) { Micronaut.build() .packages("io.heterogeneousmicroservices.micronautservice") .mainClass(MicronautServiceApplication.javaClass) .start() } }
基于 Micronaut 的应用程序的某些组件与它们在 Spring Boot 应用程序中的对应组件类似,例如,以下是控制器代码:
@Controller( value = "/application-info", consumes = [MediaType.APPLICATION_JSON], produces = [MediaType.APPLICATION_JSON] ) class ApplicationInfoController( private val applicationInfoService: ApplicationInfoService ) { @Get fun get(requestTo: String?): ApplicationInfo = applicationInfoService.get(requestTo) @Get("/logo", produces = [MediaType.IMAGE_PNG]) fun getLogo(): ByteArray = applicationInfoService.getLogo() }
Micronaut 中对 Kotlin 的支持建立在kapt编译器插件的基础上(参考Micronaut Kotlin 指南了解更多详细信息)。
构建脚本配置如下:
plugins { ... kotlin("kapt") ... } dependencies { kapt("io.micronaut:micronaut-inject-java:$micronautVersion") ... kaptTest("io.micronaut:micronaut-inject-java:$micronautVersion") ... }
以下是配置文件的内容:
micronaut: application: name: micronaut-service server: port: 8083 consul: client: registration: enabled: true application-info: name: ${micronaut.application.name} framework: name: Micronaut release-year: 2018
JSON、properties和 Groovy 文件格式也可用于配置(参考Micronaut 配置指南查看更多详细信息)。