Build a new blogging system with Golang
Some time ago, I wanted to carry out a large-scale update of the blog system, because the original Nodejs background was not good in many places, no matter in terms of design or coding structure, I did not achieve the desired effect. Therefore, we started to design the new system before the National Day. After several days of reconstruction and modification, the first version of the front desk has been completed and will continue to be optimized in the future.
The expected goals
My vision for my own blogging system hasn’t changed, and I wrote an article about it called “What KIND of Blogging System DO I Want?” I made the following optimization points for this system update.
- It opens faster
- Still no bells and whistles
- Routing is constant
- External display optimization
Open the speed
The opening speed depends mainly on three factors:
- Server Network Latency
- Server service logic processing time
- Front-end page rendering time
Since there’s really nothing I can do about the first and third items, this update will focus on the second.
About all those fancy features
I have used wordpress, also played discuz, even large and small website system. However, in order to add functions and replace templates more flexibly and conveniently, the access speed of these websites is greatly reduced, and the main performance bottleneck comes from internal logic. For example, there are many hooks designed in wordpress that most user system plug-ins communicate with some core components. While flexibility increases, performance is sacrificed.
At the same time, these systems provide many customization options, which can complicate the database structure. Data sources in a single page come from several different tables. There are mechanisms such as caching, but when a portion of data is updated, the amount of logical processing is increased.
To avoid this unnecessary overhead, I didn’t design these handy hooks into my blogging system. In other words, in addition to its own functions, the blog system can only add functions itself, even on the basis of the original structure of the image, or more generally speaking, the business logic was “written dead” by me.
Language selection
The original system background is written based on NodeJS, directly using the Express framework. I don’t like this framework, I don’t hate it, I just use it. But the framework authors have come up with a new KOA. After a brief experience, I can only say that it’s not like writing code, it’s like playing with Legos, assembling them all the time. For those who have never touched the middleware, there is a sense of panic. You never know who is going to have some kind of inexplicable problem, or even a version update will cause it to fail.
On reflection, NodeJS annoys me for three reasons:
The one that bothers me the most about the above three is the asynchronous callback. For blogs, where the business logic is not complex, most of the time we do synchronous processing. Only when we encounter that kind of complexity do we enable parallel computing to reduce processing time. Nodejs, however, uses asynchrony all the time, and the callback function can be quite cumbersome to handle. Koa, with the help of the new ES7 features, solves the problem of callback functions on the surface, but in my opinion, it is just a scheme to make up for the shortcomings of callback on the syntactic sugar level, which I do not appreciate. In the end, I still feel that there are only a few mainstream languages that can be used to switch languages and write server programs:
After repeated comparisons, I finally chose Golang for the following reasons:
- The language performs best, far faster than NodeJS and PHP
- Easy to deploy, Golang can be packaged as a stand-alone executable, making deployment extremely easy.
- Lightweight threading is far more comfortable than using NodeJS asynchronously
- Grammar sugar is closer to C and comfortable to use
Most importantly, Golang, which claims to be an online VERSION of THE C language, has an absolute advantage in performance.
Cache design
The redis cache support was one of my goals with this update. In the process of adding this functionality to NodeJS, I felt the pain of the callback function again.
Caching is also designed with performance in mind, and there are actually two caching strategies I can use.
Single page caching
Single page caching is a gzip compressed version of a rendered web page and stored in Redis.
The advantage of this strategy is that the value stored is small and is the result of gZIP. At the same time, every time the cache is detected, it can be directly taken out and sent to the client, simple logic, fast.
The disadvantages are also obvious. When the title of the site is changed, or the category is changed, all cached pages need to be updated, that is, all cached pages are discarded and need to be rebuilt.
Module data cache
A web page is mainly divided into four modules of data, which are:
- Site data, such as site title, description, etc
- One-page list of web sites
- Site Category List
- Current page content
I can cache the data of these four modules separately, and then assemble it into a web page when I use it, and then gzip it and send it to the client.
This strategy has the advantage of storing data separately and independently. No matter who updates the data, it does not affect each other, and there are no disadvantages of the single-page caching strategy.
The downside is that for every page visited, four Redis reads and a Gzip are required, which increases the IO and CPU stress.
Selection scheme
The final choice of single-page caching scheme, although changing the site attributes and classification will lead to all the cache effect, but from the business logic, site attributes, and classification of these content, the probability of change is very small. It doesn’t change very often, so this is the solution.
Static file policy
In the original system, all static files are processed by express framework, when reading static files, the speed is not ideal, this time the static file access directly migrated to nginx to process, increasing the speed of access.
Just do the following configuration in nginx:
HTTP {server {# static files by nginx processing location ~ * \. | js | | (HTML CSS PNG | JPG | | GIF ico) ${root/SRV/WWW. } # all other requests are handled by go location / {proxy_pass http://localhost:8080; }}}Copy the code
This is also a very classic configuration method for Nginx.
Contrast effects
I ran a series of tests on the server’s network. Since the server is located in the south, it takes about 60 to 70ms to access the ping value in the north. In other words, I can’t open any page of my blog for less than 60ms. This is due to physical network limitations. So in the final test, I subtract 60 from the actual time for comparison.
The blog system supported by the original NDOEJS service takes about 150ms to open a single page and only HTML files. Switching to golang’s new system takes between 70ms and 100ms. All times were less than 100ms. This speed has achieved my desired effect.
That is, after replacing Golang, and with the redis cache, the logical travel time of a page is between 10ms and 20ms without using parallel computing.