为了让客户端能找到,Service需要一个服务发现的模块。Micro默认使用Consul,你也可以使用etcd,kubernetes…。这里使用Consul。
https://www.consul.io/intro/getting-started/install.html 下载自己的平台下编译好的二进制文件,然后放到PATH能检索到的位置。可以使用命令行测试consul --version
然后,我们先运行一个服务发现的实例:consul agent -dev -advertise=127.0.0.1
默认使用Protobuf,需要先安装好环境,https://github.com/google/protobuf/releases 下载,放到%GOPATH/bin%
下。
安装Go的插件go get -u github.com/golang/protobuf/protoc-gen-go
,默认生成在%GOPATH/bin%
下。
这种方式安装的Protobuf是针对一般使用场景,但是缺少部分Micro实现,所以需要使用Micro方式。
go get github.com/micro/protobuf/proto
go get -u github.com/micro/protobuf/protoc-gen-go
// 主要不同是需要 plugins=micro 这个选项,官方版没有这个功能
protoc -I. --go_out=plugins=micro:. *.proto
// server.go
package main
import (
"fmt"
"os"
"github.com/micro/cli"
proto "github.com/micro/examples/service/proto"
"github.com/micro/go-micro"
"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() {
// Create a new service. Optionally include some options here.
service := micro.NewService(
micro.Name("greeter"),
micro.Version("v1.0"),
micro.Metadata(map[string]string{
"type": "helloworld",
}),
)
// Init will parse the command line flags. Any flags set will
// override the above settings. Options defined here will
// override anything set on the command line.
service.Init(
// Add runtime action
// We could actually do this above
micro.Action(func(c *cli.Context) {
if c.Bool("run_client") {
//runClient(service)
os.Exit(0)
}
}),
)
// By default we'll run the server unless the flags catch us
// Setup the server
// Register handler
proto.RegisterGreeterHandler(service.Server(), new(Greeter))
// Run the server
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
客户端更简单:
// client.go
package main
import (
"fmt"
"github.com/micro/cli"
proto "github.com/micro/examples/service/proto"
"github.com/micro/go-micro"
"golang.org/x/net/context"
)
// Setup and the client
func runClient(service micro.Service) {
// Create new greeter client
greeter := proto.NewGreeterClient("greeter", service.Client())
// Call the greeter
rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "John"})
if err != nil {
fmt.Println(err)
return
}
// Print response
fmt.Println(rsp.Greeting)
}
func main(){
// Create a new service. Optionally include some options here.
service := micro.NewService(
micro.Name("greeter"),
micro.Version("v1.0"),
micro.Metadata(map[string]string{
"type": "helloworld",
}),
// Setup some flags. Specify --run_client to run the client
// Add runtime flags
// We could do this below too
micro.Flags(cli.BoolFlag{
Name: "run_client",
Usage: "Launch the client",
}),
)
runClient(service)
}
执行测试:
go run server.go
// 稍等片刻
go run client.go
Web页面: http://localhost:8500/ui
在浏览器中输入 http://127.0.0.1:8500/v1/health/service/greeter 能看到服务的状态。
This directory contains templates generated with the micro new [service]
command.
Find out more on the usage at micro/new.
micro new --type api --alias template github.com/micro/examples/template/api
micro new --type fnc --alias template github.com/micro/examples/template/fnc
micro new --type srv --alias template github.com/micro/examples/template/srv
micro new --type web --alias template github.com/micro/examples/template/web
微服务是一个庞大的话题,它包含几个核心的问题点:
1. 服务发现与治理
2. 负载均衡,高可用,健康检查
3. RPC,IPC,HTTP,编解码
4. 不用语言下的开发和集成问题
5. 服务运维,包含看板等
其中,1、2有很多可用/参考的方案。3、4是开发效率和可扩展性的问题。5是运维以及是否能长期使用的问题。
后面,我们从每个方面一一学习。