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
在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
在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
下面是一個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...
這裏包括
若是你想要實現本身的中間件,這裏的官方實現是個不錯的參考
不少時候須要從處理程序內部訪問服務。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