This article focuses on the practice of microservices on the server side.

To start development, you need to configure the Go development environment, as I wrote in the Getting Started section on Golang-based microservices

Create our combat project directory tech in the SRC directory under GOPATH and switch to this directory

Go get github.com/micro/go-micro // The RPC framework for microservices for development, which is the foundation of the Micro architecture go get github.com/micro/protoc-gen-micro // The code used to generate Protobuf go get github.com/micro/micro // toolset installation will automatically add micro to the environment variableCopy the code

Go Micro

Go Micro provides the core library for distributed system development, including RPC and event-driven communication mechanisms. Micro’s design philosophy is a pluggable architecture that provides components that can quickly build systems and can be stripped of default implementations and customized to suit their own needs.

Key features of Go Micro

Go Micro abstracts the details of a distributed system

  • Service Discovery – Automatic Service registration and name resolution. Service discovery is the core of microservice development. When service A wants to collaborate with service B, it needs to know where B is. The default service discovery system is Consul, while the multicast DNS (MDNS) mechanism serves as a local solution, or the SWIM protocol in zero-dependency P2P networks (Gossip)
  • Load Balancing – Builds on top of service discovery. When we have any number of instance nodes of a service, we need a mechanism to decide which node to route to. We use a randomly processed hash load balancing mechanism to ensure uniform distribution of service requests and retry in case of problems.
  • Message Encoding – Supports dynamic Encoding of messages based on content-type. The client and server work together to seamlessly encode/decode Go using the Content-Type format. Various messages are encoded and sent to different clients, which are processed by the client server by default. Content-type contains proto-rpc and JSON-rpc by default.
  • Request/ Response-RPC communication Based on the Request/Response mode supporting bidirectional flow, we provide an abstract synchronous communication mechanism. When a request is sent to a service, it is automatically parsed, load balanced, dialled, and converted to a byte stream. The default transport protocol is HTTP /1.1, while HTTP2 is used under TLS.
  • Functions such as Async Messaging – PubSub are built into the asynchronous communication and event-driven architecture. Event notification is central to microservice development. The default messaging uses point-to-point HTTP /1.1 and HTTP2 is used when TLS is enabled.
  • Pluggable Interfaces – Go Micro abstracts Interfaces for each distributed system. As a result, Go Micro’s interfaces are all pluggable, allowing it to be supported without being known at runtime. So any technology can be used internally as long as the interface is implemented

Go Micro Consists of a package

  • Transport is used to synchronize messages
  • Broker is used for asynchronous messages
  • Codec is used for message encoding
  • Registry is used for service discovery
  • Selector Used for load balancing
  • Client is used to send requests
  • Server is used to process requests

Registries provide a service discovery mechanism to resolve service names to addresses. It can be supported using Consul, ETcd, ZooKeeper, DNS, Gossip, and more. Services are registered by starting registration shutdown uninstallation. The service can optionally provide expiration TTL and scheduled re-registration to keep the service online, and to clean it up when it goes offline.

A Selector is a load-balancing abstraction built on top of a registry. It allows services to be filtered out without being served by filtering functions, or selected to be served by selecting the appropriate algorithm, which can be random, polling (client balancing), least linking (leastconn), and so on. The selector takes effect when the syntax is created through the client. The client uses the selector instead of the registry because it provides a built-in load balancing mechanism.

Transport Transport is the communication interface for synchronizing requests/responses between services. Similar to Golang’s NET package, but with a higher level of abstraction, allow us to switch communication mechanisms such as HTTP, RabbitMQ, WebSockets, and NATs. Transport also supports bidirectional streaming, a powerful feature that allows clients to push data to the server.

Brokers provide a publish/subscribe interface to messages for asynchronous communication. Publish/subscribe is fundamental to microservice systems and event-driven architectures. To start, we use a point-to-point HTTP system in the inbox style by default to minimize the number of dependencies. However, go-plugins provide message broker implementations such as RabbitMQ, NATS, NSQ, Google Cloud Pub Sub, and so on.

Encoding (Codec) Encoding packages are used to encode and decode messages as they are transmitted to both ends. They can be JSON, Protobuf, Bson, MSgpack, and so on. Unlike other encodings, we support the RPC format. So we have JSON-RPC, Proto-RPC, Bson-RPC, etc.

The coding package isolates the client-side coding from the server-side coding and provides a powerful way to integrate other systems, such as gRPC, Vanadium, and so on.

A Server package is a build package that uses authoring services to name services, register request handlers, add middleware, and so on. Services are built on top of the packages described above and provide a separate interface to service requests. Services are currently built as RPC systems, and there may be other implementations in the future. The server side allows you to define multiple different encodings to serve different encoded messages.

The Client provides an interface to create requests to the server. Like a server, it is built on top of other packages, providing a separate interface to discover services by name through a registry, load balancing based on selectors, and handling synchronous and asynchronous messages using transport and broker.

All of these components can be thought of as services in micro at a higher level.

An example of official Greeter

If you use GOPROXY to download dependencies from the three command lines at the beginning of this article, there is a problem. The examples you get are not up to date. There are a lot of errors, so my own solution is to switch the directory directly to

cd  $GOPATH/pkg/mod/github/micro

git clone github.com/micro/examples  examples

cd examples/greeter
Copy the code

Git Clone can be used to download the greeter example from the official website

{"id":"go.micro.client"."code": 500,"detail":"error selecting go.micro.srv.greeter node: not found"."status":"Internal Server Error"}
Copy the code

At the beginning, I couldn’t find the reason, so I went to Github to ask questions in broken English and made a fool of myself. Haha, but just learn something, that’s how I comfort myself. When I run the example, I execute only three scripts:

go run api/api.go micro api --handler=api curl http://localhost:8080/greeter/say/hello? name=JohnCopy the code

The first two commands are normal, but the third one fails. To make an issue, a foreigner replied to me quickly, but I was still confused. Finally try to execute first

go run srv/main.go
Copy the code

On the normal, the current code of logic understanding is not deep, later back to explore it. Consul has not been specified in the latest version of the registry. Running Micro Web, you can start the Micro Web tools collection and access localhost:8082 to see the registered micro service name.

go run main.go --registry=consul 
Copy the code

You can find the service registered in Consul’s UI control panel (go.Micro-srv.Greeter)

Aside from my personal experience, in daily development, if you encounter a problem that you cannot overcome, you can consult more information and others. If you cannot solve it for the time being, you can put it down and look back at it once in a while. In most cases, you will come up with new ideas and solutions. There is code if the logic is too complex, please stop and think about whether their implementation ideas have problems, most of them are the implementation of the problem, there will not be very complex code. I had no one around to ask for advice when I met problems before. Actually, that’s wrong. It’s a waste of time.

Write your own services

Once the official sample works, try writing your own service. According to what I mentioned earlier

How can I use micro?

  • Write the service using Go-Micro.
  • Use the Micro toolset to access these services

Let’s see what kind of demons you’ll encounter if you follow these two steps

Service prototype

A key requirement in microservices is a strong definition of the interface. Micro uses Protobuf to fulfill this requirement. Create folder Popular/Proto under GOPATH

touch popular.proto
Copy the code

After you have created the prototype file, edit the file

syntax = "proto3";

service Popular {
	rpc Ping(PingRequest) returns (PingResponse) {}
}

message PingRequest {
	string name = 1;
}

message PingResponse {
	string popularing = 2;
}
Copy the code

The first line of the file specifies that you are using proto3 syntax. We define the Popular handler, which has a Ping method. It has a PingRequest input object and a PingResponse output object, both of which take a string parameter.

prototyping

Once the prototype is defined we have to compile it using protoc and micro plug-ins which help generate the prototype files that go Micro needs. Switch to the $GOPATH/ SRC directory and run the following command:

protoc --proto_path=$GOPATH/src/popular/proto:. --micro_out=. --go_out=. popular/proto/popular.proto
Copy the code

An error may occur when running this command

-bash: protoc: command not found
Copy the code

The following tools are needed to generate the Protobuf code files, which are responsible for generating the defined GO code implementation

  • protoc
  • protoc-gen-go
  • protoc-gen-micro
Brew install protobuf // If it fails, download the source code package and compile it yourself, add it to the environment variable, I am so full of go get github.com/golang/protobuf/ {proto, protoc - gen - go} go get github.com/micro/protoc-gen-microCopy the code

– Protobuf source code compilation and installation will have some errors, just ignore it. Install the reference

It will be generated in the proto folder when everything is normal

popular.micro.go	popular.pb.go
Copy the code

Write the service

Several requirements need to be implemented:

  • Implements the interface defined in the Popular Handler.
  • Initialize the micro. Service
  • Register the Popular handler
  • Run the service

Switch to the popular folder and create the file main.go

cd popular && touch main.go
Copy the code

Edit the main.go file

package main

import (
	"context"
	"fmt"
	micro "github.com/micro/go-micro"
	proto "popular/proto"
)

type Popular struct{}

func (g *Popular) Ping(ctx context.Context, req *proto.PingRequest, rsp *proto.PingResponse) error {
	rsp.Popularing = "Ping "+ req.Name // (Popularing, Name starts with a capital letter)return nil
}

func main() {// Create a new service, where you can pass in other options. service := micro.NewService( micro.Name("popular"), / / initialization method parses the command line identification service. The Init () / / registered processor proto RegisterPopularHandler (service. The Server (), new (Popular)) / / run the serviceiferr := service.Run(); err ! = nil { fmt.Println(err) } }Copy the code

[Stuck here can not move, the reason does not say…] Dry a whole day, finally put the micro service set up, there is time to sort out the article, have to rest, dizziness. Post a map: Service discovery and registration is using Consul

So much for this article on the server side

If you want to go further, you can read my next article: Micro-services based on Golang — Micro Practices (PART 2)