By Zhang Binbin, Nacos Committer and Sentinel-Golang Contributor
This article describes how the microservice framework Go-Micro (v2) in the Golang ecosystem integrates with Nacos for service registration and discovery. Go-Micro is currently in v3, but the project has been renamed nitro.
Go-Micro is a basic framework for building microservices based on Go. It provides the core components required for distributed development, including RPC and event-driven communication.
It is designed as a "pluggable" plug-in architecture. Its core focuses on providing underlying interface definitions and basic tools, which can be compatible with various implementations. For example, Go-Micro uses Consul to discover services and communicate through the HTTP protocol. Encoding and decoding are conducted through protobuf and JSON for quick-start based on these out-of-the-box components. If necessary, you can replace the default components with other components that conform to the underlying interface definitions, such as Nacos, etcd, or ZooKeeper, for service discovery. This is the advantage of plug-in architecture; the replacement of upper-layer components can be implemented without modifying any underlying code.
Go-Micro is a microservices toolkit that includes:
API provides and routes HTTP requests to the API Gateway of the corresponding microservice. It acts as a single entry for microservice access. It converts HTTP requests into RPC and forwards them to corresponding services. It can also be used for reverse proxy.
Web UI is the web version of Go-Micro. Web UI allows users to access the environment interactively through the UI. In the future, it will be a way to aggregate micro web services. It includes a proxy of web applications. After routing /[name] to the appropriate service through the registry, Web UI will prefix configurable "go.micro.web." to the name. Then, Web UI searches for the prefix in the registry, and the reverse proxy will be carried out.
Sidecar is the HTTP interface version of Go-Micro, which is a way to integrate non-Go applications into the microenvironment.
Bot in Hubot style is located in your microservice platform and can interact through Slack, HipChat, and XMPP. It provides Command Line Interface (CLI) through messaging. You can add additional commands to execute common operational tasks automatically.
CLI is a direct command line interface that can interact with your microservices. It provides a way to observe and interact with the running environment.
Components form the plug-in RPC framework for writing microservices in Go. It provides service discovery, client load balance, encoding, and synchronous and asynchronous communication libraries. Go-Micro is an independent library that can be used independently of other toolkits.
Go-Micro is a component-based framework. Each basic function is an interface for easy extension. Besides, the components are layered. The upper layer provides services based on the lower-layer functions, forming the overall Go-Micro framework. The components of the Go-Micro framework include:
Registry provides a service discovery mechanism that parses the service name into the service address. Currently, the supported registries include Consul, etcd, ZooKeeper, DNS, and Gossip.
Selectors provide load balance mechanisms through selection. When a client makes a request to the server, the selector will query the registry of the service first. This usually returns a node list of running services. The selector selects one of these nodes for the query. The use of a balancing algorithm is allowed in multiple calls to selectors. The current methods are loop, random hash, and blacklist.
Broker is a plug-in interface for publishing and subscription. Services communicate with each other through asynchronous communication of a message-oriented middleware. HTTP is used by default. Message-oriented middleware is commonly used online, including NATS, Kafka, RabbitMQ, and HTTP (for development.)
Transport is a plug-in interface for message transmission through point-to-point. The current implementations are HTTP, RabbitMQ, and NATS. After providing this abstraction, the communication mechanism can be switched seamlessly.
Codec is used for encoding and decoding messages between services.
Plugins provide the micro/go-plugins plug-in of Go-Micro.
A server is an interface for building a running microservice. It provides a way to offer RPC requests. Based on the preceding Registry, Selector, Transport, and Broker, this component provides a unified service request entry externally.
Client provides an RPC query method to access the microservice client. It combines with Registry, Selector, Proxy, and Transport. It also provides functions in retries, timeouts, and usage of context. Similar to the Server component, Client uses the Registry, Selector, Transport, and Broker to implement search services, load balance, synchronous communication, and asynchronous messaging.
Nacos is a platform for building dynamic service discovery and configuration and service management of cloud-native applications. Nacos is derived from ConfigServer and Diamond of Alibaba and is their open-source implementation. After experiencing the traffic peak during the Double 11 Global Shopping Festival and the ultra-large scale of Alibaba's economy, Nacos draws on ten years of experience from Alibaba's Software Load Team. This experience guarantees the stability and functionality of Nacos.
Protocol Buffers (Protobuf) is a data description language developed by Google. It was made open-source in 2008. In the beginning, Protobuf was designed to be a data description language similar to XML and JSON to generate code and serialize structured data through accompanying tools. We need to use protoc to generate the server code.
go get github.com/golang/protobuf/protoc-gen-go
Install Go-Micro v2
go install github.com/micro/micro/v2
Create a Golang project on the server:
1. Create a proto folder under the root directory of the project to store protobuf files
2. Create a greeter.proto file in the proto folder
3. The file contents are listed below:
On the server, the protobuf file is used to define a processor called Greeter. Greeter has a Hello method that receives HelloRequest
and returns HelloResponse
.
syntax = "proto3";
package helloworld;
service Greeter {
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 2;
}
4. Generate the corresponding Go code
protoc --micro_out=. --go_out=. proto/greeter.proto
5. In the proto directory, two files, pb.go and pb.micro.go, are generated.
6. Create and run the server.go
package main
import (
"context"
helloworld "go-micro-nacos-demo1/proto"
"github.com/micro/go-micro/v2"
"github.com/micro/go-micro/v2/logger"
"github.com/micro/go-micro/v2/registry"
nacos "github.com/micro/go-plugins/registry/nacos/v2"
)
type Helloworld struct{}
// Call is a single request handler called via client.Call or the generated client code
func (e *Helloworld) Hello(ctx context.Context, req *helloworld.HelloRequest, rsp *helloworld.HelloResponse) error {
logger.Info("Received Helloworld.Call request")
return nil
}
func main() {
addrs := make([]string, 1)
addrs[0] = "console.nacos.io:80"
registry := nacos.NewRegistry(func(options *registry.Options) {
options.Addrs = addrs
})
service := micro.NewService(
// Set service name
micro.Name("my.micro.service"),
// Set service registry
micro.Registry(registry),
)
helloworld.RegisterGreeterHandler(service.Server(), new(Helloworld))
service.Run()
}
7. In the Nacos console, my.micro.service
is registered successfully.
1. Create client.go file. For demonstration purposes, this article creates client.go under the same project.
package main
import (
"context"
"fmt"
helloworld "go-micro-nacos-demo1/proto"
"github.com/micro/go-micro/v2"
"github.com/micro/go-micro/v2/registry"
nacos "github.com/micro/go-plugins/registry/nacos/v2"
)
const serverName = "my.micro.service"
func main() {
addrs := make([]string, 1)
addrs[0] = "console.nacos.io:80"
r := nacos.NewRegistry(func(options *registry.Options) {
options.Addrs = addrs
})
// Define the service. Other optional parameters can be introduced.
service := micro.NewService(
micro.Name("my.micro.service.client"),
micro.Registry(r))
// Create a new client.
greeter := helloworld.NewGreeterService(serverName, service.Client())
// Call greeter.
rsp, err := greeter.Hello(context.TODO(), &helloworld.HelloRequest{Name: "John"})
if err != nil {
fmt.Println(err)
}
//Obtain all services.
fmt.Println(registry.ListServices())
//Obtain a specific service.
services, err := registry.GetService(serverName)
if err != nil {
fmt.Println(err)
}
//Listening service.
watch, err := registry.Watch()
fmt.Println(services)
// Print response requests.
fmt.Println(rsp.Greeting)
go service.Run()
for {
result, err := watch.Next()
if len(result.Action) > 0 {
fmt.Println(result, err)
}
}
}
2. Run the client. In the Nacos console, the client service is also registered in Nacos.
3. Call logs are printed on the server.go console
Server: Use Go-Micro to create a server Demo and register the Demo in Nacos
registry := nacos.NewRegistry(func(options *registry.Options) {
options.Addrs = addrs
})
service := micro.NewService(
// Set service name
micro.Name("my.micro.service"),
// Set service registry
micro.Registry(registry),
)
service.Run()
Use Go-Micro to create a client Demo, and register the Demo in Nacos.
r := nacos.NewRegistry(func(options *registry.Options) {
options.Addrs = addrs
})
service := micro.NewService (
micro.Name("my.micro.service.client")
micro.Registry(r))
Call on the client:
// Create a client.
greeter := helloworld.NewGreeterService(serverName, service.Client())
// Call greeter.
rsp, err := greeter.Hello(context.TODO(), &helloworld.HelloRequest{Name: "John"})
Query the service list:
services,err:=registry.ListServices()
Obtain a service:
service, err := registry.GetService(serverName)
Subscript a service:
watch, err := registry.Watch()
for {
result, err := watch.Next()
if len(result.Action) > 0 {
fmt.Println(result, err)
}
}
It is easy to register and discover services by integrating Go-Micro with Nacos. The Nacos client used by client.go in this project is the default configuration of Go-Micro. The registry interface in Go-Micro has a high degree of freedom. We can use context to configure parameters on the Nacos client. For setting parameters on Nacos client through context, please see this link.
Zhang Binbin is a Nacos Committer and Sentinel-Golang Contributor, GitHub ID: sanxun0325. He is currently working on the OpenJaw Microservice Team, mainly responsible for the development of Nacos and related projects of the Sentinel-Golang community. He is also responsible for the promotion and integration of Nacos in the Golang microservice ecosystem.
204 posts | 12 followers
FollowAliware - February 5, 2021
Alibaba Cloud Community - May 6, 2024
Alibaba Cloud Native Community - April 6, 2023
Alibaba Developer - May 31, 2021
Aliware - April 10, 2020
Alibaba Cloud Native Community - March 11, 2024
204 posts | 12 followers
FollowMSE provides a fully managed registration and configuration center, and gateway and microservices governance capabilities.
Learn MoreAccelerate and secure the development, deployment, and management of containerized applications cost-effectively.
Learn MoreAlibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.
Learn MoreLindorm is an elastic cloud-native database service that supports multiple data models. It is capable of processing various types of data and is compatible with multiple database engine, such as Apache HBase®, Apache Cassandra®, and OpenTSDB.
Learn MoreMore Posts by Alibaba Cloud Native