Not One Spring Boot: Tinjauan Alternatif



Saat ini tidak ada kekurangan kerangka kerja untuk membuat layanan microser di Jawa dan Kotlin. Artikel ini membahas hal-hal berikut:
JudulVersiTahun rilis pertamaPengembang
Helidon se1.1.12019Oracle
Ktor1.2.12018Otak Jet
Micronaut1.1.32018Komputasi objek
Boot musim semi2.1.52014Sangat penting

Berdasarkan mereka, empat layanan telah dibuat yang dapat berinteraksi satu sama lain melalui API HTTP menggunakan pola Penemuan Layanan yang diimplementasikan menggunakan Konsul . Dengan demikian, mereka membentuk arsitektur layanan mikro yang heterogen (pada tingkat kerangka kerja) (selanjutnya disebut sebagai ISA):



Tetapkan serangkaian persyaratan untuk setiap layanan:

  • tumpukan teknologi:
    • JDK 12;
    • Kotlin
    • Gradle (Kotlin DSL);
    • JUnit 5.

  • fungsionalitas (HTTP API):
    • GET /application-info{?request-to=some-service-name}
      Mengembalikan beberapa informasi dasar tentang layanan mikro (nama, kerangka kerja, tahun rilis kerangka kerja); ketika menentukan nama salah satu dari empat layanan microser di parameter request-to ke HTTP API-nya, permintaan serupa dijalankan yang mengembalikan informasi dasar;
    • GET /application-info/logo
      Mengembalikan gambar.

  • implementasi:
    • pengaturan menggunakan file konfigurasi;
    • Menggunakan injeksi ketergantungan
    • tes yang memverifikasi fungsionalitas API HTTP.

  • ISA:
    • menggunakan pola Penemuan Layanan (mendaftar dengan Konsul, mengakses API HTTP dari layanan Microsoft lainnya dengan namanya menggunakan penyeimbangan beban klien);
    • formasi artefak uber-jar.


Selanjutnya, kami mempertimbangkan implementasi layanan mikro pada masing-masing kerangka kerja dan membandingkan parameter aplikasi yang diterima.

Layanan Helidon


Kerangka pengembangan dibuat di Oracle untuk penggunaan internal, kemudian menjadi open-source. Ada dua model pengembangan berdasarkan kerangka kerja ini: Edisi Standar (SE) dan MicroProfile (MP). Dalam kedua kasus, layanan ini akan menjadi program Java SE biasa. Pelajari lebih lanjut tentang perbedaan pada halaman ini .

Singkatnya, Helidon MP adalah salah satu implementasi Eclipse MicroProfile , yang memungkinkan untuk menggunakan banyak API, keduanya sebelumnya dikenal oleh pengembang Java EE (misalnya, JAX-RS, CDI), dan yang lebih baru (Pemeriksaan Kesehatan, Metrik, Toleransi Kesalahan) dll.) Dalam varian Helidon SE, pengembang dipandu oleh prinsip "No magic", yang dinyatakan, khususnya, dalam sedikit atau tidak ada penjelasan yang diperlukan untuk membuat aplikasi.

Helidon SE dipilih untuk pengembangan layanan mikro. Antara lain, tidak memiliki alat untuk mengimplementasikan Dependency Injection, sehingga Koin digunakan untuk mengimplementasikan dependensi. Berikut ini adalah kelas yang berisi metode utama. Untuk mengimplementasikan Injeksi Ketergantungan, kelas mewarisi dari KoinComponent . Koin dimulai terlebih dahulu, kemudian dependensi yang diperlukan diinisialisasi dan metode startServer() dipanggil, di mana objek dari tipe WebServer dibuat, di mana konfigurasi aplikasi dan pengaturan perutean sebelumnya ditransfer setelah mulai aplikasi terdaftar di Konsul:

 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 } 

Routing dikonfigurasi sebagai berikut:

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

Aplikasi menggunakan konfigurasi dalam format HOCON :

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

Dimungkinkan juga untuk menggunakan file dalam format JSON, YAML dan properti untuk konfigurasi (lebih detail di sini ).

Layanan Ktor


Kerangka ini ditulis dalam Kotlin. Proyek baru dapat dibuat dengan beberapa cara: menggunakan sistem build, start.ktor.io atau plug-in untuk IntelliJ IDEA (selengkapnya di sini ).

Seperti Helidon SE, Ktor tidak memiliki DI di luar kotak, jadi dependensi diimplementasikan menggunakan Koin sebelum memulai server:

 val koinModule = module { single { ApplicationInfoService(get(), get()) } single { ApplicationInfoProperties() } single { ServiceClient(get()) } single { Consul.builder().withUrl("http://localhost:8500").build() } } fun main(args: Array<String>) { startKoin { modules(koinModule) } val server = embeddedServer(Netty, commandLineEnvironment(args)) server.start(wait = true) } 

Modul yang diperlukan oleh aplikasi ditentukan dalam file konfigurasi (dimungkinkan untuk hanya menggunakan format HOCON; lebih lanjut tentang mengkonfigurasi server Ktor di sini ), yang isinya disajikan di bawah ini:

 ktor { deployment { host = localhost port = 8082 watch = [io.heterogeneousmicroservices.ktorservice] } application { modules = [io.heterogeneousmicroservices.ktorservice.module.KtorServiceApplicationModuleKt.module] } } application-info { name: "ktor-service" framework { name: "Ktor" release-year: 2018 } 

Ktor dan Koin menggunakan istilah "modul", yang memiliki arti berbeda. Di Koin, modul adalah analog dari konteks aplikasi dalam Kerangka Kerja Musim Semi. Modul Ktor adalah fungsi yang ditentukan pengguna yang menerima objek bertipe Aplikasi dan dapat mengkonfigurasi pipa, mengatur fitur, mendaftarkan rute, memproses
permintaan, dll .:

 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") } } } } 

Dalam cuplikan kode ini, perutean permintaan dikonfigurasikan, khususnya, logo.png sumber daya statis.

Layanan Ktor dapat berisi fitur. Fitur adalah fungsi yang tertanam dalam jalur permintaan-respons ( DefaultHeaders, Compression, dan lainnya dalam contoh kode di atas). Dimungkinkan untuk mengimplementasikan fitur Anda sendiri, misalnya, kode di bawah ini menerapkan pola Penemuan Layanan dalam kombinasi dengan penyeimbangan beban klien berdasarkan pada algoritma 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 } } } } 

Logika utama ada di metode install : selama fase permintaan Render (yang berjalan sebelum fase Kirim ), nama layanan yang dipanggil pertama kali ditentukan, kemudian daftar instance layanan ini diminta dari consulClient , setelah itu instance ditentukan menggunakan algoritma Round-robin. Dengan demikian, panggilan berikut menjadi mungkin:

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


Layanan micronaut


Micronaut dikembangkan oleh pembuat kerangka kerja Grails dan terinspirasi oleh pengalaman membangun layanan menggunakan Spring, Spring Boot, dan Grails. Kerangka kerja ini adalah polyglot yang mendukung Java, Kotlin dan Groovy; mungkin akan ada dukungan untuk Scala. Ketergantungan injeksi dilakukan pada tahap kompilasi, yang mengarah pada konsumsi memori yang lebih sedikit dan startup aplikasi yang lebih cepat dibandingkan dengan Spring Boot.

Kelas utama memiliki bentuk berikut:

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

Beberapa komponen aplikasi berbasis Micronaut mirip dengan rekan-rekan mereka di aplikasi Boot Musim Semi, misalnya, kode pengontrol adalah sebagai berikut:

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

Dukungan Kotlin di Micronaut didasarkan pada plugin kompiler kapt ( info lebih lanjut di sini ). Script assembly dikonfigurasikan sebagai berikut:

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

Berikut ini adalah isi dari file konfigurasi:

 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 

Konfigurasi microservice juga dimungkinkan dengan JSON, properti, dan format file Groovy (lebih detail di sini ).

Layanan booting musim semi


Kerangka kerja ini dibuat untuk menyederhanakan pengembangan aplikasi menggunakan ekosistem Spring Framework. Ini dicapai melalui mekanisme konfigurasi otomatis saat menghubungkan perpustakaan. Berikut ini adalah kode pengontrol:

 @RestController @RequestMapping(path = ["application-info"], produces = [MediaType.APPLICATION_JSON_UTF8_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() } 

Layanan microsoft dikonfigurasikan dengan file YAML:

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

Dimungkinkan juga untuk menggunakan file format properti untuk konfigurasi (lebih detail di sini ).

Luncurkan


Proyek ini bekerja pada JDK 12, meskipun kemungkinan pada versi 11 juga, Anda hanya perlu mengubah parameter jvmTarget dalam skrip perakitan jvmTarget :

 withType<KotlinCompile> { kotlinOptions { jvmTarget = "12" ... } } 

Sebelum memulai layanan microser, Anda harus menginstal Konsul dan mulai agen - misalnya, seperti ini: consul agent -dev .

Memulai layanan microsoft dimungkinkan dari:

  • IDE
    Pengguna IntelliJ IDEA dapat melihat sesuatu seperti berikut:

  • konsol
    Untuk melakukan ini, buka folder proyek dan jalankan secara berurutan:

     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 spring-boot-service/build/libs/spring-boot-service.jar 


Setelah memulai semua layanan microser di http://localhost:8500/ui/dc1/services Anda akan melihat:



Pengujian API


Hasil pengujian API layanan Helidon diberikan sebagai contoh:

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

     { "name": "helidon-service", "framework": { "name": "Helidon SE", "releaseYear": 2019 }, "requestedService": null } 
  2. 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 } } 
  3. GET http://localhost:8081/application-info/logo

    Mengembalikan gambar.

Anda dapat menguji API microservice sewenang-wenang menggunakan Postman ( kumpulan permintaan), klien HTTP IntelliJ IDEA ( kumpulan permintaan), browser, atau alat lain. Jika Anda menggunakan dua klien pertama, Anda perlu menentukan port dari microservice yang disebut di variabel yang sesuai (di Postman itu ada di menu koleksi -> Edit -> Variabel , dan di HTTP Client itu berada di variabel lingkungan yang ditentukan dalam file ini ), dan ketika menguji metode 2) API juga perlu menentukan nama layanan mikro "di bawah tenda" yang diminta. Jawabannya akan serupa dengan yang diberikan di atas.

Perbandingan Pengaturan Aplikasi



Ukuran artefak


Untuk menjaga kesederhanaan konfigurasi dan menjalankan aplikasi dalam skrip assembly, tidak ada dependensi transitif yang dikecualikan, sehingga ukuran layanan uber-JAR pada Spring Boot secara signifikan melebihi ukuran analog pada kerangka kerja lain (karena ketika menggunakan permulaan, tidak hanya dependensi yang diperlukan yang diimpor; jika diinginkan, ukuran dapat dikurangi secara signifikan):
Layanan microserUkuran Artefak, MB
Layanan Helidon16.6
Layanan Ktor20.9
Layanan micronaut16.5
Layanan booting musim semi42.7


Waktu peluncuran


Waktu peluncuran setiap aplikasi tidak konsisten dan jatuh ke dalam beberapa "jendela"; tabel di bawah ini menunjukkan waktu peluncuran artefak tanpa menentukan parameter tambahan:
Layanan microserMulai waktu, detik
Layanan Helidon2.2
Layanan Ktor1.4
Layanan micronaut4.0
Layanan booting musim semi10.2

Perlu dicatat bahwa jika Anda "membersihkan" aplikasi Spring Boot dari dependensi yang tidak perlu dan memperhatikan untuk mengkonfigurasi aplikasi untuk memulai (misalnya, hanya memindai paket yang diperlukan dan menggunakan inisialisasi bin malas), Anda dapat secara signifikan mengurangi waktu startup.

Uji beban


Untuk pengujian, Gatling dan skrip Scala digunakan. Generator beban dan layanan yang diuji dijalankan pada mesin yang sama (Windows 10, prosesor quad-core 3,2 GHz, 24 GB RAM, SSD). Port layanan ini ditunjukkan dalam skrip Scala.

Untuk setiap layanan mikro ditentukan:

  • jumlah minimum heap-memory ( -Xmx ) yang diperlukan untuk menjalankan layanan microser (menanggapi permintaan) yang berfungsi
  • memori tumpukan minimum yang diperlukan untuk lulus uji beban 50 pengguna * 1000 permintaan
  • memori tumpukan minimum yang diperlukan untuk lulus uji beban 500 pengguna * 1000 permintaan

Lulus tes beban berarti bahwa layanan mikro merespons semua permintaan kapan saja.
Layanan microserJumlah minimum memori tumpukan, MB
Untuk memulai layananUntuk memuat 50 * 1000Untuk memuat 500 * 1000
Layanan Helidon9911
Layanan Ktor111113
Layanan micronaut131317
Layanan booting musim semi222325

Perlu dicatat bahwa semua layanan microser menggunakan server HTTP Netty.

Kesimpulan


Tugas - pembuatan layanan sederhana dengan HTTP API dan kemampuan untuk berfungsi di ISA - dapat diselesaikan pada semua kerangka kerja yang dimaksud. Sudah waktunya untuk mengambil stok dan mempertimbangkan pro dan kontra mereka.

Helidon

Edisi standar
  • plus
    • pengaturan aplikasi
      Dalam semua hal menunjukkan hasil yang baik;
    • "Tidak ada sihir"
      Kerangka kerja membenarkan prinsip yang dinyatakan oleh pengembang: hanya butuh satu anotasi untuk membuat aplikasi ( @JvmStatic - untuk interope Java-Kotlin).
  • kontra
    • pekerjaan mikro
      Beberapa komponen yang diperlukan untuk pengembangan industri tidak tersedia, misalnya, injeksi ketergantungan dan implementasi Service Discovery.

Mikroprofil
Microservice tidak diterapkan pada kerangka kerja ini, jadi saya hanya akan mencatat beberapa poin yang saya tahu:

  • plus
    • Implementasi Eclipse MicroProfile
      Intinya, MicroProfile adalah Java EE yang dioptimalkan untuk ISA. Jadi, pertama, Anda mendapatkan akses ke seluruh variasi Java EE API, termasuk yang dirancang khusus untuk ISA, dan kedua, Anda dapat mengubah implementasi MicroProfile ke yang lain (Open Liberty, WildFly Swarm, dll.) .
  • selain itu
    • pada MicroProfile Starter Anda dapat membuat proyek dari awal dengan parameter yang diperlukan dengan analogi dengan alat serupa untuk kerangka kerja lainnya (misalnya, Spring Initializr ). Pada saat publikasi artikel, Helidon mengimplementasikan MicroProfile 1.2, sedangkan versi spesifikasi terbaru adalah 3.0.


Ktor

  • plus
    • ringan
      Memungkinkan Anda untuk menghubungkan hanya fungsi-fungsi yang secara langsung diperlukan untuk menyelesaikan tugas;
    • pengaturan aplikasi
      Hasil bagus dalam segala hal.
  • kontra
    • โ€œDiasahโ€ di bawah Kotlin, yaitu mungkin, tetapi tidak perlu, untuk dikembangkan di Jawa;
    • microframework (lihat item serupa untuk Helidon SE).
  • selain itu
    Di satu sisi, konsep pengembangan kerangka kerja tidak termasuk dalam dua model pengembangan Java yang paling populer (Spring-like (Spring Boot / Micronaut) dan Java EE / MicroProfile), yang dapat mengarah pada:

    • masalah dengan menemukan spesialis;
    • waktu yang lebih lama untuk menyelesaikan tugas dibandingkan dengan Boot Musim Semi karena kebutuhan untuk secara eksplisit mengkonfigurasi fungsionalitas yang diperlukan.

    Di sisi lain, ketidaksamaan dengan Musim Semi โ€œklasikโ€ dan Java EE memungkinkan Anda untuk melihat proses pengembangan dari sudut yang berbeda, mungkin lebih sadar.


Micronaut

  • plus
    • Aot
      Seperti yang disebutkan sebelumnya, AOT memungkinkan Anda untuk mengurangi waktu mulai dan memori yang dikonsumsi oleh aplikasi dibandingkan dengan rekannya pada Spring Boot;
    • Model pengembangan semi-suka
      Programmer dengan pengalaman berkembang di Spring tidak akan membutuhkan banyak waktu untuk menguasai kerangka ini;
    • pengaturan aplikasi
      Hasil yang baik dalam semua hal;
    • polyglot
      Dukungan warga negara kelas satu untuk Jawa, Kotlin, Groovy; mungkin akan ada dukungan untuk Scala. Menurut pendapat saya, ini dapat secara positif mempengaruhi pertumbuhan masyarakat. Ngomong-ngomong, pada Juni 2019 Groovy di peringkat popularitas bahasa pemrograman TIOBE mengambil tempat ke-14, lepas landas dari tahun ke-60 sebelumnya, dengan demikian berada di posisi kedua terhormat di antara bahasa JVM;
    • Proyek Micronaut untuk Spring juga memungkinkan Anda untuk mengubah runtime dari aplikasi Boot Spring yang ada ke Micronaut (dengan batasan).


Boot musim semi

  • plus
    • kematangan platform dan ekosistem
      Kerangka kerja "setiap hari". Untuk sebagian besar tugas sehari-hari, sudah ada solusi dalam paradigma pemrograman Spring, yaitu, dengan cara yang akrab bagi banyak programmer. Pengembangan disederhanakan oleh konsep permulaan dan konfigurasi otomatis;
    • kehadiran sejumlah besar spesialis di pasar tenaga kerja, serta basis pengetahuan yang signifikan (termasuk dokumentasi dan jawaban untuk Stack Overflow);
    • perspektif
      Saya pikir banyak orang akan setuju bahwa dalam waktu dekat, Spring akan tetap menjadi kerangka pengembangan terkemuka.
  • kontra
    • pengaturan aplikasi
      Aplikasi pada kerangka kerja ini bukan di antara para pemimpin, namun beberapa parameter, seperti disebutkan sebelumnya, dapat dioptimalkan secara mandiri. Perlu juga mengingat kembali keberadaan proyek Spring Fu , yang sedang dalam pengembangan aktif, yang penggunaannya memungkinkan untuk mengurangi parameter-parameter ini.

Anda juga dapat menyoroti masalah umum yang terkait dengan kerangka kerja baru yang hilang dari Spring Boot:

  • ekosistem yang kurang berkembang;
  • sejumlah kecil spesialis dengan pengalaman dengan teknologi ini;
  • waktu yang lebih lama untuk menyelesaikan tugas;
  • prospek yang tidak jelas.

Kerangka kerja yang dipertimbangkan termasuk dalam kategori bobot yang berbeda: Helidon SE dan Ktor adalah mikroframe , Spring Boot adalah kerangka kerja tumpukan penuh, Micronaut lebih mungkin juga tumpukan penuh; kategori lain adalah MicroProfile (mis. Helidon MP). Dalam mikroframe, fungsionalitas terbatas, yang dapat memperlambat pelaksanaan tugas; Untuk mengklarifikasi kemungkinan penerapan fungsi ini atau itu berdasarkan kerangka pengembangan apa pun, saya sarankan Anda membiasakan diri dengan dokumentasinya.

Saya tidak berani menilai apakah kerangka kerja ini atau itu akan "menembak" dalam waktu dekat, oleh karena itu, menurut pendapat saya, lebih baik untuk terus memantau perkembangan acara menggunakan kerangka kerja pengembangan yang ada untuk menyelesaikan tugas kerja.

Pada saat yang sama, seperti yang ditunjukkan dalam artikel, kerangka kerja baru mengungguli Spring Boot oleh parameter yang dipertimbangkan dari aplikasi yang diterima. Jika salah satu dari parameter ini sangat penting untuk salah satu layanan microser Anda, maka Anda mungkin perlu memperhatikan kerangka kerja yang menunjukkan hasil terbaik pada mereka. Namun, jangan lupa bahwa Boot Musim Semi, pertama, terus membaik, dan kedua, ia memiliki ekosistem yang sangat besar dan sejumlah besar programmer Java yang akrab dengannya. Ada kerangka kerja lain yang tidak tercakup dalam artikel ini: Javalin, Quarkus, dll.

Anda dapat melihat kode proyek di GitHub . Terima kasih atas perhatian anda!

PS: Terima kasih kepada artglorin untuk membantu dengan artikel ini.

Source: https://habr.com/ru/post/id456376/


All Articles