竟然有5种微服务框架可以替代Spring Boot( 二 )

路由配置如下:
private fun createRouting(applicationInfoService: ApplicationInfoService) = Routing.builder().register(JacksonSupport.create()).get("/application-info", Handler { req, res ->val requestTo: String? = req.queryParams().first("request-to").orElse(null)res.status(Http.ResponseStatus.create(200)).send(applicationInfoService.get(requestTo))}).get("/application-info/logo", Handler { req, res ->res.headers().contentType(MediaType.create("image", "png"))res.status(Http.ResponseStatus.create(200)).send(applicationInfoService.getLogo())}).error(Exception::class.java) { req, res, ex ->log.error("Exception:", ex)res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send()}.build()该应用程序使用HOCON格式的配置文件:
webserver {port: 8081}application-info {name: "helidon-service"framework {name: "Helidon SE"release-year: 2019}}还可以使用 JSON、YAML 和properties 格式的文件进行配置(在Helidon 配置文档中了解更多信息) 。
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)}应用程序需要的模块在配置文件中指定(HOCON格式;更多配置信息参考Ktor配置文档 ),其内容如下:
ktor {deployment {host = localhostport = 8082environment = prod// for dev purposeautoreload = truewatch = [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 = 0override 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.hostval serviceInstances =feature.consulClient.healthClient().getHealthyServiceInstances(serviceName).responseval selectedInstance = serviceInstances[serviceInstanceIndex]context.url.apply {host = selectedInstance.service.addressport = selectedInstance.service.port}serviceInstanceIndex = (serviceInstanceIndex + 1) % serviceInstances.size}}}}主要逻辑在install方法中:在Render请求阶段(在Send阶段之前执行)首先确定被调用服务的名称,然后consulClient请求服务的实例列表,然后通过循环算法定义一个实例正在调用 。因此,以下调用成为可能:
fun getApplicationInfo(serviceName: String): ApplicationInfo = runBlocking {httpClient.get<ApplicationInfo>("http://$serviceName/application-info")}Micronaut 服务Micronaut 由Grails框架的创建者开发,灵感来自使用 Spring、Spring Boot 和 Grails 构建服务的经验 。该框架目前支持 Java、Kotlin 和 Groovy 语言 。依赖是在编译时注入的,与 Spring Boot 相比,这会导致更少的内存消耗和更快的应用程序启动 。
主类如下所示:
object MicronautServiceApplication {@JvmStaticfun main(args: Array<String>) {Micronaut.build().packages("io.heterogeneousmicroservices.micronautservice").mainClass(MicronautServiceApplication.javaClass).start()}}


推荐阅读