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.
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.
Sidecar
The HTTP interface version of go-micro. This is a way to integrate non-Go applications into the microenvironment.
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.
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.
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.