1. 编写服务
这是编写服务及其相关的内部内容的更详细的指南. 顶级 服务 接口是构建服务的主要组件. 它将 Go Micro 的所有基础包包装到一个便捷的接口中.
type Service interface {
Init(...Option)
Options() Options
Client() client.Client
Server() server.Server
Run() error
String() string
}
1.1.1. 1. 初始化
像这样使用 micro.NewService
创建服务。
import "github.com/micro/go-micro/v2"
service := micro.NewService()
选项可以在创建期间传入.
service := micro.NewService(
micro.Name("greeter"),
micro.Version("latest"),
)
所有可用的选项都可以 在这里 找到.
Go Micro 还提供一种使用 micro.Flags
设置命令行标志的方法.
import (
"github.com/micro/cli"
"github.com/micro/go-micro/v2"
)
service := micro.NewService(
micro.Flags(
cli.StringFlag{
Name: "environment",
Usage: "The environment",
},
)
)
要分析标志请使用 service.Init``micro.Action
此外访问标志使用该选项.
service.Init(
micro.Action(func(c *cli.Context) {
env := c.StringFlag("environment")
if len(env) > 0 {
fmt.Println("Environment set to", env)
}
}),
)
Go Micro 提供预定义的标志, 如果调用 service.Init
这些标志将设置和解析. 在此处查看 所有标志
1.1.2. 2. 定义 API
我们使用原型文件来定义服务 API 接口. 这是一种非常方便的方法来严格定义 API 并为服务器和客户端提供具体类型.
下面是一个示例定义。
greeter.proto
syntax = "proto3";
service Greeter {
rpc Hello(Request) returns (Response) {}
}
message Request {
string name = 1;
}
message Response {
string greeting = 2;
}
在这里我们定义一个服务处理程序称为 Greeter 与 Hello 的方法, 它采取参数请求类型并返回响应.
1.1.3. 3. 生成 API 接口
您需要以下规则来生成原型代码
我们使用 protoc, protoc-gen-go, protoc-gen-micro 来生成此定义的具体实现.
go get github.com/golang/protobuf/{proto,protoc-gen-go}
go get github.com/micro/micro/v2/cmd/protoc-gen-micro@master
protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. greeter.proto
现在在发出请求时, 可以在服务器或客户端的 handler 中导入和使用生成的类型.
下面是生成的代码的一部分.
type Request struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}
type Response struct {
Greeting string `protobuf:"bytes,2,opt,name=greeting" json:"greeting,omitempty"`
}
// Client API for Greeter service
type GreeterClient interface {
Hello(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error)
}
type greeterClient struct {
c client.Client
serviceName string
}
func NewGreeterClient(serviceName string, c client.Client) GreeterClient {
if c == nil {
c = client.NewClient()
}
if len(serviceName) == 0 {
serviceName = "greeter"
}
return &greeterClient{
c: c,
serviceName: serviceName,
}
}
func (c *greeterClient) Hello(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) {
req := c.c.NewRequest(c.serviceName, "Greeter.Hello", in)
out := new(Response)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Greeter service
type GreeterHandler interface {
Hello(context.Context, *Request, *Response) error
}
func RegisterGreeterHandler(s server.Server, hdlr GreeterHandler) {
s.Handle(s.NewHandler(&Greeter{hdlr}))
}
1.1.4. 4. 实现处理程序
服务器需要注册 处理程序 以服务请求. 处理程序是一种公共类型, 具有符合签名 func(ctx context.Context, req interface{}, rsp interface{}) error
的公共方法.
如上所示, Greeter 接口的处理程序签名如下所示.
type GreeterHandler interface {
Hello(context.Context, *Request, *Response) error
}
下面是 Greeter 处理程序的实现.
import proto "github.com/micro/examples/service/proto"
type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
rsp.Greeting = "Hello " + req.Name
return nil
}
处理程序在服务中注册, 就像 http.Handler 一样.
service := micro.NewService(
micro.Name("greeter"),
)
pb.RegisterGreeterHandler(service.Server(), new(Greeter))
您还可以创建双向流式处理器, 但我们会将该处理程序留给另一天.
1.1.5. 5. 运行服务
该服务可以通过调用 server.Run
来运行. 这将导致服务绑定到配置中的地址 (默认为找到的第一个 RFC1918 接口和一个随机端口), 并侦听请求.
这还将在启动时向注册表注册服务, 并在发出终止信号时注销.
if err := service.Run(); err != nil {
log.Fatal(err)
}
1.1.6. 6. 完整的服务
greeter.go
package main
import (
"log"
"github.com/micro/go-micro/v2"
pb "github.com/micro/examples/service/proto"
"golang.org/x/net/context"
)
type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
rsp.Greeting = "Hello " + req.Name
return nil
}
func main() {
service := micro.NewService(
micro.Name("greeter"),
)
service.Init()
pb.RegisterGreeterHandler(service.Server(), new(Greeter))
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
注意服务发现机制需要运行, 以便服务可以注册以被客户端和其他服务发现. 一个快速开始 在这里.
1.2. 编写客户端
客户端 包用于查询服务. 创建服务时, 将包含与服务器使用的初始包匹配的客户端.
查询上述服务非常简单.
// create the greeter client using the service name and client
greeter := pb.NewGreeterService("greeter", service.Client())
// request the Hello method on the Greeter handler
rsp, err := greeter.Hello(context.TODO(), &pb.Request{
Name: "John",
})
if err != nil {
fmt.Println(err)
return
}
fmt.Println(rsp.Greeting)
pb.NewGreeterClient
获取用于发出请求的服务名称和客户端.
完整的例子可以在这里 go-micro/examples/service 中找到.