微服务框架go-micro探究
一、简介
go-micro是一个插件化的基础框架,基于此可以构建微服务。在架构之外,它默认实现了consul作为服务发现(2019年源码修改了默认使用mdns),通过http进行通信,通过protobuf和json进行编解码。
二、主要功能
· 服务发现:自动服务注册和名称解析。服务发现是微服务开发的核心。当服务A需要与服务B通话时,它需要该服务的位置。默认发现机制是多播DNS(mdns),一种零配置系统。也可以根据需要设置为consul、etcd等服务发现注册中间件。
· 负载均衡:基于服务发现构建的客户端负载均衡。一旦我们获得了服务的任意数量实例的地址,我们现在需要一种方法来决定要路由到哪个节点。我们使用随机散列或者轮询等负载均衡方法来提供跨服务的均匀分布,并在出现问题时重试不同的节点。
· 消息编码:基于内容类型的动态消息编码。客户端和服务器将使用编解码器和内容类型无缝编码和解码。可以编码任何种类的消息并从不同的客户端发送。客户端和服务器默认处理此问题。这包括默认的protobuf和json
· 请求/响应:基于RPC的请求/响应,支持双向流。我们提供了同步通信的抽象。对服务的请求将自动解决,负载平衡,拨号和流式传输。启用tls时,默认传输为http / 1.1或http2
· 异步通信:Pub/Sub是异步通信和事件驱动架构的主流方式。事件通知是微服务开发的核心模式。
· 可插拔接口:Go Micro为每个分布式系统抽象使用Go接口,因此,这些接口是可插拔的,并允许Go Micro与运行时无关,可以插入任何基础技术。(插件地址:https://github.com/micro/go-plugins)
三、处理请求流程
· Server监听客户端的调用,和Brocker推送过来的信息进行处理。并且Server端需要向Register注册自己的存在或消亡,这样Client的请求消息才能有效的送达Server端。
· Register服务的注册的发现,Client端从Register中得到Server的信息,然后每次调用都根据算法选择一个的Server进行通信,当然通信是要经过编码/解码,选择传输协议等一系列过程的
· 如果有需要通知所有的Server端可以使用Brocker进行信息的推送,Brocker 信息队列进行信息的接收和发布
四、架构设计
go-micro之所以可以高度定制和他的框架结构是分不开的,go-micro由8个关键的interface组成,每一个interface都可以根据自己的需求重新实现,这8个主要的inteface也构成了go-micro的框架结构。
Go micro 由以下接口列表组成:
· client - 用于高级别请求/响应和通知
· server - 用于处理请求和通知
· broker - 异步消息传递
· codec - 用于消息编码的
· registry - 服务发现的注册表
· selector - 用于负载平衡
· transport - 用于同步通信
1. client
客户端提供一个接口来向服务发出请求. 同样与服务器一样, 它构建在其他包上, 提供统一接口, 用于使用注册表按名称查找服务, 使用选择器进行负载平衡, 使用代理,使用传输和异步消息传递进行同步请求.
2. server
服务器是编写服务的构建基块。 在这里, 你可以命名你的服务, 注册请求处理程序, 添加中间件等. 该服务基于上述包, 为服务请求提供统一接口. 内置服务器间消息传递方式是 RPC (远程过程调用)。将来可能还会有其他实现。服务器还允许定义多个编解码器以实现服务不同的编码消息.
3. broker
代理是异步 pub/sub 通信提供消息代理的接口。这是事件驱动体系结构和微服务的基本要求之一。默认情况下, 我们使用收件箱样式的HTTP 系统, 以尽量减少开始所需的依赖项数。但是在 go-plugins 中有许多消息代理实现, 例如 RabbitMQ, NATS, NSQ, Google Cloud Pub Sub.
4. codec
编解码器用于编码和解码消息, 然后再通过http或者消息传输中间件来传输消息。数据可能是 json, protobuf, beson, msgpack 等。这与大多数其他编解码器的不同之处在于, 我们实际上也支持此处的 RPC 格式. 因此们有 JSON-RPC, PROTO-RPC, BSON-RPC 等。它将编码与客户端/服务器分离, 并提供集成其他系统 (如 gRPC, Vandium 等) 的强大方法.
5. registry
注册表提供一种服务发现机制, 用于将名称解析为地址。它可以由 consul, etcd zookeeper, dns, gossip 等支持。服务应在启动时使用注册表进行注册, 并在关闭时解除注册。服务可以选择提供过期的 TTL 并在间隔内重新注册, 以确保服务在失效时进行清理。
6. selector
选择器是一个负载平衡抽象, 它建立在注册表上。它允许使用筛选器函数"筛选"服务, 并使用随机, 循环, 最小等算法选择服务. 客户在发出请求时利用选择器,通过查询注册表上注册的服务和它提供了内置的负载平衡机制,找到合适的用于接收请求的服务。
7. transport
传输是服务之间同步请求/响应通信的接口. 它类似于 golang 网络包, 但提供了一个更高级别的抽象, 允许我们切换通信机制, 例如 http, rabbitmq, websocket, NATS。传输还支持双向流。这对客户端推送到服务器功能非常强大。
五、应用实例
1. server端
通过调用micro包的NewService方法,创建service的对象,并在注册表中注册其名称,这样该服务的调用者便可以直接通过名称找到这个服务。然后初始化这个service并register handlers,这样client便可以通过server注册的名称以及其对应的函数名,实现跨服务的远程调用。往往可以通过外面包一层网关服务,以此实现支持http、grpc等的restful服务。
2. client端
同样的,客户端也是先需要将自己注册成一个micro service,然后便可以通过服务端的注册名称以及其函数名称,实现服务端函数的调用并返回响应结果。这里的响应内容的编码方式可以根据需要,定义为protocol,json等方式。