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