go micro wrapper 中間件

go micro wrapper 中間件node

本篇不涉及中間件底層是如何運做的,若有興趣請見[micro server]篇git

在options.go中有以下定義github

// 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()參數web

有如下幾種類型segmentfault

  1. WrapClient() 用於用一些中間件組件包裝Client,包裝器以相反的順序應用,所以最後一個先執行。
  2. WrapCall() 用於方便包裝Client CallFunc
  3. WrapHandler() 將一系列handler中間件傳給server,並初始化
  4. WrapSubscriber() 將一系列subscriber中間件傳給server,並初始化

在server/wrapper.go中,定義了wrapperapp

// 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

服務端主要是ide

  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

客戶端主要是ui

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

下面是一個client 中間件 Wrapper 的例子this

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

相關文章
相關標籤/搜索