百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

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

ccwgpt 2024-09-21 13:50 32 浏览 0 评论

在 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 = System.currentTimeMillis() - startTime
    
            log.info("Startup completed in $durationInMillis ms. Service running at: http://localhost:" + ws.port())
    
            // register in Consul
    
            consulClient.agentClient().register(createConsulRegistration(serviceName, ws.port()))
    
        }
    
    
    
    
        return server
    

    路由配置如下:

    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 = 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<ApplicationInfo>("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()
    
        }
    
    }
    

    基于 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 配置指南查看更多详细信息)。

    Quarkus服务

    Quarkus是作为一种应对新部署环境和应用程序架构等挑战的工具而引入的,在框架上编写的应用程序将具有低内存消耗和更快的启动时间。此外,对开发人员也很友好,例如,开箱即用的实时重新加载。

    Quarkus 应用程序目前没有 main 方法,但也许未来会出现(GitHub 上的问题)。

    对于熟悉 Spring 或 Java EE 的人来说,Controller 看起来非常熟悉:

    @Path("/application-info")
    
    @Produces(MediaType.APPLICATION_JSON)
    
    @Consumes(MediaType.APPLICATION_JSON)
    
    class ApplicationInfoResource(
    
        @Inject private val applicationInfoService: ApplicationInfoService
    
    ) {
    
    
    
    
        @GET
    
        fun get(@QueryParam("request-to") requestTo: String?): Response =
    
            Response.ok(applicationInfoService.get(requestTo)).build()
    
    
    
    
        @GET
    
        @Path("/logo")
    
        @Produces("image/png")
    
        fun logo(): Response = Response.ok(applicationInfoService.getLogo()).build()
    
    }
    

    如你所见,bean 是通过@Inject注解注入的,对于注入的 bean,你可以指定一个范围,例如:

    @ApplicationScoped
    
    class ApplicationInfoService(
    
        ...
    
    ) {
    
    ...
    
    }
    

    为其他服务创建 REST 接口,就像使用 JAX-RS 和 MicroProfile 创建接口一样简单:

    @ApplicationScoped
    
    @Path("/")
    
    interface ExternalServiceClient {
    
        @GET
    
        @Path("/application-info")
    
        @Produces("application/json")
    
        fun getApplicationInfo(): ApplicationInfo
    
    }
    
    
    
    
    @RegisterRestClient(baseUri = "http://helidon-service")
    
    interface HelidonServiceClient : ExternalServiceClient
    
    
    
    
    @RegisterRestClient(baseUri = "http://ktor-service")
    
    interface KtorServiceClient : ExternalServiceClient
    
    
    
    
    @RegisterRestClient(baseUri = "http://micronaut-service")
    
    interface MicronautServiceClient : ExternalServiceClient
    
    
    
    
    @RegisterRestClient(baseUri = "http://quarkus-service")
    
    interface QuarkusServiceClient : ExternalServiceClient
    
    
    
    
    @RegisterRestClient(baseUri = "http://spring-boot-service")
    
    interface SpringBootServiceClient : ExternalServiceClient
    

    但是它现在缺乏对服务发现 ( Eureka和Consul ) 的内置支持,因为该框架主要针对云环境。因此,在 Helidon 和 Ktor 服务中, 我使用了Java类库方式的Consul 客户端。

    首先,需要注册应用程序:

    @ApplicationScoped
    
    class ConsulRegistrationBean(
    
        @Inject private val consulClient: ConsulClient
    
    ) {
    
    
    
    
        fun onStart(@Observes event: StartupEvent) {
    
            consulClient.register()
    
        }
    
    }
    

    然后需要将服务的名称解析到其特定位置;

    解析是通过从 Consul 客户端获得的服务的位置替换 requestContext的URI 来实现的:

    @Provider
    
    @ApplicationScoped
    
    class ConsulFilter(
    
        @Inject private val consulClient: ConsulClient
    
    ) : ClientRequestFilter {
    
    
    
    
        override fun filter(requestContext: ClientRequestContext) {
    
            val serviceName = requestContext.uri.host
    
            val serviceInstance = consulClient.getServiceInstance(serviceName)
    
            val newUri: URI = URIBuilder(URI.create(requestContext.uri.toString()))
    
                .setHost(serviceInstance.address)
    
                .setPort(serviceInstance.port)
    
                .build()
    
    
    
    
            requestContext.uri = newUri
    
        }
    
    }
    

    Quarkus也支持通过properties 或 YAML 文件进行配置(参考Quarkus 配置指南了解更多详细信息)。

    Spring Boot服务

    创建该框架是为了使用 Spring Framework 生态系统,同时有利于简化应用程序的开发。这是通过auto-configuration实现的。

    以下是控制器代码:

    @RestController
    
    @RequestMapping(path = ["application-info"], produces = [MediaType.APPLICATION_JSON_VALUE])
    
    class ApplicationInfoController(
    
        private val applicationInfoService: ApplicationInfoService
    
    ) {
    
    
    
    
        @GetMapping
    
        fun get(@RequestParam("request-to") requestTo: String?): ApplicationInfo = applicationInfoService.get(requestTo)
    
    
    
    
        @GetMapping(path = ["/logo"], produces = [MediaType.IMAGE_PNG_VALUE])
    
        fun getLogo(): ByteArray = applicationInfoService.getLogo()
    
    }
    

    微服务由 YAML 文件配置:

    spring:
    
      application:
    
        name: spring-boot-service
    
    
    
    
    server:
    
      port: 8085
    
    
    
    
    application-info:
    
      name: ${spring.application.name}
    
      framework:
    
        name: Spring Boot
    
        release-year: 2014
    

    也可以使用properties文件进行配置(更多信息参考Spring Boot 配置文档)。

    启动微服务

    在启动微服务之前,你需要安装Consul和 启动代理-例如,像这样:consul agent -dev。

    你可以从以下位置启动微服务:

    • IDE中启动微服务IntelliJ IDEA 的用户可能会看到如下内容:要启动 Quarkus 服务,你需要启动quarkusDev的Gradle 任务。
    • console中启动微服务在项目的根文件夹中执行:

    java -jar helidon-service/build/libs/helidon-service-all.jar

    java -jar ktor-service/build/libs/ktor-service-all.jar

    java -jar micronaut-service/build/libs/micronaut-service-all.jar

    java -jar quarkus-service/build/quarkus-service-1.0.0-runner.jar

    java -jar spring-boot-service/build/libs/spring-boot-service.jar

    启动所有微服务后,访问http://localhost:8500/ui/dc1/services,你将看到:

    API测试

    以Helidon服务的API测试结果为例:

    GET http://localhost:8081/application-info

    {  "name":"helidon-service",  "framework":{    "name":"Helidon SE",    "releaseYear":2019},  "requestedService":null}
    
    
    
    

    GET http://localhost:8081/application-info?request-to=ktor-service

    {
    
      "name": "helidon-service",
    
      "framework": {
    
        "name": "Helidon SE",
    
        "releaseYear": 2019
    
      },
    
      "requestedService": {
    
        "name": "ktor-service",
    
        "framework": {
    
              "name": "Ktor",
    
              "releaseYear": 2018
    
        },
    
        "requestedService": null
    
      }
    
    }
    

    GET http://localhost:8081/application-info/logo返回logo信息

    你可以使用Postman 、IntelliJ IDEA HTTP 客户端 、浏览器或其他工具测试微服务的 API接口 。

    不同微服务框架对比

    不同微服务框架的新版本发布后,下面的结果可能会有变化;你可以使用此GitHub项目自行检查最新的对比结果 。

    程序大小

    为了保证设置应用程序的简单性,构建脚本中没有排除传递依赖项,因此 Spring Boot 服务 uber-JAR 的大小大大超过了其他框架上的类似物的大小(因为使用 starters 不仅导入了必要的依赖项;如果需要,可以通过排除指定依赖来减小大小):

    备注:什么是 maven的uber-jar

    在maven的一些文档中我们会发现 “uber-jar”这个术语,许多人看到后感到困惑。其实在很多编程语言中会把super叫做uber (因为super可能是关键字), 这是上世纪80年代开始流行的,比如管superman叫uberman。所以uber-jar从字面上理解就是super-jar,这样的jar不但包含自己代码中的class ,也会包含一些第三方依赖的jar,也就是把自身的代码和其依赖的jar全打包在一个jar里面了,所以就很形象的称其为super-jar ,uber-jar来历就是这样的。

    微服务

    程序大小(MB)

    Helidon服务

    17,3

    Ktor服务

    22,4

    Micronaut 服务

    17,1

    Quarkus服务

    24,4

    Spring Boot服务

    45,2

    启动时长

    每个应用程序的启动时长都是不固定的:

    微服务

    开始时间(秒)

    Helidon服务

    2,0

    Ktor服务

    1,5

    Micronaut 服务

    2,8

    Quarkus服务

    1,9

    Spring Boot服务

    10,7

    值得注意的是,如果你将 Spring Boot 中不必要的依赖排除,并注意设置应用的启动参数(例如,只扫描必要的包并使用 bean 的延迟初始化),那么你可以显著地减少启动时间。

    内存使用情况

    对于每个微服务,确定了以下内容:

    • 通过-Xmx参数,指定微服务所需的堆内存大小
    • 通过负载测试服务健康的请求(能够响应不同的请求)
    • 通过负载测试50 个用户 * 1000 个的请求
    • 通过负载测试500 个用户 * 1000 个的请求

    堆内存只是为应用程序分配的总内存的一部分。例如,如果要测量总体内存使用情况,可以参考本指南。

    对于负载测试,使用了Gatling和Scala脚本 。

    1、负载生成器和被测试的服务在同一台机器上运行(Windows 10、3.2 GHz 四核处理器、24 GB RAM、SSD)。
    2、服务的端口在 Scala 脚本中指定。
    3、通过负载测试意味着微服务已经响应了所有时间的所有请求。
    

    微服务

    堆内存大小(MB)

    堆内存大小(MB)

    堆内存大小(MB)

    对于健康服务

    对于 50 * 1000 的负载

    对于 500 * 1000 的负载


    Helidon服务

    11

    9

    11

    Ktor服务

    13

    11

    15

    Micronaut 服务

    17

    15

    19

    Quarkus服务

    13

    17

    21

    Spring Boot服务

    18

    19

    23

    需要注意的是,所有微服务都使用 Netty HTTP 服务器。

    结论

    通过上文,我们所需的功能——一个带有 HTTP API 的简单服务和在 MSA 中运行的能力——在所有考虑的框架中都取得了成功。

    是时候开始盘点并考虑他们的利弊了。

    Helidon标准版

    优点

    创建的应用程序,只需要一个注释(@JvmStatic)

    缺点

    开发所需的一些组件缺少开箱即用(例如,依赖注入和与服务发现服务器的交互)

    Helidon MicroProfile

    微服务还没有在这个框架上实现,所以这里简单说明一下。

    优点

    1、Eclipse MicroProfile 实现
    2、本质上,MicroProfile 是针对 MSA 优化的 Java EE。因此,首先你可以访问各种 Java EE API,包括专门为 MSA 开发的 API,其次,你可以将 MicroProfile 的实现更改为任何其他实现(例如:Open Liberty、WildFly Swarm 等)
    

    Ktor

    优点

    1、轻量级的允许你仅添加执行任务直接需要的那些功能
    2、应用参数所有参数的良好结果
    

    缺点

    1、依赖于Kotlin,即用其他语言开发可能是不可能的或不值得的

    2、微框架:参考Helidon SE

    3、目前最流行的两种 Java 开发模型(Spring Boot/Micronaut)和 Java EE/MicroProfile)

    4、中没有包含该框架,这会导致:

    难以寻找专家

    由于需要显式配置所需的功能,因此与 Spring Boot 相比,执行任务的时间有所增加

    Micronaut

    优点

    1、AOT如前所述,与 Spring Boot 上的模拟相比,AOT 可以减少应用程序的启动时间和内存消耗
    2、类Spring开发模式有 Spring 框架经验的程序员不会花太多时间来掌握这个框架
    3、Micronaut for Spring可以改变现有的Spring Boot应用程序的执行环境到Micronaut中(有限制)
    

    Quarkus

    优点

    1、Eclipse MicroProfile 的实现
    2、该框架为多种 Spring 技术提供了兼容层:DI、 Web、Security、Data JPA
    

    Spring Boot

    优点

    1、平台成熟度和生态系统对于大多数日常任务,Spring的编程范式已经有了解决方案,也是很多程序员习惯的方式。此外,starter和auto-configuration的概念简化了开发
    2、专家多,文档详细
    

    我想很多人都会同意 Spring 在不久的将来仍将是 Java/Kotlin开发领域领先的框架。

    缺点

    • 应用参数多且复杂但是,有些参数,如前所述,你可以自己优化。还有一个Spring Fu项目的存在,该项目正在积极开发中,使用它可以减少参数。

    Helidon SE 和 Ktor 是 微框架,Spring Boot 和 Micronaut 是全栈框架,Quarkus 和 Helidon MP 是 MicroProfile 框架。微框架的功能有限,这会减慢开发速度。

    我不敢判断这个或那个框架会不会在近期“大更新”,所以在我看来,目前最好继续观察,使用熟悉的框架解决工作问题。

    同时,如本文所示,新框架在应用程序参数设置方面赢得了 Spring Boot。如果这些参数中的任何一个对你的某个微服务至关重要,那么也许值得关注。但是,我们不要忘记,Spring Boot 一是在不断改进,二是它拥有庞大的生态系统,并且有相当多的 Java 程序员熟悉它。此外,还有未涉及的其他框架:Vert.x、Javalin 等,也值得关注。

    原文链接:https://www.kubernetes.org.cn/9526.html

    相关推荐

    迈向群体智能 | 智源发布首个跨本体具身大小脑协作框架

    允中发自凹非寺量子位|公众号QbitAI3月29日,智源研究院在2025中关村论坛“未来人工智能先锋论坛”上发布首个跨本体具身大小脑协作框架RoboOS与开源具身大脑RoboBrain,可实...

    大模型对接微信个人号,极空间部署AstrBot机器人,万事不求百度

    「亲爱的粉丝朋友们好啊!今天熊猫又来介绍好玩有趣的Docker项目了,喜欢的记得点个关注哦!」引言前两天熊猫发过一篇关于如何在极空间部署AstrBot并对接QQ消息平台的文章,不过其实QQ现在已经很少...

    Seata,让分布式事务不再是难题!实战分享带你领略Seata的魅力!

    终身学习、乐于分享、共同成长!前言Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的...

    常见分布式事务解决方案(分布式事务解决的问题)

    1.两阶段提交(2PC)原理:分为准备阶段(协调者询问参与者是否可提交)和提交阶段(协调者根据参与者反馈决定提交或回滚)。优点:强一致性,适用于数据库层(如XA协议)。缺点:同步阻塞:所有参与者阻塞...

    分布式事务:从崩溃到高可用,程序员必须掌握的实战方案!

    “支付成功,但订单状态未更新!”、“库存扣减后,交易却回滚了!”——如果你在分布式系统中踩过这些“天坑”,这篇文章就是你的救命稻草!本文将手把手拆解分布式事务的核心痛点和6大主流解决方案,用代码实战+...

    谈谈对分布式事务的一点理解和解决方案

    分布式事务首先,做系统拆分的时候几乎都会遇到分布式事务的问题,一个仿真的案例如下:项目初期,由于用户体量不大,订单模块和钱包模块共库共应用(大war包时代),模块调用可以简化为本地事务操作,这样做只要...

    一篇教你通过Seata解决分布式事务问题

    1 Seata介绍Seata是由阿里中间件团队发起的开源分布式事务框架项目,依赖支持本地ACID事务的关系型数据库,可以高效并且对业务0侵入的方式解决微服务场景下面临的分布式事务问题,目前提供AT...

    Seata分布式事务详解(原理流程及4种模式)

    Seata分布式事务是SpringCloudAlibaba的核心组件,也是构建分布式的基石,下面我就全面来详解Seata@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合...

    分布式事务最终一致性解决方案有哪些?MQ、TCC、saga如何实现?

    JTA方案适用于单体架构多数据源时实现分布式事务,但对于微服务间的分布式事务就无能为力了,我们需要使用其他的方案实现分布式事务。1、本地消息表本地消息表的核心思想是将分布式事务拆分成本地事务进行处理...

    彻底掌握分布式事务2PC、3PC模型(分布式事务视频教程)

    原文:https://mp.weixin.qq.com/s/_zhntxv07GEz9ktAKuj70Q作者:马龙台工作中使用最多的是本地事务,但是在对单一项目拆分为SOA、微服务之后,就会牵扯出分...

    Seata分布式事务框架关于Annotation的SAGA模式分析

    SAGAAnnotation是ApacheSeata版本2.3.0中引入的功能,它提供了一种使用Java注解而不是传统的JSON配置或编程API来实现SAGA事务模式的声明...

    分布式事务,原理简单,写起来全是坑

    今天我们就一起来看下另一种模式,XA模式!其实我觉得seata中的四种不同的分布式事务模式,学完AT、TCC以及XA就够了,Saga不好玩,而且长事务本身就有很多问题,也不推荐使用。S...

    内存空间节约利器redis的bitmap(位图)应用场景有哪些你知道吗

    在前面我们分享过一次Redis常用数据结构和使用场景,文章对Redis基本使用做了一个简单的API说明,但是对于其中String类型中的bitmap(位图)我们需要重点说明一下,因为他的作用真的不容忽...

    分布式事务原理详解(图文全面总结)

    分布式事务是非常核心的分布式系统,也是大厂经常考察对象,下面我就重点详解分布式事务及原理实现@mikechen本文作者:陈睿|mikechen文章来源:mikechen.cc分布式事务分布式事务指的是...

    大家平时天天说的分布式系统到底是什么东西?

    目录从单块系统说起团队越来越大,业务越来越复杂分布式出现:庞大系统分而治之分布式系统所带来的技术问题一句话总结:什么是分布式系统设计和开发经验补充说明:中间件系统及大数据系统前言现在有很多Java技术...

    取消回复欢迎 发表评论: