Go Micro

未匹配的标注
本文档最新版为 3.x,旧版本可能放弃维护,推荐阅读最新版!

Go Micro 是一个插件式的 RPC 框架. 用于分布式系统开发.

特性

Go Micro 抽象出分布式系统的细节. 以下是主要功能.

  • 服务发现 - 通过服务发现自动注册和名称解析
  • 负载平衡 - 基于发现构建的服务的智能客户端负载平衡
  • 同步通信 - 基于 RPC 的通信, 支持双向流
  • 异步通信 - 为事件驱动架构内置的 Pub/Sub 接口
  • 消息编码 - 基于带有 protobuf 和 json 的内容类型的动态编码
  • 服务接口 - 所有功能都打包在一个简单的高级界面中, 用于开发微服务

Go Micro 支持服务和功能编程模型. 后续会继续介绍.

插件

Go-micro 使用 Go 接口进行抽象. 因此具体的底层实现可以被置换.

我们提供了开箱即用的默认设置.

  • Consul 或 mDNS 服务发现
  • 随机散列客户端负载平衡
  • JSON-RPC 1.0 和 PROTO-RPC 消息编码
  • HTTP 通信机制

示例

示例/函数 以及 示例/服务 可以找到一些服务示例

示例 目录包含使用诸如中间件/封装器, 选择器过滤器, pub/sub, grpc, 插件等的示例. 对于完整的 greeter 示例, 可参阅 示例/greeter 程序. 其他示例可以在整个GitHub 存储库中找到.

观看 Golang UK Conf 2016 视频以获取更多内容.

软件包

Go micro 由多个软件包组成。

  • 传输同步消息
  • 代理异步消息
  • 用于消息编码的编解码器
  • 服务发现注册表
  • 选择器进行负载平衡
  • 客户端提出请求
  • 服务器来处理请求

更多细节如下

注册机制

注册机制提供了一个服务发现机制来将名称解析为地址. 它可以由consul, etcd, zookeeper, dns, gossip 等提供支持. 服务应该在启动时使用注册机制进行注册, 并在关闭时取消注册. 服务可以选择提供一个到期的 TTL 并在一段时间内重新注册以确保活跃, 并且如果服务死亡, 服务将被清除.

选择器

选择器是建立在注册表上的负载平衡抽象. 它允许使用过滤器功能对 “服务” 进行 “过滤”, 并使用诸如 random, roundrobin, leastconn 等算法选择 “选择” 服务. 客户端在请求时利用选择器. 客户端将使用选择器而不是注册表, 因为它提供了内置的负载平衡机制.

传输

传输是用于服务之间的同步请求/响应通信的接口. 它类似于 golang 网络包, 但提供更高层次的抽象, 允许我们切换通信机制, 例如 http, rabbitmq, websockets, NATS. 该传输也支持双向流式传输. 这对客户端推送到服务器提供强大的能力.

代理

代理为消息代理提供异步发布/订阅通信的接口. 这是事件驱动架构和微服务的基本要求之一. 默认情况下, 我们使用收件箱样式指向 HTTP 系统, 来最小化基本所需的依赖的数量. 但是, 在 go-plugins 中有许多消息代理实现可用, 例如 RabbitMQ, NATS, NSQ, Google Cloud Pub Sub.

编解码器

编解码器用于编码和解码消息, 然后再通过线路传输消息. 这可能是 json, protobuf, bson, msgpack 等. 这与其他大多数编解码器不同之处在于我们实际上也支持 RPC 格式. 所以我们有JSON-RPC, PROTO-RPC, BSON-RPC 等. 它将客户端/服务器的编码分离出来, 并提供了一个强大的方法来集成其他系统, 如 gRPC, Vanadium 等.

服务器

服务器是编写服务的构建模块. 在这里, 您可以命名您的服务, 注册请求处理程序, 添加中间件等. 该服务构建在上述软件包上, 为服务请求提供统一接口. 内置一个 RPC 系统的服务器. 将来可能会有其他的实现. 该服务器还允许您定义多个编解码器以提供不同的编码消息.

客户端

客户端提供一个接口来向服务发出请求. 就像服务器一样, 它建立在其他软件包上, 以提供一个统一的接口, 用于使用注册机制, 根据名称查找服务, 使用选择器进行负载平衡, 使用代理进行传输和异步消息传输的同步请求.

上述组件被组合在微服务的顶层.

内部实现

以下是关于核心部件的内部工作的原理.

service.Run()

Go-micro 服务通过调用 service.Run() 来启动m

  1. 在启动功能之前执行

      for _, fn := range s.opts.BeforeStart {
              if err := fn(); err != nil {
                      return err
              }
      }
    
  2. 启动服务

     if err := s.opts.Server.Start(); err != nil {
              return err
     }
    
  3. 注册和服务发现

      if err := s.opts.Server.Register(); err != nil {
              return err
      }
    
  4. 在启动功能后执行

     for _, fn := range s.opts.AfterStart {
             if err := fn(); err != nil {
                     return err
             }
     }
    

server.Start()

server.Start 由 service.Run 调用

  1. 调用 transport.Listen 监听连接

      ts, err := config.Transport.Listen(config.Address)
      if err != nil {
              return err
      }
    
  2. 调用 transport.Accept 开始接收链路

      go ts.Accept(s.accept)
    
  3. 调用 broker.Connect 开始处理链路消息

      config.Broker.Connect()
    
  4. 等待退出信号, 关闭传输并断开代理

      go func() {
              // wait for exit
              ch := <-s.exit
    
              // wait for requests to finish
              if wait(s.opts.Context) {
                      s.wg.Wait()
              }
    
              // close transport listener
              ch <- ts.Close()
    
              // disconnect the broker
              config.Broker.Disconnect()
      }()
    

编写服务

可参阅 文档

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
taadis
讨论数量: 0
发起讨论 只看当前版本


暂无话题~