Golang Event Bus

Recently in learning the code of the open source project Grafana, I found that the author has implemented an event bus mechanism, which is used in a large number of projects, the effect is also very good, the code is also relatively simple. https://github.com/grafana/grafana/blob/main/pkg/bus/bus.go 1. Registration and invocation This writeup is seen everywhere inside this project. 1 2 3 4 5 6 7 8 9 10 11 12 13 14

RPC-based plug-in mechanism in Golang

Recently there is a need to implement the plug-in mechanism inside the project, the so-called plug-in means that the program can be extended without releasing a new version of the case, this plug-in mechanism is particularly widely used, common such as our browser extensions, Nginx extensions, PHP extensions and so on. Inside the Go language, it comes with an official plugin extension mechanism, which I have described in a previous

How Kubernetes achieves high availability of components

In Kubernetes, components such as Controller Manager, Scheduler, and user-implemented Controllers are highly available by means of multiple replicas. However, multiple replica Controllers working at the same time inevitably trigger a contention condition for the resources they are listening to, so usually only one replica is working between multiple replicas. In order to avoid this competition, Kubernetes provides a Leader election model, where multiple replicas compete with each other for the Leader, and only the Leader will work, otherwise it will wait.

Golang Object-Oriented Interface Programming

When it comes to object-oriented (OOP), many people have heard of encapsulation, inheritance, polymorphism, these characteristics, in essence, object-oriented is just a software programming ideas. But from this comes the concept of object-oriented language, of which Java is the most typical representative, is a fully object-oriented language, expressed in the language level there are class and object design. After all, the main goal of any software engineering is to achieve

Plug-in programming with Go Plugin

Speaking of plug-ins, many people are not unfamiliar with this thing, in general, plug-in has several benefits, one is to increase the program scalability, rich functionality. In addition, you can also achieve hot updates, some large applications, often several GB of installation procedures, if a small update will need to re-download the entire program, at this time we can update the module plug-in often, so that when the update only need to download a small update file.

kubelet Remote Debugging

1. kubelet startup command analysis kubelet is a systemd service. Take the v1.23.4 k8s cluster installed with Kubeadm tool as an example, the path of the configuration file of this service is /etc/systemd/system/kubelet.service.d/10-kubeadm.conf. The contents are as follows. 1 2 3 4 5 6 7 8 9 10 11 # Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.

In-depth understanding of the principle of nocopy in Golang

01 How to set the object not to be copied sync.Pool cannot be copied. 1 2 3 4 5 6 7 8 9 10 11 // sync/pool.go type Pool struct { noCopy noCopy ... } type noCopy struct{} func (*noCopy) Lock() {} func (*noCopy) Unlock() {} sync.Mutex cannot be copied. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // sync/mutex.

In-depth understanding of Golang's memory allocation principles

01 Local cache for P: mcache 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // runtime/malloc.go numSpanClasses = _NumSizeClasses << 1 _NumStackOrders = 4 - sys.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9 // runtime/mcache.go //go:notinheap type mcache struct { nextSample uintptr scanAlloc uintptr tiny uintptr tinyoffset uintptr tinyAllocs uintptr alloc [numSpanClasses]*mspan stackcache [_NumStackOrders]stackfreelist flushGen uint32 } type stackfreelist struct { list gclinkptr // linked list of free stacks size uintptr // total size of stacks in list } nextSmaple triggers a heap instance after allocating this many bytes.

In-depth understanding of the implementation of rpc.Server in Golang

01 Understanding rpc.Server 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // net/rpc/server.go type Server struct { serviceMap sync.Map // map[string]*service reqLock sync.Mutex // protects freeReq freeReq *Request respLock sync.Mutex // protects freeResp freeResp *Response } func NewServer() *Server { return &Server{} } var DefaultServer = NewServer() 02 Register RPC service 1 2 3 4 5 6 7 func (server *Server) Register(rcvr interface{}) error { return server.

In-depth understanding of the implementation of epoll in Golang

1. Data reception process The process of external data from a computer system is relatively long from the time it enters the NIC to the time it is finally received by the application. The approximate flow is as follows. The NIC receives the data, copies it to the kernel space through the DMA controller, and at the same time initiates a hard interrupt to the CPU. The CPU receives the

In-depth understanding of Golang channel implementation

01 channel definition 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // /usr/data/go1.17/go/src/runtime/chan.go type hchan struct { qcount uint // total data in the queue dataqsiz uint // size of the circular queue buf unsafe.Pointer // points to an array of dataqsiz elements elemsize uint16 closed uint32 elemtype *_type // element type sendx uint // send index recvx uint // receive index recvq waitq // list of recv waiters sendq waitq // list of send waiters lock mutex } type waitq struct { first *sudog last *sudog } The underlying data structure of channel is hchan, which itself consists of buf forming a circular linked list, which is a circular queue.

In-depth understanding of zero-copy technology

01 How processes read data A process has its own separate heap area memory and stack area memory, so it can only read the area of memory that belongs to it. If it needs to access a device outside the process, then it can only be handled by the operating system on its behalf. The operation by which a process requests access to a device from the operating system is called a system call (system call).

In-depth understanding of the Golang timer implementation principle

01 time.timer 1 2 3 4 5 6 7 8 9 10 11 12 // runtime/time.go type timer struct { pp puintptr when int64 period int64 f func(interface{}, uintptr) arg interface{} seq uintptr nextwhen int64 status uint32 } timer is defined in runtime/time.go. pp is a pointer to the current counter on p and a pointer to the heap. when is the scale, indicating how often to trigger. nextWhen indicates the nanosecond timestamp of the next trigger, the underlying cpu time of the call.

Several strategies for implementing load balancing

Consider the scenario, an API gateway that distributes requests to multiple upstream nodes, as in the upstream configuration of nginx. 1 2 3 4 5 6 7 8 9 10 11 12 upstream backend { server a1.com weight=5; server a2.com; server a3.com backup; server a4.com backup; } server { location / { proxy_pass http://backend; } } There are many common practices on how to distribute the routes / equally to the four services, in general, such as randomized algorithms, etc.

Several ways to splice strings in Golang

String Splicing Definition Define a method that implements string splicing, with the following function signature prototype. 1 type concatFn func(...string) string That is, pass in a series of strings and return the result of their stitching. Way 1: Use the + operator 1 2 3 4 5 6 7 func ConcatWithAdd(strs ...string) string { var r = "" for _, v := range strs { r += v } return r } Obviously, the performance of this approach is poor.

In-depth understanding of containerization technologies

The following is a standard explanation of containerization. A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings. Containers are different from virtual

Golang's go:linkname directive

Suppose there is an internal package that provides a method as follows. 1 2 3 4 5 6 7 package internal import "fmt" func print(msg string) { fmt.Println("[internal]", msg) } This method is used internally, it has no export properties, so it can’t be imported by other external packages, so since this is the case, is there any way to call this method outside the package? The answer is yes, except that this hack blocks at least 80% of Gopher’s knowledge, and it is go:linkname.

Cloud-native virtual networking tun/tap & veth-pair

Overview The mainstream virtual NIC solutions are tun/tap and veth, with tun/tap appearing much earlier in time. The kernel released after Linux Kernel version 2.4 compiles tun/tap driver by default, and tun/tap is widely used. In the cloud-native virtual network, flannel0 in the UDP mode of flannel is a tun device, and OpenVPN also uses tun/tap for data forwarding. veth is another mainstream virtual NIC solution. In Linux Kernel version 2.

Ensuring Concurrency Safety with Atomic Operations in Golang

Scenarios In many backend services, configuration files or dictionary data need to be loaded dynamically. So when accessing these configurations or dictionaries, it is necessary to add locks to these data to ensure the security of concurrent reads and writes. Normally, read and write locks are required. Here’s an example of a read/write lock. Read/Write Locks to Load Data Using read/write locks ensures that access to data does not result

Building a Zero-Copy File Web Server in Golang

This article starts with Golang’s file server, then explores what the sendfile system call is, and finally summarizes the usage scenarios for zero-copy. Build a file server How to build a zero-copy file server in Golang, here is the complete code. 1 2 3 4 5 6 7 8 package main import "net/http" func main() { http.Handle("/", http.StripPrefix("/static/", http.FileServer(http.Dir("./output")))) http.ListenAndServe(":8000", nil) } Well, yes. Two lines of code to implement a file server.