<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          只會用 Spring Boot 創(chuàng)建微服務(wù)?這 4 種替代方案絕了!

          共 28234字,需瀏覽 57分鐘

           ·

          2022-11-01 10:53

          點擊關(guān)注公眾號,Java干貨及時送達(dá)??

          來源:www.kubernetes.org.cn/9526.html

          • 前言
          • 先決條件
          • 從頭開始創(chuàng)建應(yīng)用程序
          • Helidon服務(wù)
          • Ktor服務(wù)
          • Micronaut 服務(wù)
          • Quarkus服務(wù)
          • Spring Boot服務(wù)
          • 啟動微服務(wù)
          • API測試
          • 不同微服務(wù)框架對比
            • 程序大小
            • 啟動時長
            • 內(nèi)存使用情況
          • 結(jié)論
            • Helidon標(biāo)準(zhǔn)版
            • Helidon MicroProfile
            • Ktor
            • Micronaut
            • Quarkus
            • Spring Boot

          前言

          在 Java 和 Kotlin 中, 除了使用Spring Boot創(chuàng)建微服務(wù)外,還有很多其他的替代方案。

          圖片

          本文,基于這些微服務(wù)框架,創(chuàng)建了五個服務(wù),并使用Consul的服務(wù)發(fā)現(xiàn)模式實現(xiàn)服務(wù)間的 相互通信。因此,它們形成了異構(gòu)微服務(wù)架構(gòu)(Heterogeneous Microservice Architecture, 以下簡稱 MSA):

          圖片

          本文簡要考慮了微服務(wù)在各個框架上的實現(xiàn)(更多細(xì)節(jié)請查看源代碼:https : //github.com/rkudryashov/heterogeneous-microservices

          • 技術(shù)棧:
          • JDK 13
          • Kotlin
          • Gradle (Kotlin DSL)
          • JUnit 5
          • 功能接口(HTTP API):
          • GET /application-info{?request-to=some-service-name}
          • GET /application-info/logo
          • 實現(xiàn)方式:
          • 使用文本文件的配置方式
          • 使用依賴注入
          • HTTP API
          • MSA:
          • 使用服務(wù)發(fā)現(xiàn)模式(在Consul中注冊,通過客戶端負(fù)載均衡的名稱請求另一個微服務(wù)的HTTP API)
          • 構(gòu)建一個 uber-JAR

          先決條件

          • JDK 13
          • Consul

          從頭開始創(chuàng)建應(yīng)用程序

          要基于其中一個框架上生成新項目,你可以使用web starter 或其他選項(例如,構(gòu)建工具或 IDE):

          圖片

          Helidon服務(wù)

          該框架是在 Oracle 中創(chuàng)建以供內(nèi)部使用,隨后成為開源。Helidon 非常簡單和快捷,它提供了兩個版本:標(biāo)準(zhǔn)版(SE)和MicroProfile(MP)。在這兩種情況下,服務(wù)都是一個常規(guī)的 Java SE 程序。(在Helidon上了解更多信息)

          Helidon MP 是 Eclipse MicroProfile的實現(xiàn)之一,這使得使用許多 API 成為可能,包括 Java EE 開發(fā)人員已知的(例如 JAX-RS、CDI等)和新的 API(健康檢查、指標(biāo)、容錯等)。在 Helidon SE 模型中,開發(fā)人員遵循“沒有魔法”的原則,例如,創(chuàng)建應(yīng)用程序所需的注解數(shù)量較少或完全沒有。

          Helidon SE 被選中用于微服務(wù)的開發(fā)。因為Helidon SE 缺乏依賴注入的手段,因此為此使用了Koin。

          以下代碼示例,是包含 main 方法的類。為了實現(xiàn)依賴注入,該類繼承自KoinComponent。

          首先,Koin 啟動,然后初始化所需的依賴并調(diào)用startServer()方法—-其中創(chuàng)建了一個WebServer類型的對象,應(yīng)用程序配置和路由設(shè)置傳遞到該對象;

          啟動應(yīng)用程序后在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()  

          該應(yīng)用程序使用HOCON格式的配置文件:

          webserver {  
            port: 8081  
          }  
            
          application-info {  
            name: "helidon-service"  
            framework {  
              name: "Helidon SE"  
              release-year: 2019  
            }  
          }  

          還可以使用 JSON、YAML 和properties 格式的文件進(jìn)行配置(在Helidon 配置文檔中了解更多信息)。

          Ktor服務(wù)

          該框架是為 Kotlin 編寫和設(shè)計的。和 Helidon SE 一樣,Ktor 沒有開箱即用的 DI,所以在啟動服務(wù)器依賴項之前應(yīng)該使用 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)  
          }  

          應(yīng)用程序需要的模塊在配置文件中指定(HOCON格式;更多配置信息參考Ktor配置文檔 ),其內(nèi)容如下:

          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 中,術(shù)語“模塊”具有不同的含義。

          在 Koin 中,模塊類似于 Spring 框架中的應(yīng)用程序上下文。Ktor的模塊是一個用戶定義的函數(shù),它接受一個 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")  
                      }  
                  }  
              }  
          }  

          此代碼是配置請求的路由,特別是靜態(tài)資源logo.png。

          下面是基于Round-robin算法結(jié)合客戶端負(fù)載均衡實現(xiàn)服務(wù)發(fā)現(xiàn)模式的代碼:

          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階段之前執(zhí)行)首先確定被調(diào)用服務(wù)的名稱,然后consulClient請求服務(wù)的實例列表,然后通過循環(huán)算法定義一個實例正在調(diào)用。因此,以下調(diào)用成為可能:

          fun getApplicationInfo(serviceName: String): ApplicationInfo = runBlocking {  
              httpClient.get<ApplicationInfo>("http://$serviceName/application-info")  
          }  

          Micronaut 服務(wù)

          Micronaut 由Grails框架的創(chuàng)建者開發(fā),靈感來自使用 Spring、Spring Boot 和 Grails 構(gòu)建服務(wù)的經(jīng)驗。該框架目前支持 Java、Kotlin 和 Groovy 語言。依賴是在編譯時注入的,與 Spring Boot 相比,這會導(dǎo)致更少的內(nèi)存消耗和更快的應(yīng)用程序啟動。

          主類如下所示:

          object MicronautServiceApplication {  
            
              @JvmStatic  
              fun main(args: Array<String>) {  
                  Micronaut.build()  
                      .packages("io.heterogeneousmicroservices.micronautservice")  
                      .mainClass(MicronautServiceApplication.javaClass)  
                      .start()  
              }  
          }  

          基于 Micronaut 的應(yīng)用程序的某些組件與它們在 Spring Boot 應(yīng)用程序中的對應(yīng)組件類似,例如,以下是控制器代碼:

          @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編譯器插件的基礎(chǔ)上(參考Micronaut Kotlin 指南了解更多詳細(xì)信息)。

          構(gòu)建腳本配置如下:

          plugins {  
              ...  
              kotlin("kapt")  
              ...  
          }  
            
          dependencies {  
              kapt("io.micronaut:micronaut-inject-java:$micronautVersion")  
              ...  
              kaptTest("io.micronaut:micronaut-inject-java:$micronautVersion")  
              ...  
          }  

          以下是配置文件的內(nèi)容:

          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 配置指南查看更多詳細(xì)信息)。

          Quarkus服務(wù)

          Quarkus是作為一種應(yīng)對新部署環(huán)境和應(yīng)用程序架構(gòu)等挑戰(zhàn)的工具而引入的,在框架上編寫的應(yīng)用程序?qū)⒕哂械蛢?nèi)存消耗和更快的啟動時間。此外,對開發(fā)人員也很友好,例如,開箱即用的實時重新加載。

          Quarkus 應(yīng)用程序目前沒有 main 方法,但也許未來會出現(xiàn)(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(  
              ...  
          ) {  
          ...  
          }  

          為其他服務(wù)創(chuàng)建 REST 接口,就像使用 JAX-RS 和 MicroProfile 創(chuàng)建接口一樣簡單:

          @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  

          但是它現(xiàn)在缺乏對服務(wù)發(fā)現(xiàn) ( Eureka和Consul ) 的內(nèi)置支持,因為該框架主要針對云環(huán)境。因此,在 Helidon 和 Ktor 服務(wù)中, 我使用了Java類庫方式的Consul 客戶端。

          首先,需要注冊應(yīng)用程序:

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

          然后需要將服務(wù)的名稱解析到其特定位置;

          解析是通過從 Consul 客戶端獲得的服務(wù)的位置替換 requestContext的URI 來實現(xiàn)的:

          @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 文件進(jìn)行配置(參考Quarkus 配置指南了解更多詳細(xì)信息)。

          Spring Boot服務(wù)

          創(chuàng)建該框架是為了使用 Spring Framework 生態(tài)系統(tǒng),同時有利于簡化應(yīng)用程序的開發(fā)。這是通過auto-configuration實現(xiàn)的。

          以下是控制器代碼:

          @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()  
          }  

          微服務(wù)由 YAML 文件配置:

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

          也可以使用properties文件進(jìn)行配置(更多信息參考Spring Boot 配置文檔)。

          啟動微服務(wù)

          在啟動微服務(wù)之前,你需要安裝Consul和 啟動代理-例如,像這樣:consul agent -dev。

          你可以從以下位置啟動微服務(wù):

          IDE中啟動微服務(wù)IntelliJ IDEA 的用戶可能會看到如下內(nèi)容:

          圖片

          要啟動 Quarkus 服務(wù),你需要啟動quarkusDev的Gradle 任務(wù)。

          console中啟動微服務(wù)在項目的根文件夾中執(zhí)行:

          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

          啟動所有微服務(wù)后,訪問http://localhost:8500/ui/dc1/services,你將看到:

          圖片

          API測試

          以Helidon服務(wù)的API測試結(jié)果為例:

          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 客戶端 、瀏覽器或其他工具測試微服務(wù)的 API接口 。

          不同微服務(wù)框架對比

          不同微服務(wù)框架的新版本發(fā)布后,下面的結(jié)果可能會有變化;你可以使用此GitHub項目自行檢查最新的對比結(jié)果 。

          另外,微服務(wù)系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺發(fā)送:面試,可以在線閱讀。

          程序大小

          為了保證設(shè)置應(yīng)用程序的簡單性,構(gòu)建腳本中沒有排除傳遞依賴項,因此 Spring Boot 服務(wù) uber-JAR 的大小大大超過了其他框架上的類似物的大小(因為使用 starters 不僅導(dǎo)入了必要的依賴項;如果需要,可以通過排除指定依賴來減小大?。?/p>

          備注:什么是 maven的uber-jar

          在maven的一些文檔中我們會發(fā)現(xiàn) “uber-jar”這個術(shù)語,許多人看到后感到困惑。其實在很多編程語言中會把super叫做uber (因為super可能是關(guān)鍵字), 這是上世紀(jì)80年代開始流行的,比如管superman叫uberman。所以uber-jar從字面上理解就是super-jar,這樣的jar不但包含自己代碼中的class ,也會包含一些第三方依賴的jar,也就是把自身的代碼和其依賴的jar全打包在一個jar里面了,所以就很形象的稱其為super-jar ,uber-jar來歷就是這樣的。

          圖片

          啟動時長

          每個應(yīng)用程序的啟動時長都是不固定的:

          圖片

          值得注意的是,如果你將 Spring Boot 中不必要的依賴排除,并注意設(shè)置應(yīng)用的啟動參數(shù)(例如,只掃描必要的包并使用 bean 的延遲初始化),那么你可以顯著地減少啟動時間。

          內(nèi)存使用情況

          對于每個微服務(wù),確定了以下內(nèi)容:

          • 通過-Xmx參數(shù),指定微服務(wù)所需的堆內(nèi)存大小
          • 通過負(fù)載測試服務(wù)健康的請求(能夠響應(yīng)不同的請求)
          • 通過負(fù)載測試50 個用戶 * 1000 個的請求
          • 通過負(fù)載測試500 個用戶 * 1000 個的請求

          堆內(nèi)存只是為應(yīng)用程序分配的總內(nèi)存的一部分。例如,如果要測量總體內(nèi)存使用情況,可以參考本指南。

          對于負(fù)載測試,使用了Gatling和Scala腳本 。

          1、負(fù)載生成器和被測試的服務(wù)在同一臺機器上運行(Windows 10、3.2 GHz 四核處理器、24 GB RAM、SSD)。

          2、服務(wù)的端口在 Scala 腳本中指定。

          3、通過負(fù)載測試意味著微服務(wù)已經(jīng)響應(yīng)了所有時間的所有請求。

          圖片

          需要注意的是,所有微服務(wù)都使用 Netty HTTP 服務(wù)器。

          結(jié)論

          通過上文,我們所需的功能——一個帶有 HTTP API 的簡單服務(wù)和在 MSA 中運行的能力——在所有考慮的框架中都取得了成功。

          是時候開始盤點并考慮他們的利弊了。

          Helidon標(biāo)準(zhǔn)版

          優(yōu)點

          創(chuàng)建的應(yīng)用程序,只需要一個注釋(@JvmStatic)

          缺點

          開發(fā)所需的一些組件缺少開箱即用(例如,依賴注入和與服務(wù)發(fā)現(xiàn)服務(wù)器的交互)

          Helidon MicroProfile

          微服務(wù)還沒有在這個框架上實現(xiàn),所以這里簡單說明一下。

          優(yōu)點

          1、Eclipse MicroProfile 實現(xiàn)

          2、本質(zhì)上,MicroProfile 是針對 MSA 優(yōu)化的 Java EE。因此,首先你可以訪問各種 Java EE API,包括專門為 MSA 開發(fā)的 API,其次,你可以將 MicroProfile 的實現(xiàn)更改為任何其他實現(xiàn)(例如:Open Liberty、WildFly Swarm 等)

          Ktor

          優(yōu)點

          1、輕量級的允許你僅添加執(zhí)行任務(wù)直接需要的那些功能

          2、應(yīng)用參數(shù)所有參數(shù)的良好結(jié)果

          缺點

          1、依賴于Kotlin,即用其他語言開發(fā)可能是不可能的或不值得的

          2、微框架:參考Helidon SE

          3、目前最流行的兩種 Java 開發(fā)模型(Spring Boot/Micronaut)和 Java EE/MicroProfile)

          4、中沒有包含該框架,這會導(dǎo)致:

          • 難以尋找專家
          • 由于需要顯式配置所需的功能,因此與 Spring Boot 相比,執(zhí)行任務(wù)的時間有所增加

          Micronaut

          優(yōu)點

          1、AOT如前所述,與 Spring Boot 上的模擬相比,AOT 可以減少應(yīng)用程序的啟動時間和內(nèi)存消耗

          2、類Spring開發(fā)模式有 Spring 框架經(jīng)驗的程序員不會花太多時間來掌握這個框架

          3、Micronaut for Spring可以改變現(xiàn)有的Spring Boot應(yīng)用程序的執(zhí)行環(huán)境到Micronaut中(有限制)

          Quarkus

          優(yōu)點

          1、Eclipse MicroProfile 的實現(xiàn)

          2、該框架為多種 Spring 技術(shù)提供了兼容層:DI、 Web、Security、Data JPA

          Spring Boot

          優(yōu)點

          1、平臺成熟度和生態(tài)系統(tǒng)對于大多數(shù)日常任務(wù),Spring的編程范式已經(jīng)有了解決方案,也是很多程序員習(xí)慣的方式。此外,starter和auto-configuration的概念簡化了開發(fā)

          2、專家多,文檔詳細(xì)

          我想很多人都會同意 Spring 在不久的將來仍將是 Java/Kotlin開發(fā)領(lǐng)域領(lǐng)先的框架。

          缺點

          • 應(yīng)用參數(shù)多且復(fù)雜但是,有些參數(shù),如前所述,你可以自己優(yōu)化。還有一個Spring Fu項目的存在,該項目正在積極開發(fā)中,使用它可以減少參數(shù)。

          Helidon SE 和 Ktor 是 微框架,Spring Boot 和 Micronaut 是全??蚣?,Quarkus 和 Helidon MP 是 MicroProfile 框架。微框架的功能有限,這會減慢開發(fā)速度。

          我不敢判斷這個或那個框架會不會在近期“大更新”,所以在我看來,目前最好繼續(xù)觀察,使用熟悉的框架解決工作問題。

          同時,如本文所示,新框架在應(yīng)用程序參數(shù)設(shè)置方面贏得了 Spring Boot。如果這些參數(shù)中的任何一個對你的某個微服務(wù)至關(guān)重要,那么也許值得關(guān)注。

          但是,我們不要忘記,Spring Boot 一是在不斷改進(jìn),二是它擁有龐大的生態(tài)系統(tǒng),并且有相當(dāng)多的 Java 程序員熟悉它。此外,還有未涉及的其他框架:Vert.x、Javalin 等,也值得關(guān)注。

          原文:https://dzone.com/articles/not-only-spring-boot-a-review-of-alternatives

          譯文:https://www.kubernetes.org.cn/9526.html

          1. 三種跨域解決方案:HttpClient、注解、網(wǎng)關(guān)

          2. 這五款牛逼的 IDEA 插件,堪稱代碼質(zhì)量檢查利器!

          3. ULID - 一種比UUID更好的方案

          4. Nacos、Apollo、Config配置中心如何選型?這10個維度告訴你!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號平臺更改了推送規(guī)則,如果不想錯過內(nèi)容,記得讀完點一下在看,加個星標(biāo),這樣每次新文章推送才會第一時間出現(xiàn)在你的訂閱列表里。

          “在看”支持小哈呀,謝謝啦

          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一本色道久久综合无码人妻四虎 | 91 国产 爽 黄 在线 | 超碰人人摸人人操 | 蜜桃秘 av无码一区二区三区 | 亚洲区色情区激情区小说纯熟调抖 |