关于micro:go-micro-metrics-接入PrometheusGrafana

本文介绍go micro中退出metric, 并接入Prometheus、Grafana 1.go micro中间件加载prometheus pluginsgo micro中提供了prometheus plugins github.com/micro/go-plugins/wrapper/monitoring/prometheus/ package mainimport ( "net/http" "github.com/micro/go-plugins/wrapper/monitoring/prometheus/v2" "github.com/prometheus/client_golang/prometheus/promhttp" //...)func main() { // New Service service := micro.NewService( micro.Name("go.micro.api.myauth"), micro.Version("latest"), micro.WrapHandler(prometheus.NewHandlerWrapper()), ) // Initialise service service.Init( // create wrap for the Myauth service client micro.WrapHandler(client.MyauthWrapper(service)), ) go PrometheusBoot() // Register Handler myauth.RegisterMyauthHandler(service.Server(), new(handler.Myauth)) // Run service if err := service.Run(); err != nil { log.Fatal(err) }}func PrometheusBoot() { http.Handle("/metrics", promhttp.Handler()) // 启动web服务,监听8085端口 go func() { err := http.ListenAndServe("localhost:8085", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } }()}代码很简略,在micro.NewService中传入micro.WrapHandler(prometheus.NewHandlerWrapper()), ...

August 6, 2020 · 2 min · jiezi

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

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 CallFuncfunc 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 serverfunc 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 serverfunc 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()参数 ...

August 6, 2020 · 3 min · jiezi

关于micro:go-micro-熔断与限流

本篇文章参考【Micro In Action(七):熔断与限流】 https://medium.com/@dche423/m... @dche423写的太好了,这里仅做局部摘录介绍 熔断go micro 封装了hystrix-go,gobreaker,都在plugins下 上面是hystrix的例子 import ( ... "github.com/micro/go-plugins/wrapper/breaker/hystrix/v2" ...)func main(){ ... // New Service service := micro.NewService( micro.Name("com.foo.breaker.example"), micro.WrapClient(hystrix.NewClientWrapper()), ) // Initialise service service.Init() ...}他的默认值超时工夫是1000毫秒,最大并发数是10 // DefaultTimeout is how long to wait for command to complete, in milliseconds DefaultTimeout = 1000 // DefaultMaxConcurrent is how many commands of the same type can run at the same time DefaultMaxConcurrent = 10其余参数请见官网,https://github.com/afex/hystr... ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-链路追踪

本片介绍go micro中应用jaeger作为链路追踪的应用 jaeger相干常识请见官网文档,这里应用docker启动gaeger,作为测试应用 启动jaeger docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest 拜访地址http://localhost:16686 go micro版本2.x,和1.x有些许不同 样例代码应用examples/greeter中代码批改srv/mian.go // Package mainpackage mainimport ( "context" "io" "time" hello "github.com/micro/examples/greeter/srv/proto/hello" "github.com/micro/go-micro/v2" "github.com/micro/go-micro/v2/util/log" wrapperTrace "github.com/micro/go-plugins/wrapper/trace/opentracing/v2" "github.com/opentracing/opentracing-go" "github.com/uber/jaeger-client-go" jaegercfg "github.com/uber/jaeger-client-go/config")type Say struct{}func (s *Say) Hello(ctx context.Context, req *hello.Request, rsp *hello.Response) error { log.Log("Received Say.Hello request") rsp.Msg = "Hello " + req.Name return nil}func main() { t, io, err := NewTracer("tracer-srv", "127.0.0.1:6831") if err != nil { log.Fatal(err) } defer io.Close() opentracing.SetGlobalTracer(t) service := micro.NewService( micro.Name("go.micro.srv.greeter"), micro.WrapHandler(wrapperTrace.NewHandlerWrapper(opentracing.GlobalTracer())), ) // optionally setup command line usage service.Init() // Register Handlers hello.RegisterSayHandler(service.Server(), new(Say)) // Run server if err := service.Run(); err != nil { log.Fatal(err) }}// NewTracer 创立一个jaeger Tracerfunc NewTracer(servicename string, addr string) (opentracing.Tracer, io.Closer, error) { cfg := jaegercfg.Configuration{ ServiceName: servicename, Sampler: &jaegercfg.SamplerConfig{ Type: jaeger.SamplerTypeConst, Param: 1, }, Reporter: &jaegercfg.ReporterConfig{ LogSpans: true, BufferFlushInterval: 1 * time.Second, }, } sender, err := jaeger.NewUDPTransport(addr, 0) if err != nil { return nil, nil, err } reporter := jaeger.NewRemoteReporter(sender) // Initialize tracer with a logger and a metrics factory tracer, closer, err := cfg.NewTracer( jaegercfg.Reporter(reporter), ) return tracer, closer, err}这里封装了`NewTracer()`创立一个jaeger Tracer ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-jwt-网关鉴权

本文介绍go micro中的api拜访权限管制,这里仅仅介绍外部服务间的相互调用鉴权(jwt),不是针对用户零碎的粗疏rbac模式。 指标: 外部服务间调用应在header上带上jwt token,否则返回谬误提示信息有2种形式 在每个服务上各自鉴权在网关上鉴权,各服务只需注册一个wrapper查看header中jwt信息鉴权。这样做有个前提,所有服务需放到同一个网络内,走对立的服务注册核心,这里次要介绍这种形式。先创立一个myauth的服务,对外提供2个接口 GetJwt() 返回jwt token,能够用用户名明码或其余形式验证,依据具体业务灵便决定即可,这里示例采纳服务名和密钥方InspectJwt() 验证jwt token是否无效自定义一个网关,通过插件形式wrapper指定一个鉴权函数,除了第3步中的2个接口外,其余都须要header中有jwt的token其余业务只须要注册一个wrapper查看header中jwt信息鉴权业务调用步骤 调用GetJwt()获取jwt token调用其余接口时,在header退出jwt token首先创立一个api我的项目 micro new --type=api myauth GetJwt()、InspectJwt()相干代码 // Myauth.Call is called by the API as /myauth/call with post body {"name": "foo"}func (e *Myauth) GetJwt(ctx context.Context, req *api.Request, rsp *api.Response) error { log.Info("Received Myauth.GetJwt request") getmap := req.GetGet() log.Info("Received getmap %+v\n", getmap) postmap := req.GetPost() log.Info("Received postmap %+v\n", postmap) // 外部服务调用底层service,通过jwt验证 // 定义服务名和key,通过这2个参数获取jwt access token // serviceName := "order" // serviceKey := "123456" // 比照serviceName\serviceKey 也能够是用户名明码等,这里的示例为了不便硬编码在代码中 // 理论我的项目中应该从数据库或文件读取 serviceName := extractValue(postmap["service"]) serviceKey := extractValue(postmap["key"]) log.Info("serviceName %+v\n", serviceName, serviceKey) if serviceName != "order" || serviceKey != "123456" { Rsp(rsp, 403, "服务名称或key谬误", nil) return nil } //生成jwt // expireTime := time.Now().Add(time.Hour * 24 * 3).Unix() expireTime := time.Now().Add(time.Second * 60 * 60).Unix() token := &token.Token{} token.Init([]byte("key123456")) //理论我的项目需从数据库或文件读取 jwtstring, err := token.Encode("auth jwt", serviceName, expireTime) if err != nil { Rsp(rsp, 403, "jwt 生成谬误", nil) return nil } msg := make(map[string]interface{}) msg["jwt"] = jwtstring Rsp(rsp, 200, "ok", msg) return nil}// 验证jwtfunc (e *Myauth) InspectJwt(ctx context.Context, req *api.Request, rsp *api.Response) error { log.Info("Received Myauth.InspectJwt request") // getmap := req.GetGet() // log.Info("Received getmap %+v\n", getmap) postmap := req.GetPost() // log.Info("Received postmap %+v\n", postmap) jwtString := extractValue(postmap["jwt"]) log.Info("jwtString %+v\n", jwtString) if len(jwtString) == 0 { Rsp(rsp, 403, "jwt参数谬误", nil) return nil } //解析jwt token := &token.Token{} token.Init([]byte("key123456")) info, err := token.Decode(jwtString) if err != nil { Rsp(rsp, 403, "jwt 解析谬误", nil) //过期或jwt有问题 return nil } t := make(map[string]interface{}) t["data"] = info Rsp(rsp, 200, "ok", t) return nil}// 返回funcfunc Rsp(rsp *api.Response, code int, err string, msg map[string]interface{}) error { if msg == nil { msg = make(map[string]interface{}) } r := &rspMsg{ Code: code, Err: err, Msg: msg, } b, err2 := json.Marshal(r) if err2 != nil { log.Info("json.Marshal err", err2) } rsp.StatusCode = int32(code) rsp.Body = string(b) return nil}自定义micro网关代码 ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-plugin

这篇文章中的 plugin 次要讲https://github.com/micro/micro 中的插件,次要用于自定义网关中如何加载插件。(如文章[micro auth jwt]) go-micro中的插件请见https://github.com/micro/go-p... 官网README中有一些介绍 https://github.com/micro/micr... 官网示例: 在我的项目目录创立plugin.go package mainimport ( "log" "github.com/micro/cli/v2" "github.com/micro/micro/v2/plugin")func init() { plugin.Register(plugin.NewPlugin( plugin.WithName("example"), plugin.WithFlag(cli.StringFlag{ Name: "example_flag", Usage: "This is an example plugin flag", EnvVars: []string{"EXAMPLE_FLAG"}, Value: "avalue", }), plugin.WithInit(func(ctx *cli.Context) error { log.Println("Got value for example_flag", ctx.String("example_flag")) return nil }), ))}最初编译 `go build -o micro ./main.go ./plugin.go` 一步步看看是怎么注册的,在micro/plugin/manager.go中 type manager struct { sync.Mutex plugins []Plugin registered map[string]bool}var ( // global plugin manager defaultManager = newManager())func newManager() *manager { return &manager{ registered: make(map[string]bool), }}plugin包有默认`defaultManager = newManager()`,是一个manager{}对象 ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-registry-插件consul

go micro v2版本中,consul不在默认反对,官网举荐应用etcd,具体起因官网blog有讲https://medium.com/microhq/de... consul被放到go-plugins, 由社区保护github.com/micro/go-plugins/registry/consul 要应用consul,须要从go-plugins引入 import ( "fmt" "os" "context" "github.com/micro/cli/v2" proto "github.com/micro/examples/service/proto" "github.com/micro/go-micro/v2" "github.com/micro/go-micro/v2/transport/grpc" "github.com/micro/go-plugins/registry/consul/v2")/*Example usage of top level service initialisation*/type Greeter struct{}func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error { rsp.Greeting = "Hello " + req.Name return nil}func main() { //reg := consul.NewRegistry() // Create a new service. Optionally include some options here. service := micro.NewService( micro.Name("greeter"), micro.Version("latest"), micro.Metadata(map[string]string{ "type": "helloworld", }), micro.Registry(reg), micro.Transport(grpc.NewTransport()), // Setup some flags. Specify --run_client to run the client // Add runtime flags // We could do this below too micro.Flags(&cli.BoolFlag{ Name: "run_client", Usage: "Launch the client", }), ) // Init will parse the command line flags. Any flags set will // override the above settings. Options defined here will // override anything set on the command line. service.Init( // Add runtime action // We could actually do this above micro.Action(func(c *cli.Context) error { if c.Bool("run_client") { runClient(service) os.Exit(0) } return nil }), ) // By default we'll run the server unless the flags catch us // Setup the server // Register handler proto.RegisterGreeterHandler(service.Server(), new(Greeter)) // Run the server if err := service.Run(); err != nil { fmt.Println(err) }}两种形式应用插件,具体见[go-plugins应用阐明](https://github.com/micro/go-p... ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-registry-插件consul

go micro v2版本中,consul不在默认反对,官网举荐应用etcd,具体起因官网blog有讲https://medium.com/microhq/de... consul被放到go-plugins, 由社区保护github.com/micro/go-plugins/registry/consul 要应用consul,须要从go-plugins引入 import ( "fmt" "os" "context" "github.com/micro/cli/v2" proto "github.com/micro/examples/service/proto" "github.com/micro/go-micro/v2" "github.com/micro/go-micro/v2/transport/grpc" "github.com/micro/go-plugins/registry/consul/v2")/*Example usage of top level service initialisation*/type Greeter struct{}func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error { rsp.Greeting = "Hello " + req.Name return nil}func main() { //reg := consul.NewRegistry() // Create a new service. Optionally include some options here. service := micro.NewService( micro.Name("greeter"), micro.Version("latest"), micro.Metadata(map[string]string{ "type": "helloworld", }), micro.Registry(reg), micro.Transport(grpc.NewTransport()), // Setup some flags. Specify --run_client to run the client // Add runtime flags // We could do this below too micro.Flags(&cli.BoolFlag{ Name: "run_client", Usage: "Launch the client", }), ) // Init will parse the command line flags. Any flags set will // override the above settings. Options defined here will // override anything set on the command line. service.Init( // Add runtime action // We could actually do this above micro.Action(func(c *cli.Context) error { if c.Bool("run_client") { runClient(service) os.Exit(0) } return nil }), ) // By default we'll run the server unless the flags catch us // Setup the server // Register handler proto.RegisterGreeterHandler(service.Server(), new(Greeter)) // Run the server if err := service.Run(); err != nil { fmt.Println(err) }}两种形式应用插件,具体见[go-plugins应用阐明](https://github.com/micro/go-p... ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-web

examples/web 有一个web的例子,这里比较简单 service.HandleFunc("/", helloWorldHandler) 这一行指定处理程序比较简单,第2个参数定义了一个函数,只有满足条件就行 handler func(http.ResponseWriter, *http.Request) 理论我的项目中不太可能只用go micro, 从0开始手撸所有其余轮子,那么可不可以在go micro中引入罕用的框架呢? 当然能够,来看一个引入gin的例子examples/greeter/api/gin/gin.go func main() { // Create service service := web.NewService( web.Name("go.micro.api.greeter"), ) service.Init() // setup Greeter Server Client cl = hello.NewSayService("go.micro.srv.greeter", client.DefaultClient) // Create RESTful handler (using Gin) say := new(Say) router := gin.Default() router.GET("/greeter", say.Anything) router.GET("/greeter/:name", say.Hello) // Register Handler service.Handle("/", router) // Run server if err := service.Run(); err != nil { log.Fatal(err) }}要害是service.Handle("/", router) ...

August 6, 2020 · 3 min · jiezi

关于micro:go-micro-web

examples/web 有一个web的例子,这里比较简单 service.HandleFunc("/", helloWorldHandler) 这一行指定处理程序比较简单,第2个参数定义了一个函数,只有满足条件就行 handler func(http.ResponseWriter, *http.Request) 理论我的项目中不太可能只用go micro, 从0开始手撸所有其余轮子,那么可不可以在go micro中引入罕用的框架呢? 当然能够,来看一个引入gin的例子examples/greeter/api/gin/gin.go func main() { // Create service service := web.NewService( web.Name("go.micro.api.greeter"), ) service.Init() // setup Greeter Server Client cl = hello.NewSayService("go.micro.srv.greeter", client.DefaultClient) // Create RESTful handler (using Gin) say := new(Say) router := gin.Default() router.GET("/greeter", say.Anything) router.GET("/greeter/:name", say.Hello) // Register Handler service.Handle("/", router) // Run server if err := service.Run(); err != nil { log.Fatal(err) }}要害是service.Handle("/", router) ...

August 6, 2020 · 3 min · jiezi

关于micro:go-micro-transport

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Transporttransport.DefaultTransport,在transport/transport.go中的DefaultTransport Transport = newHTTPTransport() func NewTransport(opts ...Option) Transport { return newHTTPTransport(opts...)}func newHTTPTransport(opts ...Option) *httpTransport { var options Options for _, o := range opts { o(&options) } return &httpTransport{opts: options}}这里就初始化并设置options,返回了一个httpTransport{} ...

August 6, 2020 · 1 min · jiezi

关于micro:go-micro-runtime

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Runtimeruntime.DefaultRuntime,在runtime/runtime.go中的DefaultRuntime Runtime = NewRuntime() // NewRuntime creates new local runtime and returns itfunc NewRuntime(opts ...Option) Runtime { // get default options options := Options{} // apply requested options for _, o := range opts { o(&options) } // make the logs directory path := filepath.Join(os.TempDir(), "micro", "logs") _ = os.MkdirAll(path, 0755) return &runtime{ options: options, closed: make(chan bool), start: make(chan *service, 128), namespaces: make(map[string]map[string]*service), }}这里做了以下事件: ...

August 6, 2020 · 1 min · jiezi

关于micro:go-micro-router

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Routerrouter.DefaultRouter,在router/router.go中的DefaultRouter = NewRouter() // NewRouter creates new Router and returns itfunc NewRouter(opts ...Option) Router { return newRouter(opts...)}// newRouter creates new router and returns itfunc newRouter(opts ...Option) Router { // get default options options := DefaultOptions() // apply requested options for _, o := range opts { o(&options) } // construct the router r := &router{ options: options, subscribers: make(map[string]chan *Advert), } // create the new table, passing the fetchRoute method in as a fallback if // the table doesn't contain the result for a query. r.table = newTable(r.fetchRoutes) // start the router and return r.start() return r}这里做了以下事件: ...

August 6, 2020 · 1 min · jiezi

关于micro:go-micro-registry

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Registryregistry.DefaultRegistry,在registry/registry.go中的DefaultRegistry = NewRegistry() // NewRegistry returns a new default registry which is mdnsfunc NewRegistry(opts ...Option) Registry { return newRegistry(opts...)}func newRegistry(opts ...Option) Registry { options := Options{ Context: context.Background(), Timeout: time.Millisecond * 100, } for _, o := range opts { o(&options) } // set the domain defaultDomain := DefaultDomain d, ok := options.Context.Value("mdns.domain").(string) if ok { defaultDomain = d } return &mdnsRegistry{ defaultDomain: defaultDomain, globalDomain: globalDomain, opts: options, domains: make(map[string]services), watchers: make(map[string]*mdnsWatcher), }}这里做了以下事件: ...

August 6, 2020 · 7 min · jiezi

关于micro:go-micro-store

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Storestore.DefaultStore,这里不要间接去看store/store.go中的DefaultStore Store = new(noopStore),因为在micro/defaults.go中曾经初始化了,默认应用的是store.DefaultStore = memoryStore.NewStore() // NewStore returns a memory storefunc NewStore(opts ...store.Option) store.Store { s := &memoryStore{ options: store.Options{ Database: "micro", Table: "micro", }, store: cache.New(cache.NoExpiration, 5*time.Minute), } for _, o := range opts { o(&s.options) } return s}type memoryStore struct { options store.Options store *cache.Cache}初始化了memoryStore{},store是应用的patrickmn/go-cache设置options,返回memoryStore实例性能比较简单,在store/memory/memory.go封装了读写删改等操作函数 ...

August 6, 2020 · 1 min · jiezi

关于micro:go-micro-store

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看Storestore.DefaultStore,这里不要间接去看store/store.go中的DefaultStore Store = new(noopStore),因为在micro/defaults.go中曾经初始化了,默认应用的是store.DefaultStore = memoryStore.NewStore() // NewStore returns a memory storefunc NewStore(opts ...store.Option) store.Store { s := &memoryStore{ options: store.Options{ Database: "micro", Table: "micro", }, store: cache.New(cache.NoExpiration, 5*time.Minute), } for _, o := range opts { o(&s.options) } return s}type memoryStore struct { options store.Options store *cache.Cache}初始化了memoryStore{},store是应用的patrickmn/go-cache设置options,返回memoryStore实例性能比较简单,在store/memory/memory.go封装了读写删改等操作函数 ...

August 6, 2020 · 1 min · jiezi

关于micro:go-micro-config

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,来看看configconfig.DefaultConfig,在config/config.go中 var ( // Default Config Manager DefaultConfig, _ = NewConfig())// NewConfig returns new configfunc NewConfig(opts ...Option) (Config, error) { return newConfig(opts...)}func newConfig(opts ...Option) (Config, error) { var c config c.Init(opts...) go c.run() return &c, nil}func (c *config) Init(opts ...Option) error { c.opts = Options{ Reader: json.NewReader(), } c.exit = make(chan bool) for _, o := range opts { o(&c.opts) } // default loader uses the configured reader if c.opts.Loader == nil { c.opts.Loader = memory.NewLoader(memory.WithReader(c.opts.Reader)) } err := c.opts.Loader.Load(c.opts.Source...) if err != nil { return err } c.snap, err = c.opts.Loader.Snapshot() if err != nil { return err } c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet) if err != nil { return err } return nil}func (c *config) run() { watch := func(w loader.Watcher) error { for { // get changeset snap, err := w.Next() if err != nil { return err } c.Lock() if c.snap.Version >= snap.Version { c.Unlock() continue } // save c.snap = snap // set values c.vals, _ = c.opts.Reader.Values(snap.ChangeSet) c.Unlock() } } for { w, err := c.opts.Loader.Watch() if err != nil { time.Sleep(time.Second) continue } done := make(chan bool) // the stop watch func go func() { select { case <-done: case <-c.exit: } w.Stop() }() // block watch if err := watch(w); err != nil { // do something better time.Sleep(time.Second) } // close done chan close(done) // if the config is closed exit select { case <-c.exit: return default: } }}看看Init()左做了什么 ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-cmd

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,先来看看cmd cmd.DefaultCmd,在config/cmd/cmd.go DefaultCmd = newCmd() type Cmd interface { // The cli app within this cmd App() *cli.App // Adds options, parses flags and initialise // exits on error Init(opts ...Option) error // Options set within this command Options() Options}type cmd struct { opts Options app *cli.App}type Option func(o *Options)func newCmd(opts ...Option) Cmd { options := Options{ Auth: &auth.DefaultAuth, Broker: &broker.DefaultBroker, Client: &client.DefaultClient, Registry: &registry.DefaultRegistry, Server: &server.DefaultServer, Selector: &selector.DefaultSelector, Transport: &transport.DefaultTransport, Router: &router.DefaultRouter, Runtime: &runtime.DefaultRuntime, Store: &store.DefaultStore, Tracer: &trace.DefaultTracer, Profile: &profile.DefaultProfile, Config: &config.DefaultConfig, Brokers: DefaultBrokers, Clients: DefaultClients, Registries: DefaultRegistries, Selectors: DefaultSelectors, Servers: DefaultServers, Transports: DefaultTransports, Routers: DefaultRouters, Runtimes: DefaultRuntimes, Stores: DefaultStores, Tracers: DefaultTracers, Auths: DefaultAuths, Profiles: DefaultProfiles, Configs: DefaultConfigs, } for _, o := range opts { o(&options) } if len(options.Description) == 0 { options.Description = "a go-micro service" } cmd := new(cmd) cmd.opts = options cmd.app = cli.NewApp() cmd.app.Name = cmd.opts.Name cmd.app.Version = cmd.opts.Version cmd.app.Usage = cmd.opts.Description cmd.app.Before = cmd.Before cmd.app.Flags = DefaultFlags cmd.app.Action = func(c *cli.Context) error { return nil } if len(options.Version) == 0 { cmd.app.HideVersion = true } return cmd}这里的cmd构造体中 ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-cmd

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,先来看看cmd cmd.DefaultCmd,在config/cmd/cmd.go DefaultCmd = newCmd() type Cmd interface { // The cli app within this cmd App() *cli.App // Adds options, parses flags and initialise // exits on error Init(opts ...Option) error // Options set within this command Options() Options}type cmd struct { opts Options app *cli.App}type Option func(o *Options)func newCmd(opts ...Option) Cmd { options := Options{ Auth: &auth.DefaultAuth, Broker: &broker.DefaultBroker, Client: &client.DefaultClient, Registry: &registry.DefaultRegistry, Server: &server.DefaultServer, Selector: &selector.DefaultSelector, Transport: &transport.DefaultTransport, Router: &router.DefaultRouter, Runtime: &runtime.DefaultRuntime, Store: &store.DefaultStore, Tracer: &trace.DefaultTracer, Profile: &profile.DefaultProfile, Config: &config.DefaultConfig, Brokers: DefaultBrokers, Clients: DefaultClients, Registries: DefaultRegistries, Selectors: DefaultSelectors, Servers: DefaultServers, Transports: DefaultTransports, Routers: DefaultRouters, Runtimes: DefaultRuntimes, Stores: DefaultStores, Tracers: DefaultTracers, Auths: DefaultAuths, Profiles: DefaultProfiles, Configs: DefaultConfigs, } for _, o := range opts { o(&options) } if len(options.Description) == 0 { options.Description = "a go-micro service" } cmd := new(cmd) cmd.opts = options cmd.app = cli.NewApp() cmd.app.Name = cmd.opts.Name cmd.app.Version = cmd.opts.Version cmd.app.Usage = cmd.opts.Description cmd.app.Before = cmd.Before cmd.app.Flags = DefaultFlags cmd.app.Action = func(c *cli.Context) error { return nil } if len(options.Version) == 0 { cmd.app.HideVersion = true } return cmd}这里的cmd构造体中 ...

August 6, 2020 · 2 min · jiezi

关于micro:go-micro-broker

micro.newService()中newOptions func newOptions(opts ...Option) Options { opt := Options{ Auth: auth.DefaultAuth, Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Config: config.DefaultConfig, Client: client.DefaultClient, Server: server.DefaultServer, Store: store.DefaultStore, Registry: registry.DefaultRegistry, Router: router.DefaultRouter, Runtime: runtime.DefaultRuntime, Transport: transport.DefaultTransport, Context: context.Background(), Signal: true, } for _, o := range opts { o(&opt) } return opt}初始化了一堆根底设置,先来看看Broker broker.DefaultBroker,在broker/broker.go中 DefaultBroker Broker = NewBroker() // NewBroker returns a new http brokerfunc NewBroker(opts ...Option) Broker { return newHttpBroker(opts...)}func newHttpBroker(opts ...Option) Broker { options := Options{ Codec: json.Marshaler{}, Context: context.TODO(), Registry: registry.DefaultRegistry, } for _, o := range opts { o(&options) } // set address addr := DefaultAddress if len(options.Addrs) > 0 && len(options.Addrs[0]) > 0 { addr = options.Addrs[0] } h := &httpBroker{ id: uuid.New().String(), address: addr, opts: options, r: options.Registry, c: &http.Client{Transport: newTransport(options.TLSConfig)}, subscribers: make(map[string][]*httpSubscriber), exit: make(chan chan error), mux: http.NewServeMux(), inbox: make(map[string][][]byte), } // specify the message handler h.mux.Handle(DefaultPath, h) // get optional handlers if h.opts.Context != nil { handlers, ok := h.opts.Context.Value("http_handlers").(map[string]http.Handler) if ok { for pattern, handler := range handlers { h.mux.Handle(pattern, handler) } } } return h}这里做了几件事 ...

August 6, 2020 · 7 min · jiezi

关于micro:go-micro-server-启动分析

基于go-micro 2.9.1版本, 样例代码example/greeter,git commit:3b3de68cded8879ca3dde5d81192f2881619aabd 一个微服务server的外围只有3步 service := micro.NewService()service.Init()service.Run()先看micro.NewService() service := micro.NewService( micro.Name("greeter"), micro.Version("latest"), micro.Metadata(map[string]string{ "type": "helloworld", }),)micro.NewService的参数都会返回一个Option,这些参数没有做任何事件,只是返回了一些设置用的函数, 这种写法是“函数选项模式”,可参考https://segmentfault.com/a/11... 先看NewService()外面做了什么 // Name of the servicefunc Name(n string) Option { return func(o *Options) { o.Server.Init(server.Name(n)) }}//Option函数在micro.go中定义//Options构造体在options.go中定义type Option func(*Options)// Options for micro servicetype Options struct { Auth auth.Auth Broker broker.Broker Cmd cmd.Cmd Config config.Config Client client.Client Server server.Server Store store.Store Registry registry.Registry Router router.Router Runtime runtime.Runtime Transport transport.Transport Profile profile.Profile // Before and After funcs BeforeStart []func() error BeforeStop []func() error AfterStart []func() error AfterStop []func() error // Other options for implementations of the interface // can be stored in a context Context context.Context Signal bool}server.Name(n)实现这样,通过micro包提供的函数设置micro.options ...

August 6, 2020 · 5 min · jiezi