In the current internet architecture circle, containerization and microservices are the main topics of discussion.
Clearly, looking at the development trends of the internet, projects are becoming increasingly large. A single massive project is not conducive to maintenance and development; developers' computers can hardly directly support huge projects like Alibaba Cloud or Azure, so we need to decouple them. In other words, componentization, containerization, and microservices of applications will inevitably become trends.
Regarding the development of containerized applications, I have some insights from my previous development experience, which I will elaborate on in this article.
Previous Language Choices#
Before I started learning Golang, I had tried many languages. As mentioned in my personal profile, I have used classic PHP, Java, complex CPP, and interesting frameworks like Express.js, Koa.js, and Next.js. Even now, you can find many of my previous exercises on my GitHub account, such as AH-dark/bing-image-api. However, these languages have their shortcomings, which led me to abandon them.
Java#
The Spring family is widely used in mainland China, especially by Alibaba, which can almost be considered one of the main users of Spring. Relying on Alibaba, SpringBoot has almost become a required course for every Java engineer in China.
Having heard its name for a long time, I spent about two weeks building a Java SpringBoot application, only to abandon it shortly after.
As a Java program, even when compiled into bytecode, its enormous size is daunting. Moreover, Java, as a VM-based cross-platform language, relies on the JVM to run, requiring a large Runtime to be installed on the system. In this case, the packaged Docker Image becomes extremely large, but this has nothing to do with your code. Applications running on the JVM also consume a lot of memory, which is clearly not conducive to containerization, as a single application consumes too much memory unnecessarily. The most unacceptable aspect is its startup time. Even a very small Spring Boot application requires at least about 5 seconds of cold startup time, which can cause significant lag in an Edge call chain. This is also the main reason I abandoned it.
PHP#
PHP is a dynamically typed scripting language that cannot be packaged into bytecode or elegantly encapsulated into a Jar-like application.
PHP in a Docker Image requires various extensions and PHP FPM to be installed within the Image, which is unacceptable.
This often means that in a production environment, a Kubernetes cluster needs to run dozens or even hundreds of PHP FPM and its extensions, which cannot be reused, clearly wasting computational resources significantly.
C++#
I have not publicly released any web applications written in CPP on my GitHub because my existing CPP applications are generally at a very low level of completion.
As a memory-unsafe language, CPP applications place high demands on the writer, and the development cycle of CPP projects is typically very long.
Furthermore, cross-platform issues are quite challenging with CPP, and there is still a certain need for cross-platform compatibility in containerized applications.
For these three reasons, I did not consider continuing to use CPP for writing containerized applications.
Node.js#
I previously used Node.js to write middleware for the multi-layer RPC chain of Source Global CDN.
Almost all elements in JavaScript can be presented as Objects, which is why I have a preference for it. Additionally, TypeScript, with its static type enforcement, is the language I widely use in production environments (especially on the frontend, thanks to React's perfect support for TypeScript, using TypeScript in React frontend is something I find very enjoyable).
After writing almost all the middleware for Source Global CDN using JavaScript, TypeScript, and frameworks like Express.js and Koa.js, I realized an issue: the Docker image encapsulating Node.js does not seem to perform well in terms of cold startup.
It was at this point that I began to pay attention to the cold startup speed of applications.
On ServerLess platforms, the invocation of Docker Images often follows the pattern of invoking the Docker image -> running -> sending Http Request. In Node.js applications, the large image resulting from encapsulating the Node.js Runtime struggles to run quickly within 500ms. Consequently, Source Global CDN had to introduce a layer of object storage to persistently cache files to avoid lag caused by cold starts. Subsequently, I gradually aggregated and rewrote the middleware, and the language I rewrote it in is the upcoming highlight—Golang.
Go#
First, we need to understand it to some extent.
Introduction#
Go (also known as Golang) is a statically typed, compiled, concurrent programming language developed by Google, featuring garbage collection.
Robert Griesemer, Rob Pike, and Ken Thompson began designing Go in September 2007, and later Ian Lance Taylor and Russ Cox joined the project. Go was developed based on the Inferno operating system. Go was officially announced in November 2009 as an open-source project, supporting operating systems like Linux, macOS, and Windows.
In 2016, Go was selected by the software evaluation company TIOBE as the "TIOBE Language of the Year 2016."
Currently, Go releases a minor version every six months (i.e., upgrading from a.x to a.y).
The syntax of Go is similar to C, but the declaration of variables is different. Go supports garbage collection. The parallel computing model of Go is based on Tony Hoare's Communicating Sequential Processes (CSP), with other languages that adopt similar models including Occam and Limbo. Go also features this model, such as channel communication. Through parallel constructs like goroutines and channels, thread pools and pipelines can be built. In version 1.8, support for plugins was introduced, allowing parts of functions to be dynamically loaded from Go.
Compared to C++, Go does not include features like enums, try-catch exception handling, inheritance, or virtual functions but adds language-level support for features like slices, generics, concurrency, channels, garbage collection, and interfaces. It holds a negative attitude towards the existence of assertions and defends itself for not providing type inheritance.
Unlike Java, Go natively provides associative arrays (also known as hash tables or dictionaries).
Quoted from Go - Wikipedia
The initial purpose of Google designing Go was to improve development efficiency in multi-core, networked machines with large codebases. Therefore, it has good performance and requires less from the Runtime.
At the same time, Go has a built-in lightweight coroutine called Goroutine, which meets basic concurrency needs.
Containerization#
Unlike Java and Node.js, Go has a natural advantage in containerization as a compiled language.
The size of a compiled Go application can be reduced to the MB level, without the need for a large built-in Runtime; it can run with just some system environment. The packaged Golang Application Image is usually very small.
Above is the Golang image, below is the Node.js image.
Functionality#
Although many proposals in Go are nonsensical and unconstructive, Go remains a powerful and unified language.
The HTTP Client you see in different PHP projects may vary; some use curl, while others use the file_get_content function. However, in Go, most people tend to choose the built-in http module. This is an advantage because it reduces the likelihood of errors due to differing specifications.
Performance#
Go can internally call C language programs, Rust programs, and Assembly programs, allowing it to compensate for some of its performance disadvantages by referencing other languages.
Unlike Java, Go does not require a VM environment and has very low memory usage, not needing to run programs in a VM. The size of the compiled executable file is also small, unlike Java, where the bytecode size is enormous.
The biggest advantage of Go applications for me is the cold startup. The cold startup time of the rewritten Go backend program for Source Global CDN improved by about 3000%. This is a significant improvement and can greatly enhance user experience. This is also the main reason I chose Go as the primary development language for the Source Global CDN project in the future.
If you mention C++, consider the development cycle and difficulty.
Conclusion#
Go will be the main language I use for a while because most of its designs align with my aesthetic preferences. Let's not even talk about the foolish design of generics and the future manual memory control. At the same time, I also recommend everyone to try using Go; although some of its designs are very stupid, overall, it is still worth a try.
I won't say that I'm about to start deeply learning Rust.
References#
- https://zh.wikipedia.org/zh-cn/Go
- https://go.dev/doc/devel/release
- https://go.dev/doc/install/gccgo
- https://go.dev/doc/faq#different_syntax
- https://discord.com/blog/why-discord-is-switching-from-go-to-rust
- https://zh.wikipedia.org/zh-cn/Java
- http://www.oracle.com/technetwork/java/javase/overview/javahistory-index-198355.html
- https://www.rust-lang.org/learn/get-started