In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "the original era of the cloud is Java or Go". The content of the explanation in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "whether the original era of cloud is Java or Go".
Java's once famous motto, "write once, run everywhere", is out of date because now we just want to run code in a container. In a container, a "Just in time" compiler doesn't make much sense.
For this reason, the Java ecosystem is probably in transition to better adapt to cloud computing. Oracle's GraalVm allows bytecode to be compiled into Linux executables (ELF), while Rad Heat's Quarkus and other frameworks are determined to make responsive services easier. Quarkus, with Netty and Vertx.x as the core, can be used to build very efficient responsive Web services.
Java is compiled into executable binaries and starts at millisecond speed with a small memory footprint. This allows you to take advantage of the Java ecosystem and even write in other JVM languages such as Scala and Kotlin. You can use the online project generator to play with Quarkus, or use the maven plug-in to build a project locally.
Golang, on the other hand, is created for the cloud and has no legacy burden when running in a container. It is considered to be the programming language of the cloud. The generated binary executables are small, fast start, and have a small memory footprint, and this is a feature that Go has had since its inception. The popularity of Golang has posed a severe challenge to the Java world.
Does Java have a chance? maybe only time will tell us the final answer. However, out of curiosity, I would like to compare the cloud native services of Java and Golang in terms of performance and development experience.
In this article, I will write the same service in both languages. Compare their CPU usage, RAM, latency, and running speed. These services will be started in the container with the same resource allocation and tested with ab.
In my case, this is a "good enough" benchmark because I don't assume that the best / worst benchmark results are found, but run two benchmarks in the same environment for comparison.
Scene
The two services will connect to the MySQL database running in another container, with one table and three rows of data.
Each service takes all the records, converts them to objects, and then outputs the JSON array.
Ab will issue a 10K request with a concurrency level of 100MagneQukus JVM version running twice (to test the "cold" / "warm" JVM).
Go language version
The Go language version uses the gin framework.
# the service package main import ("database/sql"fmt"github.com/gin-gonic/gin" _ "github.com/go-sql-driver/mysql"net/http") type Fruit struct {Id int `json: "id" `Name string `json: "name" `} var con * sql.DB func init () {/ / opening a mysql connection pool with another container db, err: = sql.Open ("mysql") "root:password@tcp (host.docker.internal:3306) / payments") if err! = nil {panic ("failed to open a mysql connection")} con = db} func main () {r: = gin.Default () r.GET ("/ fruits", fruits) r.Run () / / server up on 8080} / / THE REQUEST HANDLER func fruits (c * gin.Context) {fruits: = getFruits () c.JSON (http.StatusOK Fruits)} func getFruits () [] Fruit {rows, _: = con.Query ("SELECT * FROM fruits") fruits: = [] Fruit {} for rows.Next () {var r Fruit rows.Scan (& r.Id, & r.Name) fruits = append (fruits, r)} return fruits}
Golang's MySQL driver uses go-sql-driver. The code style of golang is very clear. An attitude that everything is right in front of you. The main function starts the server, configures the request handler, and opens the DB connection.
Compile the local executable file
Kotlin version
Package org.acme import io.vertx.core.json.JsonArray import io.vertx.core.json.JsonObject import io.vertx.mutiny.mysqlclient.MySQLPool import io.vertx.mutiny.sqlclient.Row import io.vertx.mutiny.sqlclient.RowSet import java.util.concurrent.CompletionStage import javax.inject.Inject import javax.ws.rs.GET import javax.ws.rs.Path import javax.ws.rs.Produces import javax.ws.rs.core.MediaType @ Path ("/ fruits") class FruitResource {@ field: Inject lateinit var client: MySQLPool @ GET @ Produces (MediaType.APPLICATION_JSON) fun listFruits (): CompletionStage {return client.query ("SELECT * FROM fruits") .execute () .map {rows: RowSet-> rows.fold (JsonArray ()) {array Row-> array.add (JsonObject () .put ("id", row.getLong ("id")) .put ("name", row.getString ("name"))}} .subscribeAsCompletionStage ()}}
Database connections use Quarkus React Mysql extensions.
The code is quite different from the Go version, such as CDI dependency injection, declarative routing using javax annotations, automatic configuration parsing, and data source / connection creation / server boot. This is the price of using the framework, which does the heavy work for you and determines the way you do things. However, it is much shorter than the go version.
The Netty responsive web server is used here, which is wrapped in a Vert.x multi-event loop, and there is a Vert.x responsive MySQL driver so that multiple DB connections can be handled with a single thread.
In addition, I can use the fold function of Kotlin's collection library, which does not have a general Go version.
Compile the executable file for the Java version
I've figured out what happened during the build, and at its core is SubstrateVM. It is designed as an embeddable virtual machine in the AOT process, and it links to our code and compiles as a unit. According to Oracle, however, SubstrateVM has fewer optimizations than HotSpot Vm, and the garbage collector is simpler.
The AOT compiler is called "Graal" and is language-independent. Java bytecode needs to be translated into an intermediate representation (Truffle language). The related discussion about Graal and Truffle can be found in this article [1].
Building a Java native executable looks more complex and compiles more slowly, resulting in binaries that are almost twice the size of the Go version. However, a 35m executable binary is much smaller than Java FatJar. 35MB even allows you to run using aws lambda.
Pressure testing
I run all the tests on this machine and the settings are as follows.
MacBook Pro (15 inches, 2017)
2.9 GHz Intel Core i7 (8 cores).
16 GB 2133 MHz LPDDR3
Use cAdvisor's tools to monitor container statistics.
Scene
Quarkus JVM hotspot
Quarkus Java native
Golang
Each of the above cases is tested on the following three configurations
100MB / 0.5 CPU | 200MB / 1 CPU | 300MB / 2 CPU
My main concern is:
Cpu/ram utilization (multicore utilization)
Cpu/ram peak value
Cpu/ram spare
Startup time
Response delay avg/max
Throughput (requests per second)
Test result
It seems that Quarkus is ready for a production environment, allowing a simple JVM/ native release / development model and allowing native tests to be run locally. As long as you don't use reflection or JNI, it's possible according to the configuration of GraalVM. Otherwise, you will have to configure the graal compiler yourself, but there is also a solution.
Latency and throughput
The test results of Golang and native Java are similar, although the test results of the Golang version are slightly better on average. However, the test results for the Java Native version are more stable. Golang services sometimes complete the response within 1.25 μ s, while others take 7 seconds to complete.
The result of the "preheated" version of JVM is not bad, but slightly worse than the version of Native or Go.
CPU utilization
When using 0.5 core, both Go and native-java seem to perform poorly under load, and there is no significant improvement when starting with 2 core. This may be because the bottleneck of the workload is IO. Or because the default configuration of gin/Netty does not take into account the problem of multicore.
The JVM version takes advantage of all given cores and improves performance in all dimensions.
Memory utilization
Under pressure, Java native uses 40MB Golang and 24MB. Both cases are fine, although the Golang version uses almost twice as much memory.
JVM uses 140MB. It's exactly the same as the official statistics of Quarkus. Not bad for JVM, but nearly six times more than the Golang version.
Startup time
Both Golang and cloud-native java start immediately, but the JVM version takes a few seconds (depending on the assigned CPU) and produces CPU spikes at startup. If it is not configured properly, it will cause K8s HPA to get mad and increase pods.
Development experience
This is not so much a practical problem as a religious one. Quarkus uses abstractions that are common in the Java world (such as annotation-based DI). It starts the service for you and creates a connection pool. It can use a rich collection of standard libraries and generics. However, this may feel a bit like dark magic, and once some components don't work, you will feel helpless. In addition, compiling Java code to native binaries is not that easy. There are some limitations and considerations that you must know. Not every Java library is compatible with native compilation. Once you use an incompatible library (such as Guice), you need to configure Graal VM yourself.
Quarkus and Graal VM are relatively new. So there may be some problems. But due to dual mode (JVM or native). When some components of the native version stop working, there is always a backup solution, which is a good workaround for any new problem.
Golang, on the other hand, did not admit that it needed generics until 10 years after its establishment. And it certainly doesn't like the frame to use a lot of magic. This is both a good thing and a bad thing in many ways. In addition, although the Go community is doing very well, there are relatively few tools and libraries available. However, its compilation and build process is faster / simpler. And compatible with each Golang package, there are no restrictions brought by the java-native platform.
Thank you for reading. The above is the content of "is the cloud native era Java or Go". After the study of this article, I believe you have a deeper understanding of whether the cloud native era is Java or Go, and the specific usage needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.