Go Micro 创建 API
Go Micro API 服务是对 SRV RPC服务的封装,它将请求装换为 RPC 请求转给 SRV RPC 服务,并将 SRV RPC 的处理结果返回客户端。
我们可以使用 Go Micro 的 micro 工具创建 API 服务。例如,创建 hello API 服务:
micro new --type=api hello
以下是 micro 创建的 API 服务的文件结构:
. ├── main.go ├── generate.go ├── plugin.go ├── client │ └── hello.go ├── handler │ └── hello.go ├── proto/hello │ └── hello.proto ├── Makefile ├── Dockerfile └── README.md
1. main.go
package main import ( "github.com/micro/go-micro/util/log" "github.com/micro/go-micro" "hello/handler" "hello/client" hello "hello/proto/hello" ) func main() { // 创建一个新的服务,服务名为 go.micro.api.hello service := micro.NewService( micro.Name("go.micro.api.hello"), micro.Version("latest"), ) // 通过命令行参数或者插件初始化服务 service.Init( // 为 hello srv客户端创建封装 wrap。 micro.WrapHandler(client.HelloWrapper(service)), ) // 注册业务处理组件 handler.Hello hello.RegisterHelloHandler(service.Server(), new(handler.Hello)) // 运行服务 if err := service.Run(); err != nil { log.Fatal(err) } }
2. proto/hello/hello.proto
syntax = "proto3"; package go.micro.api.hello; option go_package="proto/hello"; service Hello { rpc Call(Request) returns (Response) {} } message Request { string name = 1; } message Response { string msg = 1; }
执行 make 命令进行编译:
make proto
编译后生成 proto/hello/hello.pb.micro.go 和 proto/hello/hello.pb.go 文件。
3. handler/hello.go
package handler import ( "context" "github.com/micro/go-micro/util/log" api "github.com/micro/go-micro/api/proto" "github.com/micro/go-micro/errors" "hello/client" "hello/proto/hello" ) type Hello struct{} func extractValue(pair *api.Pair) string { if pair == nil { return "" } if len(pair.Values) == 0 { return "" } return pair.Values[0] } // Hello.Call is called by the API as /hello/call with post body {"name": "foo"} func (e *Hello) Call(ctx context.Context, req *hello.Request, rsp *hello.Response) error { log.Log("Received Hello.Call request") // extract the client from the context helloClient, ok := client.HelloFromContext(ctx) if !ok { return errors.InternalServerError("go.micro.api.hello.hello.call", "hello client not found") } // make request response, err := helloClient.Call(ctx, &hello.Request{ Name: req.Name, }) if err != nil { return errors.InternalServerError("go.micro.api.hello.hello.call", err.Error()) } rsp.Msg = response.Msg return nil }
4. client/hello.go
package client import ( "context" "github.com/micro/go-micro" "github.com/micro/go-micro/server" hello "hello/proto/hello" ) type helloKey struct {} // FromContext retrieves the client from the Context func HelloFromContext(ctx context.Context) (hello.HelloService, bool) { c, ok := ctx.Value(helloKey{}).(hello.HelloService) return c, ok } // Client returns a wrapper for the HelloClient func HelloWrapper(service micro.Service) server.HandlerWrapper { client := hello.NewHelloService("go.micro.srv.hello", service.Client()) return func(fn server.HandlerFunc) server.HandlerFunc { return func(ctx context.Context, req server.Request, rsp interface{}) error { ctx = context.WithValue(ctx, helloKey{}, client) return fn(ctx, req, rsp) } } }
5. 编译运行
make build
编译后生成可执行文件 hello_api,运行 hello_api。
nohup micro & ./hello_api
直接在浏览器中,输入 http://localhost:8080/hello.call。输出结果为:
{"msg":"success"}
Go Micro 插件 plugin:Go Micro plugin 会在每次调用服务的都会触发,根据注册的顺序进行调用,它的作用可以理解为拦截器。可以利用 plugin 实现拦截功能,比如鉴权,可结合 jwt 来实现。以下代码 plugi ...