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:Go Micro plugin 会在每次调用服务的都会触发,根据注册的顺序进行调用,它的作用可以理解为拦截器。可以利用 plugin 实现拦截功能,比如鉴权,可结合 jwt 来实现。以下代码 plugi ...