Zeng Fanwei classes la education technology co., LTD. Hangzhou senior development engineer source | alibaba cloud native public number

Hangzhou Kaikai Education Technology Co., Ltd. is an online education company committed to providing learning guidance for primary and secondary school students. At present, the company’s back-end service infrastructure mainly relies on Aliyun, including computing, network, storage and Kubernetes services.

Technical selection background

2020 is a year of course! The company develop, the company team from hundreds of people up to now thousands of people, basically there will be several thousand in concentrated use in operating the background at the same time, the company internal background operation system is built with PHP, performance with business has gradually cannot meet the needs of the company planning, In addition, the development department of the company has split the microservices, and the main external service is the Dubbo cluster of Java language. The background system needs to seamlessly connect with the Dubbo service of Java, so PHP has gradually failed to meet the needs of the company.

At that time, I also investigated PHP Dubbo project, which was passed because there was basically no one to update and maintain. Later, I was interested in the simple and high-performance GO language, and then I paid attention to the Dubbo-Go project. After a period of research, we found that Dubbo Go met our business needs and the community was very active, so we decided to choose Dubbo- Go as the background PC business framework.

Some students may also ask why they don’t use gRPC with better cross-language support, because many companies started their RPC service clusters based on Dubbo ecology. If it costs too much to change the framework, they will not consider it. GRPC has better cross-language support, but many things need to build their own wheels. Such as service registration, service discovery, log monitoring and so on.

At that time, when we decided to choose Dubo-Go, there were some objections from the development team. Why not just switch to Java? If we switch to Java, there will be no cross-language communication problems. Go itself is a high-performance language not inferior to Java, which is very suitable for microservices architecture.

Challenges

After determining the framework selection, the first task I received was to build a set of scaffolding for the rapid creation of business projects, develop THE RPC proxy service based on HTTP protocol, and deploy the container deployment platform of the company, all from scratch, and basically can not find reference materials on the Internet.

First of all, we need to plan the architecture of dubbo-Go project and determine the directory structure of the project. After referring to Dubbo-Go Demo and other GO projects, we finally determine the directory structure of the project. The following directory structure can be used as a reference.

In order to be consistent with the Java Services Registry, Dubo-Go selected the following components for project selection:

  • Use ZooKeeper as the registry
  • Nacos serves as the configuration center
  • Database ORM uses GORM
  • Message queues use RocketMQ

In order to increase the efficiency of development, we can simplify the configuration before the initialization of the Provider service. Only the most basic configuration can be preserved, such as the following. The code of the Provider service can be referred to the Dubo-go demo.

Here is the code for the main method that starts the service:

Design of DUbo-go RPC service gateway

Generally, Dubbo is used. The provider side needs to expose the interface and method, and the consumer side needs to clearly define the interface definition and method definition used by the service, as well as the type of input and return parameters. In addition, the API provided by the provider side is required for the two sides to communicate and call normally.

However, the use scenario of the gateway is not concerned with the detailed definition of the interface to be called. The gateway only focuses on the method to be called, the parameters to be passed, and the returned results can be received. The basis of the implementation of the gateway proxy is the generalization call feature of Dubbo/ Dubbo-Go.

The following is the demo given by Dubo-Go official. After loading the generalization service, it needs to wait for 3 seconds to complete the call. However, in actual use, it must not be able to load the service in real time and wait for 3 seconds.

After the study of dubbo-Go generalization call demo, it is found that it is feasible to use this feature to design dubbo-Go gateway. The difficulty is that we need to obtain and cache the parameters of each gateway proxy RPC service method and the path of the service, so as to initialize the generalization call service well before the call. The configuration of a service is as follows.

As the gateway proxy is made by go language, the Java RPC service configuration cannot be obtained through the Java JAR package. If manual maintenance is used, it is too much work and error-prone, which is obviously unacceptable. It has taken some time to understand that Java services can obtain the configuration through annotations. When the Java side starts the service with annotations on the method, it sends the configuration information to MQ in a message, which is consumed by the gateway to obtain the configuration of the Java RPC service.

Since the RPC service of Dubbo Go does not support annotations in the Go language, I wrote a small tool to scan the code after thinking, adding corresponding annotations before each RPC service method, scanning the annotations to obtain the CONFIGURATION of RPC service, and generating the CONFIGURATION of RPC service in the project directory after obtaining the configuration. The configuration is read and sent to MQ when the application is started.

After the implementation of gateway proxy, more functions can be implemented on the basis of the gateway, such as token verification, whitelist, traffic limiting, fusing, and log monitoring. The implementation effect of gateway proxy request is as follows:

Containerized deployment

The internal container deployment environment of the company is K8s of Ali Cloud, and the deployment to K8s platform only needs to provide image files. Since Dubbo-Go is a binary file after compilation, it does not need any additional third-party libraries, and it can run stably in the Docker environment. You can use any Linux distribution, such as centos, as the base image.

LABEL Maintainer ="<[email protected]>" LABEL version="1.0" LABEL Description =" KKL-go-NKO-base "' ARG envType=stable # Sets the environment variable ENV ADD./target/ NKO-base -${envType}.tar.gz /app/ WORKDIR /app EXPOSE 20000Copy the code

After the image is written, it is provided to the publishing platform. The publishing platform machine starts the image, decompresses the package file, and executes the Dubo-go program.

Container entrypoint set to [bash, -c, tar -zxf nko-base-stable.tar.gz && SERVER_ENV=kubernetes && sh ./nko-base/bin/load.sh start -group=stable]
Copy the code

Since there are usually multiple deployment environments from development test to production, we need to change the compilation script in the Dubo-Go Samples demo to support multi-environment packaging.

In addition, the default registered IP address of Dubo-go is the virtual IP address of K8s pod. The network between different K8s clusters cannot communicate with each other, so the default registered IP address needs to be changed if the call needs to be made across clusters. Change the default registered POD IP + port to Kubernetes entity machine IP plus the corresponding port, Kubernetes will write the entity machine IP plus the corresponding port environment variable in pod, applications can read the environment variable to obtain the entity machine IP plus port, To implement this function, modify the registration logic of Dubo-Go. A zookeeper registry, for example, for example, we can by extending the registery/zookeeper/registry. Go registerTempZookeeperNode method to implement the modification registration of IP and port, the code below, Dubo-go will officially support custom IP and port registration in the form of configuration in a later version.

func (r *zkRegistry) registerTempZookeeperNode(root string, node string) error { ... RegIp = OS. The Getenv (constant2. RegistryEnvIP) / / entity machine IP regPort = OS Getenv (constant2. RegistryEnvPort) / / entity machine port urlNode, _ := common.NewURL(node) role, _ := strconv.Atoi(urlNode.GetParam(constant.ROLE_KEY, "")) if role == common.PROVIDER && regIp ! = "" && regPort ! = "" { urlNode.Ip = regIp urlNode.Port = regPort node = url.QueryEscape(urlNode.String()) } zkPath, err = r.client.RegisterTemp(root, node) ... }Copy the code

The last word

If you encounter some problems while using Dubo-Go, you can submit an issue or join the community nail group for communication.

Personal advice: If you’re ready to go into dubbo-Go, it’s best to solve these problems yourself and give PR back to the authorities. You can grow and learn by solving problems when you encounter them, right?

Anyone interested in apache/ Dubo-Go is welcome to join the apache/ Dubo-Go exchange group by searching the Spike group number 31363295.

Author’s brief introduction

Github @jack15083 zeng Fanwei (Github @jack15083), a front-line programmer with 9 years of experience in server-side business development, has worked as back-end development engineer in Tencent Literature and many other companies. Currently, he is working in Hangzhou Kaikaela Education Technology Co., LTD., engaged in go language service infrastructure and middleware as well as some business development.