"Go-micro" study notes-Micro

Micro overview

Micro is a platform for cloud native development.

Micro is a microservice toolkit that includes:

API

Provide and route HTTP requests to the API gateway of the corresponding microservice. It acts as a single entry point for microservice access, converts HTTP requests into RPC and forwards them to the corresponding service, and can also be used as a reverse proxy.

image

Web

UI is the web version of go-micro, allowing interactive access to the environment through the UI. In the future, it will also be a way to aggregate micro Web services. It contains a proxy method for web applications. Route /[name] to the corresponding service through the registry. Web UI adds the prefix "go.micro.web." (configurable) to the name, looks for it in the registry, and then reverse proxy will be performed.

image

Sidecar

The HTTP interface version of go-micro. This is a way to integrate non-Go applications into the microenvironment.
image

Bot

Hubot-style bot, located in your microservice platform, can interact through Slack, HipChat, XMPP, etc. It provides CLI functionality through messaging. You can add other commands to automate common operational tasks.
image

CLI

A direct command line interface to interact with your microservices, it provides a way to observe and interact with the running environment.

Go-Micro

A plug-in RPC framework for writing microservices in Go. It provides libraries for service discovery, client load balancing, coding, synchronous and asynchronous communication. go-micro is an independent library that can be used independently of other toolkits.

image
go-micro is a componentized framework, and each basic function is an interface, which is convenient for expansion. At the same time, the components are layered, and the upper layer provides services upward based on the functions of the lower layer, forming a go-micro framework as a whole. The components of the go-micro framework are:

Registry

Provide service discovery mechanism: resolve service name to service address. Currently supported registry centers include consul, etcd, zookeeper, dns, gossip, etc.

Selector

The selector provides a load balancing mechanism through selection. When the client sends a request to the server, it will first query the service registry. This usually returns a list of running nodes representing the service. The selector will select one of these nodes for query. Calling the selector multiple times will allow the balance algorithm to be used. The current methods are round-robin, random hashing and blacklisting.

Broker

Pluggable interface for publish and subscribe, asynchronous communication between services based on message middleware, http mode is used by default, and message middleware is usually used online, such as Nats, Kafka, RabbitMQ and http (for development).

Transport

A pluggable interface for point-to-point transmission of messages. The current implementations are http, rabbitmq and nats. By providing this abstraction, transportation can be swapped out seamlessly. .

Codec

Encoding/decoding of messages between services.

Plugins

Provide micro/go-plugins for go-micro .

Server

The server is the interface for building the running microservices. It provides a way to provide RPC requests. This component is based on the Registry/Selector/Transport/Broker component above, and provides a unified service request entry.

Client

Provides a method of making RPC queries to access the client of the microservice. It combines registry, selector, proxy and transport. It also provides retry, timeout, usage context, etc. Similar to the Server component, it also uses the Registry/Selector/Transport/Broker component to implement functions such as search services, load balancing, synchronous communication, and asynchronous messaging.


Installation and application

installation

Micro

# go get
$ go get github.com/micro/micro

# docker install
$ docker pull microhq/micro

Go-Micro

Go Micro is an RPC framework for Go development of microservices

$ go get github.com/micro/go-micro

protobuf

If you use code generation, you also need to use protoc-gen-go

$ go get github.com/micro/protobuf/{
    
    proto,protoc-gen-go}

gRPC gateway

protobuf

mkdir tmp
cd tmp
git clone https://github.com/google/protobuf
cd protobuf
./autogen.sh
./configure
make
make check
sudo make install

Install plugin

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go get -u github.com/micro/protobuf/protoc-gen-go

Test service

# 运行 greeter 服务,需要 consul 依赖
$ go get github.com/micro/examples/greeter/srv && srv

# 服务清单
$ micro list services
consul
go.micro.srv.greeter

# 获取服务
$ micro get service go.micro.srv.greeter

service  go.micro.srv.greeter

version 1.0.0

Id	Address	Port	Metadata
go.micro.srv.greeter-34c55534-368b-11e6-b732-68a86d0d36b6	192.168.1.66	62525	server=rpc,registry=consul,transport=http,broker=http

Endpoint: Say.Hello
Metadata: stream=false

Request: {
    
    
	name string
}

Response: {
    
    
	msg string
}

# 查询服务
$ micro query go.micro.srv.greeter Say.Hello '{"name": "John"}'
{
    
    
	"msg": "Hello John"
}

Micro CLI application

Create service

# 新建一个 helloworld 的服务
$ micro new helloworld

Start and run services

# 在本地运行该服务并确保其正常工作.
# 启动服务器
micro server

# 设置为本地环境
micro env set local

# 启动你的服务
micro run name

service status

# 检查状态
micro status

# 检查是否已注册
micro services

# 检查日志
micro logs helloworld

End of service

micro kill helloworld

Deployment service

# 将代码上传到 Github 才能完成部署

# 初始化 git
cd helloworld && git init && git add . && git commit -m "My helloworld service"

# 在 github 创建一个新的仓库并推送上去
# assuming you created it, add the remote origin
git remote add origin https://github.com/$user/helloworld.git

# 推送
git push origin master

# 设置环境为平台模式
micro env set platform

# 确保已经登陆到平台
micro login

# 现在可以运行了
micro run github.com/$user/helloworld

Call service

Check that the service is running and call the service. In addition, because it is built from source code, it may take several minutes to start (we will optimize this situation later)

# 检查服务状态
micro status

# 检查服务注册情况
micro services

# 调用指定的服务
micro helloworld --name=Alice

Pay attention to the symbols used to call the service. Micro supports dynamic CLI commands, which means that anything in your namespace will become a subcommand.

micro [service] [endpoint] [args]

Where the endpoint is submitted, we assume it is the service name + the "call" method, for example, helloworld becomes Helloworld. call. If this is a greeting method, we will assume Helloworld. The greeting and c are in c.micro helloworld greet

We assume that a method with a service name + "Call" is an endpoint. For example, helloworld will be Helloworld.Call. If it is the Greet method, we will assume that the command corresponding to Helloworld.Greet is micro helloworld greet.

Parameters can be passed as flags--name represents the Name field parameter.

If you want a simpler way using pure json and raw methods

micro call helloworld Helloworld.Call '{"name": "Alice"}'

Go-micro framework application

Greeter service

Created a Greeter microservice using go-grpc.

  • The prototype is as follows:
syntax = "proto3";

package go.micro.srv.greeter;

service Say {
    
    
	rpc Hello(Request) returns (Response) {
    
    }
}

message Request {
    
    
	string name = 1;
}

message Response {
    
    
	string msg = 1;
}
  • The services are as follows:
package main

import (
	"log"
	"time"

	hello "github.com/micro/examples/greeter/srv/proto/hello"
	"github.com/micro/go-grpc"
	"github.com/micro/go-micro"

	"golang.org/x/net/context"
)

type Say struct{
    
    }

func (s *Say) Hello(ctx context.Context, req *hello.Request, rsp *hello.Response) error {
    
    
	log.Print("Received Say.Hello request")
	rsp.Msg = "Hello " + req.Name
	return nil
}

func main() {
    
    
	service := grpc.NewService(
		micro.Name("go.micro.srv.greeter"),
		micro.RegisterTTL(time.Second*30),
		micro.RegisterInterval(time.Second*10),
	)

	// optionally setup command line usage
	service.Init()

	// Register Handlers
	hello.RegisterSayHandler(service.Server(), new(Say))

	// Run server
	if err := service.Run(); err != nil {
    
    
		log.Fatal(err)
	}
}

GRPC gateway

The grpc gateway uses the same protocol as the service, and adds an http option

syntax = "proto3";

package greeter;

import "google/api/annotations.proto";

service Say {
    
    
	rpc Hello(Request) returns (Response) {
    
    
		option (google.api.http) = {
    
    
			post: "/greeter/hello"
			body: "*"
		};
	}
}

message Request {
    
    
	string name = 1;
}

message Response {
    
    
	string msg = 1;
}

proto use the following commands to generate grpc stub and reverse proxy

protoc -I/usr/local/include -I. \
  -I$GOPATH/src \
  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
  --go_out=plugins=grpc:. \
  path/to/your_service.proto
protoc -I/usr/local/include -I. \
  -I$GOPATH/src \
  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
  --grpc-gateway_out=logtostderr=true:. \
  path/to/your_service.proto

We used the following code to create a sample api for the greeter service. Similar code will be written to register other endpoints. Please note that the gateway needs the port address of the greeter service.

package main

import (
	"flag"
	"net/http"

	"github.com/golang/glog"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"golang.org/x/net/context"
	"google.golang.org/grpc"

	hello "github.com/micro/examples/grpc/gateway/proto/hello"
)

var (
	// the go.micro.srv.greeter address
	endpoint = flag.String("endpoint", "localhost:9090", "go.micro.srv.greeter address")
)

func run() error {
    
    
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	mux := runtime.NewServeMux()
	opts := []grpc.DialOption{
    
    grpc.WithInsecure()}

	err := hello.RegisterSayHandlerFromEndpoint(ctx, mux, *endpoint, opts)
	if err != nil {
    
    
		return err
	}

	return http.ListenAndServe(":8080", mux)
}

func main() {
    
    
	flag.Parse()

	defer glog.Flush()

	if err := run(); err != nil {
    
    
		glog.Fatal(err)
	}
}

Run example

Run the greeter service. Specify mdns because we don't need discovery.

go run examples/grpc/greeter/srv/main.go --registry=mdns --server_address=localhost:9090

Run the gateway. It will default to the greeter service at the endpoint localhost:9090.

go run examples/grpc/gateway/main.go

Use curl to initiate a request on the (localhost:8080) gateway.

curl -d '{"name": "john"}' http://localhost:8080/greeter/hello

Execute protocommand to generate the current pb files go to achieve:

protoc --go_out=plugins=micro:. ./proto/hello.proto

protoc  --go_out=. --micro_out=. ./proto/hello.proto

Write a go service

  • Define API
    We use protobuf file to define service API interface. This is a very convenient way to strictly define the API and provide specific types for the server and client.

    // this is greeter.proto
    syntax = "proto3";
    
    service Greeter {
          
          
    	rpc Hello(HelloRequest) returns (HelloResponse) {
          
          }
    }
    
    message HelloRequest {
          
          
    	string name = 1;
    }
    
    message HelloResponse {
          
          
    	string greeting = 2;
    }
    

    Here, we define a service handler named Greeter, where the method Hello uses the parameter HelloRequest type and returns HelloResponse.

  • Generate API interface
    Use protoc and protoc-gen-go to generate a specific go implementation for this definition.

    protoc --go_out=plugins=micro:. greeter.proto
    
  • Write a service

    package main
    
    import (
            "log"
    
            "github.com/micro/go-micro"
            proto "github.com/micro/examples/service/proto"
    
            "golang.org/x/net/context"
    )
    
    type Greeter struct{
          
          }
    
    func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error {
          
          
            rsp.Greeting = "Hello " + req.Name
            return nil
    }
    
    func main() {
          
          
            service := micro.NewService(
                    micro.Name("greeter"),
                    micro.Version("latest"),
            )
    
            service.Init()
    
            proto.RegisterGreeterHandler(service.Server(), new(Greeter))
    
            if err := service.Run(); err != nil {
          
          
                    log.Fatal(err)
            }
    }
    
  • Write a client

    // create the greeter client using the service name and client
    greeter := proto.NewGreeterClient("greeter", service.Client())
    
    // request the Hello method on the Greeter handler
    rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{
          
          
    	Name: "John",
    })
    if err != nil {
          
          
    	fmt.Println(err)
    	return
    }
    
    fmt.Println(rsp.Greeter)
    

Service Communication

The communication between the two microservices is based on the C/S model, that is, the service requester acts as the Client and the service receiver acts as the Server.
image

Guess you like

Origin blog.csdn.net/zd398900463/article/details/109208026