Go Micro(2)——微服务工具箱

微服务工具箱

现在你也许听到了这个新现象:微服务。如果你对此不熟悉也有兴趣学习,欢迎参考上一篇文章。

这篇文章我们将讨论 Micro - 一个开源的微服务工具箱,Micro 提供了核心的必须工具来构建和管理微服务。它包含了一系列由 golang 开发的库和工具,同时也通过 Sidecar 特性与其他语言兼容。

在我们开始了解 Micro 之前,我们讨论一下为什么我们要把时间花费在它上面。

开发与部署

从我们过去在软件工程领域的经验可以很清晰的看到,我们有这样一种需求:专注于开发而不是部署。PasS 的解决方案是可行的,类似 AWS,Google 和微软的公司,提供了功能丰富的平台,并快速的推进着容器技术(container)。所有的这些让我们点几下鼠标就能使用大规模计算服务。

新世界看着不错,你也许说这解决了你所有的问题,真的是这样吗?当我们能接触到大规模计算的能力时,仍然缺少工具来让我们发挥出大规模计算的优势。不仅如此,在这个新世界中,容器的生命周期变得更加短暂,在运行时调度中不断创建和销毁。

规模的挑战

另一个问题是,正如我们一次又一次看到的,我们一直是巨型架构的受害者。随着功能需求的增加,现在的趋势是在巨型系统上不断增加功能,直到不断增加的技术债务让我们回天乏术。除此以外,随着组织不断扩张工程师团队,开发者想要单独的进行代码开发,或者开发功能时不被其他人 block,变得极其困难。

这是一种难以避免的需求:重新进行架构设计,使用 SOA 或者微服务架构。公司需要在研发上投入努力,在尝试和错误中学习。现在正需要这样一种工具来帮助我们构建可扩展系统,减少研发部门的阻碍,由在此领域有经验的人士为大家提供建议。

了解 Micro

Micro 中我们构建了一个微服务生态系统,包括用于开发的基本的工具、服务和解决方案。我们已经构建好了基础的工具,这个工具与整个项目同名,也叫 Micro,这一工具让我们更容易构建可扩展的架构,提供效率。

让我们更深入的挖掘 Micro 的特性。

Go Micro

Go Micro 是一个 golang 编写的用于构建微服务的插件化的 RPC 框架。它实现了服务创建、服务发现、服务间通信需要的功能需求。任何优秀的微服务架构都需要解决这三个基础问题:服务发现、同步通信和异步通信。

Go Micro 包括以下这些包和功能:

  • Registry:客户端的服务发现
  • Transport:同步通信
  • Broker:异步通信
  • Selector:节点过滤、负载均衡
  • Codec:消息编解码
  • Server:基于此库构建RPC服务端
  • Client:基于此库构建RPC客户端

Go Micro 跟其他工具最大的不同是它是插件化的架构,这让上面每个包的具体实现都可以切换出去。举个例子,默认的服务发现的机制是通过 Consul,但是如果想切换成 etcd 或者 zookeeper 或者任何你实现的方案,都是非常便利的。官方实现的插件可以在这个地址看到:[github.com/micro/go-plugins]

插件化架构的最大好处是你可以选择你喜欢的平台来支撑微服务架构,但无需更改任何底层代码。Go Micro 无需任何更改,只需要 import 你的插件,直接使用即可。

Go Micro 是编写微服务的切入点,readme 提供了说明包括怎样编写、运行和查询一个服务。这个 greeter 示例可以参考:micro/examples/greeter ,更多的服务示例可以在这个工程看到: github.com/micro

Sidecar

Go Micro 提供了用 Golang 编写服务的方式,那么其他编程语言呢?我们怎样构建一个有兼容性的系统,让任何人都能受益于 Micro?虽然 Micro 是用 golang 编写的,我们提供了一个快速且方便的方式,让其他语言能够接入。

Sidecar 是一个轻量级的组装服务,概念上来说就是将 Micro 的库提供的功能,依附于其他语言的主程序中。Sidecar 本质上是一个单独运行的服务,通过 http 提供接口,其他语言通过接口使用 Go Micro 提供的功能。

Sidecar 的特性:

  • 在服务发现系统进行注册
  • 发现其他服务
  • 与主程序进行健康检查
  • 作为代理与 RPC 系统通信
  • 通过 websocket 订阅

[图片上传失败...(image-e9608-1513045777103)]

rubypython 借助Sidecar 进行使用的例子可以在这里看到 micro/examples/greeter,我们会提供更多示例,帮助理解 Sidecar 的使用。


API

服务之间请求调用是非常简单直接的,但外部调用就要复杂一些。具体的服务实例可能会崩溃,重新调度,并监听随机的端口。API 这个组件提供了一个接入点,外部的服务可以通过这个 API 网关向内部的服务发起请求。

API 提供了几种不同的请求方式

/rpc

每个单独的服务可以通过 /rpc 这个接入点进行访问,示例如下:

curl \
    -d "service=go.micro.srv.greeter" \
    -d "method=Say.Hello" \
    -d "request={\"name\": \"John\"}" \
    http://localhost:8080/rpc

{"msg":"Hello John"}

api.Request

API 也可以通过约定好的 URL 格式,请求到内部的服务,这是 API 服务的一个强大功能。经过 URL 解析能将路径转换成实际的请求,示例如下

请求

GET /greeter/say/hello?name=John

将会处理成

service: go.micro.api.greeter (default namespace go.micro.api is applied)
method: Say.Hello
request {
    "method": "GET",
    "path": "/greeter/say/hello",
    "get": {
        "name": "John"
    }
}

可以查看 protobuf 定义的这个接口实现:

// 内部定义的接口
syntax = "proto3";

message Pair {
    optional string key = 1;
    repeated string values = 2;
}

message Request {
    optional string method = 1;   // GET, POST, etc
    optional string path = 2;     // e.g /greeter/say/hello
    map<string, Pair> header = 3;
    map<string, Pair> get = 4;    // The URI query params
    map<string, Pair> post = 5;   // The post body params
    optional string body = 6;     // raw request body; if not application/x-www-form-urlencoded
}

message Response {
    optional int32 statusCode = 1;
    map<string, Pair> header = 2;
    optional string body = 3;
}

使用示例可以在这里看到:Greeter API

反向代理

最后一个 API 服务提供的功能是反向代理。正如上面例子中提到的,API 服务可以通过路径解析到具体的服务,通过添加参数 --api_handler=proxy 我们就可以支持 REST 风格的请求。反向代理只需要简单的在运行时添加 --api_handler=proxy 参数即可。

使用 API 构建 RESTful 风格的 API 可以在这个例子中看到:micro/examples/greeter/api


Web UI

web UI 提供了一个简单的界面观察运行中的系统,也可以进行一些交互。它提供了类似 API 这样的反向代理功能,我们的『web代理』也可以把开发好的其他 web 应用接入到 web UI 中,web UIAPI 一样仍然通过路径解析实现与内部服务的通信,通过 websocket 我们可以实时了解运行中系统的情况

[图片上传失败...(image-dac467-1513045777104)]


CLI

CLI 是一个命令行工具,让我们可以观察、交互和管理运行中的服务,当前的特性允许你查询服务注册,检查服务的健康情况,也可以对服务进行请求

[图片上传失败...(image-995294-1513045777104)]

其他有意思的特性包括,CLI 可以使用 Sidecar 作为代理,只需要简单的设置参数:--proxy_address=example.proxy.com


组装在一起

我们已经写了一个全功能的示例,整体的执行过程是这样的:

  1. HTTP GET 请求到 API 服务,请求地址是:/greeter/say/hello with the query name=John
  2. API 服务将请求解析并转换成默认的服务形式,服务名是 go.micro.api.greeter,方法是 Say.Hello
  3. API 使用 Go Micro,查询注册器中服务 go.micro.api.greeter 注册的所有节点,根据负载均衡算法,选择其中一个节点,发出请求
  4. go.micro.api.greeter 服务收到请求,解析到结构体,去注册器查询到 go.micro.srv.greeter 这个服务,发送请求
  5. go.micro.srv.greeter 服务处理完成后,返回相应的内容到 go.micro.api.greeter
  6. go.micro.api.greeter 转换 go.micro.srv.greeter 服务的响应内容到 api.Response,返回到 API 服务
  7. API 服务解析请求,返回 HTTP 请求

整体流程如下:

[图片上传失败...(image-c77079-1513045777104)]

有更复杂的例子,比如 API 服务请求多个服务,组装多个服务的返回内容。示例如下:greeter service

总结一下就是: HTTP 请求发送到 Micro Api 服务,然后请求被解析到具体微服务的 api 服务,具体微服务的 api 服务再去请求对应的干活服务。

注意 Micro Api 并不需要我们去实现,是 Micro 自带的。

Demo

如果你想看看正在运行中的系统,在这个页面查看:web.micro.pm

我们运行了一个 MicroKubernetes 上,demo 是开源的,可以运行一下:github.com/micro/kubernetes

总结

Micro 提供了基础的工具用于编写和管理微服务,Go Micro 包括了核心的必须功能:服务发现、客户端、服务端和订阅、发布。CLI 可以让你与运行中的服务进行交互。Sidecar 可以让你接入其他非 Micro 应用。API 是一个单独的接入点来调用内部的服务。借助于插件化的接口,你可以灵活选择各种组件来提升你的微服务。

推荐阅读更多精彩内容