首页>>后端>>Golang->从micro命令行说起谈谈micro

从micro命令行说起谈谈micro

时间:2023-11-29 本站 点击:0

注:本文的micro 版本为v3.0

1. 一切的开始

packagemain//go:generate./scripts/generate.shimport("fmt""os""github.com/micro/micro/v3/cmd"//internalpackages_"github.com/micro/micro/v3/internal/usage"//loadpackagessotheycanregistercommands_"github.com/micro/micro/v3/client/cli"_"github.com/micro/micro/v3/client/cli/init"_"github.com/micro/micro/v3/client/cli/new"_"github.com/micro/micro/v3/client/cli/signup"_"github.com/micro/micro/v3/client/cli/user"_"github.com/micro/micro/v3/server"_"github.com/micro/micro/v3/service/auth/cli"_"github.com/micro/micro/v3/service/cli"_"github.com/micro/micro/v3/service/config/cli"_"github.com/micro/micro/v3/service/network/cli"_"github.com/micro/micro/v3/service/runtime/cli"_"github.com/micro/micro/v3/service/store/cli")funcmain(){iferr:=cmd.DefaultCmd.Run();err!=nil{fmt.Println(err)os.Exit(1)}}

一眼看去,内容确实是不多的。主要涉及的操作就是执行默认命令行的Run方法,并进行错误检测。

但是从导入的软件包看去,可以发现其实内容还是不少的,只不是大多都是进行初始化操作。我们可以看看主要有哪些,以及它的主要用途是做什么的。

2.plugin

第一个匿名导入的是一个内部包usage,我们来看他主要做了什么

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}

要想理解上面的代码含义以及功能,需要了解一下micro中plugin的功能和原理

Plugins 是一种扩展Micro功能的方式。它可以使Micro扩展和被拦截以提供其他功能。这包含日志,指标获取,追踪,认证等等。插件模型需要注册成满足plugin接口的结构体。然后在Micro启动时进行注册和设置。

以上就是plugin接口设计的目的。

当然了,不同于go-micro中的plugin,这里的plugin主要用于micro API, Web, Sidecar, CLI.这也是用于在HTTP里面构建中间件的方法。

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler

看完了这些接口类型原型后,问题来了,如何使用他们呢。下面的例子是一个比较简单的例子,添加一个flag然后输出它的值。

packagemainimport("log""github.com/urfave/cli/v2""github.com/micro/micro/plugin")funcinit(){plugin.Register(plugin.NewPlugin(plugin.WithName("example"),plugin.WithFlag(&cli.StringFlag{Name:"example_flag",Usage:"Thisisanexamplepluginflag",EnvVars:[]string{"EXAMPLE_FLAG"},Value:"avalue",}),plugin.WithInit(func(ctx*cli.Context)error{log.Println("Gotvalueforexample_flag",ctx.String("example_flag"))returnnil}),))}

编译代码

gobuild-omicro./main.go./plugin.go

看看,是不是和我们刚开始看到的plugin匿名导入,既然整个过程的操作流程都是一样的,那我们不妨先来一探究竟

//RegisterregistersaglobalpluginsfuncRegister(pluginPlugin,opts...PluginOption)error{returndefaultManager.Register(plugin,opts...)}

在默认的管理器defaultManager上注册plugin

var(//globalpluginmanagerdefaultManager=newManager())funcnewManager()*manager{return&manager{plugins:make(map[string][]Plugin),registered:make(map[string]map[string]bool),}}

至于注册的动作其实很简单,锁保护下,进行map的操作

func(m*manager)Register(pluginPlugin,opts...PluginOption)error{options:=PluginOptions{Module:defaultModule}for_,o:=rangeopts{o(&options)}m.Lock()deferm.Unlock()name:=plugin.String()ifreg,ok:=m.registered[options.Module];ok&&reg[name]{returnfmt.Errorf("Pluginwithname%salreadyregistered",name)}if_,ok:=m.registered[options.Module];!ok{m.registered[options.Module]=map[string]bool{name:true}}else{m.registered[options.Module][name]=true}if_,ok:=m.plugins[options.Module];ok{m.plugins[options.Module]=append(m.plugins[options.Module],plugin)}else{m.plugins[options.Module]=[]Plugin{plugin}}returnnil}

还有一点提一句plugin.NewPlugin在创建一个plugin时,参数是Options结构体,那些With开头的方法WithFlag...

typeOptionsstruct{NamestringFlags[]cli.FlagCommands[]*cli.CommandHandlers[]HandlerInitfunc(*cli.Context)error}funcWithFlag(flag...cli.Flag)Option{returnfunc(o*Options){o.Flags=append(o.Flags,flag...)}}

都是对相关plugin属性进行初始化的。这个比较清晰就不必多说。

3.client

看完了usage,看匿名导入的第二部分内容

_"github.com/micro/micro/v3/client/cli"_"github.com/micro/micro/v3/client/cli/init"_"github.com/micro/micro/v3/client/cli/new"_"github.com/micro/micro/v3/client/cli/signup"_"github.com/micro/micro/v3/client/cli/user"

有关客户端的一些初始化工作。

第一个是cli

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}0

命令行注册,主要包含以下命令行功能:

cli:用于交互式的命令行操作

call:服务调用例如 micro call greeter Say.Hello '{\"name\": \"John\"}

stream: 创建一个服务流

stats: 查询一个服务的状态

env:获取或者设置环境变量

services:罗列出所有已经注册的服务列表

第二个是clien包中的匿名导入init导入

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}1

该命令行注册的是micro init。用于为micro的plugin产生profile.go。那么执行该命令到底做了什么呢?

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}2

根据该命令对用的执行动作,我们发现,其实就是根据该命令的参数profile提供的参数,把相应的参数组成可导入路径,进行匿名导入,默认写到标准输出,可以通过output选项进行指定输出路径。

第三个是clien包中的匿名导入new导入,用于注册micro new命令行,该命令行用于创建一个消息模板,通过我们通过micro new helloworld && cd helloworld'来创建一个服务时,就是通过该命令来操作的。

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}3

在上一篇文章中,我们进行了操作,新建一个服务,那么该命令执行的动作是什么呢?

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}4

首先他会获取第一个参数服务名,如果没有指定,将直接结束。提供了服务名之后,他会进行路径检测,看是否是绝对路径,这里是不提倡使用绝对路径的。如果是绝对路径也会直接返回。

在一切都就绪后,它将创建服务的整体目录。

第四个是clien包中的匿名导入signup导入,用户注册用于登录的命令行。我们在上一篇文章中使用的micro login就跟这个有关系。

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}5

而该命令的执行动作就是注册用户的整个流程。注册成功后,后面就可以使用micro login进行登录。

最后一个是clien包中的匿名导入user导入,用户打印出当前登录的用户

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}6

该命令包含一些子命令,比如用于修改用户的密码的子命令。

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}7

到这里,整个client包的准备工作都已经结束了,而下一部分就到了server

4.server

在这里,注册micro server命令。并运行起整个平台。

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}8

而在我们启动micro server时,执行的行为为:

funcinit(){plugin.Register(Plugin())}funcPlugin()plugin.Plugin{varrequestsuint64//createrandsource:=rand.NewSource(time.Now().UnixNano())r:=rand.New(source)returnplugin.NewPlugin(plugin.WithName("usage"),plugin.WithInit(func(c*cli.Context)error{//onlydoifenabledif!c.Bool("report_usage"){os.Setenv("MICRO_REPORT_USAGE","false")returnnil}varservicestring//setservicenameifc.Args().Len()>0&&len(c.Args().Get(0))>0{service=c.Args().Get(0)}//servicesubcommandifservice=="service"{//setasthesubcommandifv:=c.Args().Get(1);len(v)>0{service=v}}//kickoffthetrackergofunc(){//newreportu:=New(service)//initialpublishin30-60secondsd:=30+r.Intn(30)time.Sleep(time.Second*time.Duration(d))for{//getservicelists,_:=registry.ListServices()//getrequestsreqs:=atomic.LoadUint64(&requests)srvs:=uint64(len(s))//resetrequestsatomic.StoreUint64(&requests,0)//setmetricsu.Metrics.Count["instances"]=uint64(1)u.Metrics.Count["requests"]=reqsu.Metrics.Count["services"]=srvs//attempttosendreport3timesfori:=1;i<=3;i++{iferr:=Report(u);err!=nil{time.Sleep(backoff.Do(i*2))continue}break}//nowsleep24hourstime.Sleep(time.Hour*24)}}()returnnil}),plugin.WithHandler(func(hhttp.Handler)http.Handler{//onlyenableifsetifv:=os.Getenv("MICRO_REPORT_USAGE");v=="false"{returnh}//returnusagerecorderreturnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//countrequestsatomic.AddUint64(&requests,1)//servetherequesth.ServeHTTP(w,r)})}),)}9

如果在运行server时,提供了参数,将打印出子命令帮助信息并直接退出。

之后,遍历下面的切片

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler0

进行服务的注册.所有的服务运行,都是通过micro service [name]

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler1

在这当中,1.如果未设置proxy_address,使用默认的本地网络proxy = "127.0.0.1:8443"2.获取环境变量中我们关心的值。

在一系列的准备工作就绪后,调用service的Run方法启动起server

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler2

结束了上的工作之后,开始进入最后一部分内容的准备工作

5.service

首先是关于鉴权相关命令行注册, micro auth命令。该命令涵盖一些子命令,包含

list:罗列出鉴权资讯

create: 创建鉴权资源

delete:删除鉴权资源

login:登录用户

logout:登出用户

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler3

在进行了用户的鉴权后,第二部分是关于service相关命令行的准备工作

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler4

第三部分关于config的命令行注册,该命令行用于管理配置项的值的设置,包括获取,删除,设置。

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler5

第四部分是关于network相关的设置的命令行注册。该命令用于管理micro service的网络,包含一些子命令

connect:连接指定网络

connections:列出直接连接的网络

graph:获取网络图

nodes:获取网络节点

routes:获取网络路由

services:获取网络服务

call:调用服务

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler6

第五部分,主要涉及micro run/update/kill/status/logs等相关命令的注册,这些命令都是管理特定的服务的相关操作。

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler7

最后一部分,主要涉及关于存储相关的micro store命令注册,包括一些子命令

read:从存储中读取记录

list:罗列出一个存储中所有的key

write:写入一条记录到存储中

delete:删除存储中的一条记录

databases:罗列出已知存储中的所有数据库

tables:罗列出指定数据库中所有的表

snapshot:备份一个存储

sync:同步一份存储到新的里面

restore:从一份快照中恢复存储

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler8

至此,整个初始化准备工作都已经完成。。。。

开启整个命令行程序。

typePlugininterface{//全局的flagsFlags()[]cli.Flag//自命令集Commands()[]*cli.Command//Handle是HTTP请求的中间件处理器。我们将它传入到已经存在的handler中以使它可以被包裹来创建一个调用链Handler()Handler//Init方法在命令行参数被解析到时候调用,传入的参数是已经初始化后的cli.ContextInit(*cli.Context)error//plugin的名称。String()string}//Manager是plugin管理器。它存储plugins并允许他们可以被检索。//它被用于micro的所有组件中。typeManagerinterface{Plugins(...PluginOption)[]PluginRegister(Plugin,...PluginOption)error}//Handler是中间件处理器plugin.可以用来包裹一个存在的http.Handler.//需要在链中调用下一个http.HandlertypeHandlerfunc(http.Handler)http.Handler9


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/254.html