Micro实践(二)

项目布局

通过micro命令生成的hello微服务项目布局如下:

.
├── main.go
├── generate.go
├── plugin.go
├── proto/hello
│   └── hello.proto
│   └── hello.pb.go
│   └── hello.pb.micro.go
├── handler
│   └── hello.go
├── subscriber
│   └── hello.go
├── Dockerfile
├── go.mod
├── go.sum
├── Makefile
└── README.md

这是项目中的文件列表:

  • main.go,项目主文件
  • generate.go,仅包含一行//go:generate make proto,与集成go generate。确保执行make proto 期间会自动调用 go generate
  • plugins.go,此文件当前为空。根据Micro的约定,建议在此处管理所有插件的导入,稍后将使用。
  • proto / hello / hello.proto,一个gRPC服务定义文件,它定义了一个名为的RPC服务Hello。在此服务中,声明了3种典型的RPC方法:一元RPC,服务器流RPC和双向流RPC
  • proto / hello / hello.pb.go,由protoc上述文件生成的golang源.proto文件
  • proto / hello / hello.pb.micro.go,由生成的golang源文件protoc-gen-micro,进一步简化了开发人员的工作。它定义了HelloSerivce接口和HelloHandler接口。后者是我们实现和完善业务逻辑所需的接口
  • handler / hello.go,用于实现业务逻辑的文件。它定义了一个Hello对象,该对象实现了HelloHandler接口。
  • Subscriber / Hello.go,用于实现异步消息订阅和处理的文件。它显示了两种不同的消息处理方式,一种是通过对象方法,另一种是通过函数。
  • Dockerfile,定义如何构建Docker映像
  • go.mod / go.sum,Go模块相关文件
  • Makefile,定义几个常见任务,进行编译,测试,构建Docker镜像等。
  • README.md,包含项目的基本信息

注意:该文件夹proto具有特殊含义。尽管没有技术限制,但按照Micro的约定proto,每个项目的根目录中的文件夹用于存储“接口”文件。这既包括项目需要向外界公开的接口,也包括项目所依赖的其他接口。例如,假设我们需要依赖另一个服务foo来实现业务逻辑。然后,我们将创建一个名为proto/foo的文件夹,并在其中放置三个文件foo.proto,foo.pb.go,foo.pb.micro.go。

项目如何启动

看看main.go来了解下程序的启动过程。

package main
//导入依赖关系
import (
   "github.com/micro/go-micro/util/log"
   "github.com/micro/go-micro"
   "hello/handler"
   "hello/subscriber"
   hello "hello/proto/hello"
)
func main() {
   // New Service创建和初始化服务
   service := micro.NewService(
      micro.Name("com.foo.srv.hello"),
      micro.Version("latest"),
   )
   // Initialise service
   service.Init()
   // Register Handler注册业务处理程序
   hello.RegisterHelloHandler(service.Server(), new(handler.Hello))
   // Register Struct as Subscriber
   micro.RegisterSubscriber("com.foo.srv.hello", service.Server(), new(subscriber.Hello))
   // Register Function as Subscriber
   micro.RegisterSubscriber("com.foo.srv.hello", service.Server(), subscriber.Handler)
   // Run service运行服务
   if err := service.Run(); err != nil {
      log.Fatal(err)
   }
}

该代码大致分为4部分,分别是导入依赖关系,创建和初始化服务,注册业务处理程序以及运行服务。

micro微服务的25个option

  1. micro.Name(n string),指定服务名称。通常,命名约定为$namespace. $type. $name。$namespace 代表项目的名称空间,并$type代表服务类型(例如gRPC和Web)。gRPC服务类型通常缩写为srv。服务实例启动后,该名称将自动在Registry中注册,这将成为服务发现的基础。默认值为go.micro.server。注意:因此必须指定此选项,否则所有节点都使用相同的默认名称,这将导致混乱
  2. micro.Version(v string),指定服务版本。默认值是启动时的格式化字符串。通过正确选择版本号,并结合正确的使用Selector,我们可以实现优雅的螺旋式升级,灰度发布,A / B测试和许多其他操作。
  3. micro.Address(addr string),指定gRPC服务地址。默认值为本地主机地址和随机端口。因为客户端通过Registry服务来发现,所以随机端口不会影响该发现。但是,实际上通常会指定一个固定的端口号,这将有利于操作和安全控制。
  4. micro.RegisterTTL(t time.Duration),在注册表中指定服务注册信息的TTL。默认值为1分钟
  5. micro.RegisterInterval(t time.Duration),指定服务将其状态报告给注册表的时间间隔。默认值为30秒。当服务遇到意外的停机时间时,这两个与注册表相关的选项有助于避免“无效的注册信息”。
  6. micro.WrapHandler(w …server.HandlerWrapper),包装服务处理程序。它在概念上类似于Gin中间件,并集中控制处理程序的行为。包装器可以应用于多个层,并且执行顺序是从外到内的(示例将在后面的文章中提供)
  7. micro.WrapSubscriber(w …server.SubscriberWrapper),类似于WrapHandler,不同之处在于它用于在异步消息传递中包装订户。
  8. micro.WrapCall(w …client.CallWrapper) ,包装来自客户端的每个方法调用。
  9. micro.WrapClient(w …client.Wrapper) ,包装服务客户端,可以多层应用,执行顺序从内到外。
  10. micro.BeforeStart(fn func() error),在服务启动前设置多个回调函数。
  11. micro.BeforeStop(fn func() error) ,在服务停止前设置多个回调函数。
  12. micro.AfterStart(fn func() error) ,服务启动后设置多个回调函数。
  13. micro.AfterStop(fn func() error) ,服务停止后设置多个回调函数。
  14. micro.Action(a func(*cli.Context)) ,处理命令行参数。支持子命令和标志。见micro/cli的详细信息。
  15. micro.Flags(flags …cli.Flag) ,处理命令行标志。见micro/cli的详细信息。
  16. micro.Cmd(c cmd.Cmd),指定命令行处理对象。newCmd默认情况下生成的此对象支持多个默认环境变量和命令行参数。本质上,它是cli.Flag的内置集合。注意:关于命令行支持,Micro同时具有优点和缺点。优点是它提供了许多默认选项,可以节省开发人员时间。缺点是该设计对用户程序具有很强的侵害性:该框架要求开发人员根据micro / cli以统一的方式处理其命令行参数。否则,程序将报告错误并且无法运行。例如,如果运行./hello-srv –foo=bar,,将得到和错误:Incorrect Usage. Flag provided but not defined: –foo=bar。幸好,micro.Cmd可以弥补由干扰引起的问题。如果现有项目要引入Micro并且它已经具有自己的命令行处理机制,则您需要使用它micro.Cmd来覆盖默认行为(同时失去默认命令行处理功能)。
  17. micro.Metadata(md map[string]string),指定服务元数据。元数据通常用于标记和分组服务,实现自定义负载平衡策略等。
  18. micro.Transport(t transport.Transport),指定传输协议,默认为http。
  19. micro.Selector(s selector.Selector) ,指定节点选择器以实现不同的加载策略。默认为随机选择器
  20. micro.Registry(r registry.Registry),指定Registry用于服务发现的。默认是基于mDNS的Registry
  21. micro.Server(s server.Server) ,Server如果默认项不符合您的要求,请指定自定义。默认为rpcServer
  22. micro.HandleSignal(b bool) ,切换捕获TERM,INT和QUIT的信号处理程序的自动安装。默认是true
  23. micro.Context(ctx context.Context) ,指定服务的初始上下文。默认值为context.BackGround(),可用于控制服务寿命以及更多
  24. micro.Client(c client.Client) ,指定服务客户端。默认是rpcClient
  25. micro.Broker(b broker.Broker) ,指定pub / sub使用的消息代理。默认为HTTP代理

因此,通过指定适当的Option,可以高度定制服务的行为。比如修改TTL为5分钟:

...
// New Service
service := micro.NewService(
   micro.Name("foo.bar"),
   micro.Version("v1.0"),
   // change default TTL value
   micro.RegisterTTL(5 * time.Minute),
   ...
)
...

注意:可以通过多种方法指定上述大多数选项。在源文件中进行硬编码只是其中一种方法。实际上,Micro建议用户通过环境变量指定选项,因为这样可以提供更大的灵活性。以micro.RegisterTTL作为一个例子,我们可以通过将环境变量在运行时指定它$ MICRO_REGISTER_TTL=value或命令行标记 –register_ttl=value(单位是秒)。这些内置选项目前没有文档。运行./hello-srv -h将显示它们的简要说明。如果您想了解完整的细节,请查看newCmd的源代码。

创建后,您可以初始化服务:

// Initialize service
service.Init()

该service.Init方法与micro.NewService一样,可以接受参数。因此,以上25个选项也可以在service.Init中使用。它们具有相同的效果,只是时间点不同。

由于此时已创建了服务,因此我们可以从服务实例中检索信息。例如,您可以读取随机端口:

// Initialize service
service.Init(
   // print log after start
   micro.AfterStart(func() error {
      log.Infof("service listening on %s!",
         service.Options().Server.Options().Address,
      )
      return nil
   }),
)

注册业务处理程序

// Register Handler
hello.RegisterHelloHandler(service.Server(), new(handler.Hello))
// Register Struct as Subscriber
micro.RegisterSubscriber("com.foo.srv.hello", service.Server(), new(subscriber.Hello))
// Register Function as Subscriber
micro.RegisterSubscriber("com.foo.srv.hello", service.Server(), subscriber.Handler)

只有在Handler注册后,我们的业务代码才能真正为外界提供服务。以下是三种典型的注册操作:

  1. 注册gRPC处理程序。创建一个handler.Hello对象并将其注册到Server。因为handler.Hello实现了HelloHandler接口,所以可以将其传递给hello.RegisterHelloHandler,否则将发生错误。Handlers可以注册多个Server以提供不同的业务功能。
  2. 注册消息处理对象。第一个参数是消息主题,第二个参数是Server,第三个参数是消息处理对象。
  3. 注册消息句柄功能。与对象注册类似,不同之处在于第三个参数是处理消息的函数。

运行服务

if err := service.Run(); err != nil {
      log.Fatal(err)
}

检查运行时状态

命令行工具micro可用于在运行时检查和操作服务。

服务启动后,运行micro web:

$ micro web
2020/01/15 18:13:25 : [web] HTTP API Listening on [::]:8082
2020/01/15 18:13:25 : [web] Transport [http] Listening on [::]:59005
2020/01/15 18:13:25 : [web] Broker [http] Connected to [::]:59006
2020/01/15 18:13:25 : [web] Registry [mdns] Registering node: go.micro.web-950a8b2b-003d-47c1-a512-53aedebc9d12

服务器正在监听本地主机的端口8082。 端口8082是默认值,可以通过环境变量或命令行标志进行修改。运行micro web -h以获取详细信息。 然后访问http://localhost:8082查看服务状态。

http://localhost:8082

也可以访问下面这个地址:

http://localhost:8082/service/go.micro.srv.microtry

欢迎转载,本文地址: https://blog.prodrich.com/detail/14/

带着使命来到世上的你,给他人提供价值,才有价值