关于micro:go-micro-wrapper-中间件

5次阅读

共计 5101 个字符,预计需要花费 13 分钟才能阅读完成。

go micro wrapper 中间件

本篇不波及中间件底层是如何运作的,如有趣味请见 [micro server] 篇

在 options.go 中有如下定义

// WrapClient is a convenience method for wrapping a Client with
// some middleware component. A list of wrappers can be provided.
// Wrappers are applied in reverse order so the last is executed first.
func WrapClient(w ...client.Wrapper) Option {return func(o *Options) {
        // apply in reverse
        for i := len(w); i > 0; i-- {o.Client = w[i-1](o.Client)
        }
    }
}

// WrapCall is a convenience method for wrapping a Client CallFunc
func WrapCall(w ...client.CallWrapper) Option {return func(o *Options) {o.Client.Init(client.WrapCall(w...))
    }
}

// WrapHandler adds a handler Wrapper to a list of options passed into the server
func WrapHandler(w ...server.HandlerWrapper) Option {return func(o *Options) {var wrappers []server.Option

        for _, wrap := range w {wrappers = append(wrappers, server.WrapHandler(wrap))
        }

        // Init once
        o.Server.Init(wrappers...)
    }
}

// WrapSubscriber adds a subscriber Wrapper to a list of options passed into the server
func WrapSubscriber(w ...server.SubscriberWrapper) Option {return func(o *Options) {var wrappers []server.Option

        for _, wrap := range w {wrappers = append(wrappers, server.WrapSubscriber(wrap))
        }

        // Init once
        o.Server.Init(wrappers...)
    }
}

这些参数设置用于 micro.NewService() 参数

有以下几种类型

  1. WrapClient() 用于用一些中间件组件包装 Client, 包装器以相同的程序利用,因而最初一个先执行。
  2. WrapCall() 用于不便包装 Client CallFunc
  3. WrapHandler() 将一系列 handler 中间件传给 server,并初始化
  4. WrapSubscriber() 将一系列 subscriber 中间件传给 server,并初始化

在 server/wrapper.go 中,定义了 wrapper

// HandlerFunc represents a single method of a handler. It's used primarily
// for the wrappers. What's handed to the actual method is the concrete
// request and response types.
type HandlerFunc func(ctx context.Context, req Request, rsp interface{}) error

// SubscriberFunc represents a single method of a subscriber. It's used primarily
// for the wrappers. What's handed to the actual method is the concrete
// publication message.
type SubscriberFunc func(ctx context.Context, msg Message) error

// HandlerWrapper wraps the HandlerFunc and returns the equivalent
type HandlerWrapper func(HandlerFunc) HandlerFunc

// SubscriberWrapper wraps the SubscriberFunc and returns the equivalent
type SubscriberWrapper func(SubscriberFunc) SubscriberFunc

// StreamWrapper wraps a Stream interface and returns the equivalent.
// Because streams exist for the lifetime of a method invocation this
// is a convenient way to wrap a Stream as its in use for trace, monitoring,
// metrics, etc.
type StreamWrapper func(Stream) Stream

服务端次要是

  1. HandlerWrapper() 用于 handler 处理器的中间件
  2. SubscriberWrapper() 用于订阅的中间件
  3. StreamWrapper() 用于流的中间件

在 client/wrapper.go 中,定义了 client 的中间件

// CallFunc represents the individual call func
type CallFunc func(ctx context.Context, node *registry.Node, req Request, rsp interface{}, opts CallOptions) error

// CallWrapper is a low level wrapper for the CallFunc
type CallWrapper func(CallFunc) CallFunc

// Wrapper wraps a client and returns a client
type Wrapper func(Client) Client

// StreamWrapper wraps a Stream and returns the equivalent
type StreamWrapper func(Stream) Stream

客户端次要是

  1. CallWrapper() client call 中间件
  2. Wrapper() client 中间件
  3. StreamWrapper() 流中间件

上面是一个 client 中间件 Wrapper 的例子

type logWrapper struct {client.Client}

func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {md, _ := metadata.FromContext(ctx)
    fmt.Printf("[Log Wrapper] ctx: %v service: %s method: %s\n", md, req.Service(), req.Endpoint())
    return l.Client.Call(ctx, req, rsp)
}

func NewLogWrapper(c client.Client) client.Client {return &logWrapper{c}
}

NewLogWrapper()实现了type Wrapper func(Client) Client

上面是一个 handler wrapper 的例子

func NewLogWrapper(fn server.HandlerFunc) server.HandlerFunc {return func(ctx context.Context, req server.Request, rsp interface{}) error {log.Printf("[Log Wrapper] Before serving request method: %v", req.Endpoint())
        err := fn(ctx, req, rsp)
        log.Printf("[Log Wrapper] After serving request")
        return err
    }
}

NewLogWrapper()实现了type HandlerWrapper func(HandlerFunc) HandlerFunc

HandlerFunc定义是type HandlerFunc func(ctx context.Context, req Request, rsp interface{}) error

所以咱们看到中间件都是函数里 return 的写法

具体实例能够参考官网 plugins 中的 opentracing wrapper 写法

https://github.com/micro/go-p…

这里包含

  1. client.Client 定义
  2. NewClientWrapper
  3. NewCallWrapper
  4. NewHandlerWrapper
  5. NewSubscriberWrapper

如果你想要实现本人的中间件,这里的官网实现是个不错的参考

Service Wrapper

很多时候须要从处理程序外部拜访服务。Service Wrapper 就是形式之一。它将服务嵌入到 ctx 中,这样就能够在 handler 中应用它。

srv := micro.NewService(micro.Name("com.example.srv.foo"),
)

srv.Init(micro.WrapClient(service.NewClientWrapper(srv))
    micro.WrapHandler(service.NewHandlerWrapper(srv)),
)

在 srv.Init()中增加 wrapper

在 handler 中能够这样应用 service

func (e *Example) Handler(ctx context.Context, req *example.Request, rsp *example.Response) error {service, ok := micro.FromContext(ctx)
    if !ok {return errors.InternalServerError("com.example.srv.foo", "Could not retrieve service")
    }

    // do something with the service
    fmt.Println("Got service", service)
    return nil
}

在 client wrapper 中也能够应用

type myWrapper struct {client.Client}

func (m *myWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {service, ok = micro.FromContext(ctx)
    if !ok {return errors.InternalServerError("com.example.srv.foo.mywrapper", "Could not retrieve service")
    }

    // do something with the service
    fmt.Println("Got service", service)

    // now do some call
    return c.Client.Call(ctx, req, rsp, opts...)
}

go micro 剖析系列文章
go micro server 启动剖析
go micro client
go micro broker
go micro cmd
go micro config
go micro store
go micro registry
go micro router
go micro runtime
go micro transport
go micro web
go micro registry 插件 consul
go micro plugin
go micro jwt 网关鉴权
go micro 链路追踪
go micro 熔断与限流
go micro wrapper 中间件
go micro metrics 接入 Prometheus、Grafana

正文完
 0